My messages are delivered out of flow sequence order and how do I compensate? - json

I wish to use Twilio in the context of an adventure game. As the gamer (Geocacher) progresses on an actual treasure (cache) hunt, clues are given by text when certain code words or numbers are entered as part of the thread. I am very comfortable creating the flow in Studio and have a working flow that is debugged and ready to go.
Not so fast, grasshopper! Strange things started to happen when beta testing the flow. Basically texts that show as being sent arrive to the user out of sequence in the thread. The SM logs show everything is working correctly (message sent) but, what I call Zombie messages arrive to the user after a previous message has arrived. The Zombies are legitimate messages from the Flow but out of the correct sequence and that makes the thread unusable for my purposes.
I learned too late in my "programming" that Twilio states, "If you send multiple SMS messages to the same user in a short time, Twilio cannot guarantee that those messages will arrive in the order that you sent them." Ugh!
So , I started with the Help Techs at Twillio and one solution is to create a subflow that basically is inserted after a Send Message Widget. This sub flow basically Fetches the message via the SMS SID to check for SMS status. If status is "delivered", we can safely say the message has been received by the recipient and then permit the next message in the flow.
That sound great but I am not a programmer and will never be able to integrate the suggested code much less debug it when things don't work. There might be many other approaches that you guys can suggest. The task is 1.) Send a message, 2.) Run a subflow that checks for message delivery, 3.) send the next message in the sequence.
I need to move on to implementation and this type of sub flow is out of my wheelhouse. I am willing to pay for programming help.
I can post the JSON code that was created as a straw man but have no idea how to use it and if it is the optimum solution if that is of help. It would seem that a lot of folks experience this issue and would like a solution. A nice tight JSON subflow with directions on how to insert would seem to be a necessary part of the Widget toolkit provided by Twillio in Studio.
Please Help Me! =)

As you stated, the delivery of the message cannot be guaranteed. Checking the status of the sent message is the most reliable, using a subflow, a Twilio Function, or a combination. Just keep in mind that Twilio Functions have a 10s execution time limit. I don't expect delivering the SMS will take longer than 10s is most cases. If you're worried about edge cases, you'd have to loop the check for the status multiple times. I'll share a proof of concept later for this.
An easier way, but it still doesn't guarantee delivery order, would be to add some delay between each message. There's no built-in delay widget, but here's code on how to create a Twilio Function to add delays, up to 10s.
A more hacky way to implement delays without having to use this Twilio Function, is to use the Send & Wait For Reply Widget and configure the "Stop Gathering After" property to the amount of delay you'd like to add. If the user responds, connect to the next widget, if they don't also connect to the widget.
As mentioned earlier, here's th Subflow + Function proof of concept I hacked together:
First, create a Twilio Functions Service, in the service create two functions:
/delay:
// Helper function for quickly adding await-able "pauses" to JavaScript
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
exports.handler = async (context, event, callback) => {
// A custom delay value could be passed to the Function, either via
// request parameters or by the Run Function Widget
// Default to a 5 second delay
const delay = event.delay || 5000;
// Pause Function for the specified number of ms
await sleep(delay);
// Once the delay has passed, return a success message, TwiML, or
// any other content to whatever invoked this Function.
return callback(null, `Timer up: ${delay}ms`);
};
/get-message:
exports.handler = function(context, event, callback) {
const messageSid = event.message_sid,
client = context.getTwilioClient();
if(!event.message_sid) throw "message_sid parameter is required.";
client.messages(messageSid)
.fetch()
.then(message => callback(null, message))
.catch((error) => {
console.error(error);
return callback(error);
});
};
Then, create a Studio Flow named something like "Send and Wait until Delivered".
In this flow, you send the message, grabbing the message body passed in from the parent flow, {{trigger.parent.parameters.message_body}}.
Then, you run the /get-message Function, and check the message status.
If delivered, set status variable to delivered. This variable will be passed back to the parent flow. If any of these accepted,queued,sending,sent, then the message is still in route, so wait a second using the /delay function, then loop back to the /get-message function.
If any other status, it is assumed there's something wrong and status is set to error.
Now you can create your parent flow where you call the subflow, specifying the message_body parameter. Then you can check the status variable for the subflow, whether it is 'delivered' or 'error'.
You can find the export for the subflow and the parent flow in this GitHub Gist. You can import it and it could be useful as a reference.
Personally, I'd add the /delay function, and use that after every message, adding a couple of seconds delay. I'd personally assume the delay adds enough buffer for no zombie messages to appear.
Note: The code, proof of concept, and advice is offered as is without liability to me or Twilio. It is not tested against a production workload, so make sure you test this thoroughly for your use case!

Related

Handling intensive server-side tasks? Do I still use async/await in the front-end?

How do I handle really intensive server-side tasks, that can take multiple minutes? It's a user-facing task, so the user can give me some data, and the server will then work in the backend.
I am fairly new to this, but I think my browser won't "wait" for this long, if I am using async/await ? But then if I don't use async await, I won't know whether the task was completed successfully?
Or am I missing something here?
The bigger the task, the more brittle is a solution that depends on a single HTTP request/response. Imagine that the connection breaks after the task has been 99% completed. The client would have to repeat the whole thing.
Instead, I suggest a pattern like the following that depends on several HTTP requests:
The client (browser) makes a request like POST /starttask to start the task and receives a "task ID" in the response.
The task runs on the server while the client can do other things. Any results that the task computes are stored in a database under the task ID.
The client can check the task progress by making regular requests like GET /task/<taskID> and receive a progress notification (50% completed). This can be used to animate a "progress bar" on the UI.
When the task is 100% completed and has yielded a result that the client needs to know, it can retrieve that result with a request like GET /taskresult/<taskID>.
If the task result is huge, the client may want to repeat the result retrieval, perhaps with paging (GET /taskresult/<taskID>?page=1 and so on) until it has received and processed the entire result. This should not burden the server much, because it simply reads the task result from the database.
Finally, the client can delete the task result from the server database with another request like POST /taskcleanup/<taskID>.
Using await / async will work as this will wait forever until a promise (request to backend) has been fulfilled. You could show some kind of loading graphic to the user which is how other websites handle lengthy tasks.
Depends how big the task is, but an example if the task is fairly small (eg 10 seconds) we could use a 'loading' state as the way to identify if we should display loading graphic:
function example() {
setLoading(true);
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
Axios Minimal Example
I think it would be bad to keep the connection open waiting for the response for couple of minutes.
Instead, I would recommend SignalR server side notifications (or equivalent) to notify front end about tasks updates.
Notification DTO would contain all needed information about the task.
Backend:
// Post method
void startTask(params) {
// start backend processing
// after completion notify
signalRHub.notify();
}
On front end you just need subscribe to notifications and add handlers for them.

In angular 2+ (Component => Service A => ServiceB), need help to understand the flow

In angular 2+, I have a component A which calls service A where i make some changes and call service B (Http Calls) and get the data which is simply passed back to service A, now i need to subscribe into service A to see the data and also subscribe into Component A to display data there?
why i need to subscribe at 2 places which means its making the http calls twice (which is not good at all)
what is the best way where I can fetch and store data in Service A by subscribing and do all manipulation and simply send that object back to component A to display it? even I try to make a variable in subscribing section in service A but when I try to log that variable outside the subscribe block. it is undefined.
thanks for the help.
while searching for the answer, I found one way (or can called worked around) that is to use "async-await" feature in angular with HttpClient.
which will basically wait at the same line of execution till you get result (success or error). and then proceed further with next line of execution.
for example:
async myFunction() {
this.myResult = await this.httpClient.get(this.url).toPromise();
console.log('No issues, it will wait till myResult is populated.');
}
Explanation:
adding async in front of the function to let it know that execution need to wait and the desire place (mostly at http service call as I need to wait till I get the result) we put await. so execution will go under wait period till it get the response back. and later. simply return the variable.

google.script.run is NOT running every time it is called. Some times the function runs, other times it does nothing

In Google apps script when using a client sided .HTML file you can call a server sided script using google.script.run.(Function name).
You can see the related documentation here: https://developers.google.com/apps-script/guides/html/reference/run
Now this script has been working with no problems over the first 6 months of its lifetime or so. I have not touched the program and I have not been notified or have located any newly deprecated code.
Over the course of the last couple months however, my users have been reporting that when they finish interacting with the HTML document, nothing happens when they close it and they have to repeat the entire process 3 or sometimes even 4 times before they will get it to go through.,
This means that when the user closes the client sided HTML window, the server sided function should be called to handle the remaining tasks but in some cases is not. This issue is completely random, and does not seem to be caused by anything specific.
I have taken some steps myself to attempt to solve the issue. I have wrapped the entirety of the code in try catch blocks, including the .HTML and .GS files. This means that if literally ANYTHING goes wrong in ANY script, I will be notified of it immediately. However, despite this being the case I am yet to receive any emails of it failing even though I watch it fail with my own eyes. I have added log commands before and after this function to see if it stops working all together or continues. In every case regardless of whether the function call is successful or not the log commands go through.
To me this can only mean that for some reason the function google.script.run is not working properly, and is failing to run the associated function, but is not returning an error message or stopping the script.
I am at an absolute loss since I have no error message, no reproducible steps, and no history of this being a problem before while suddenly starting to get worse and worse over time. I have checked Google's issue tracker to no results. If anyone else is using this function and is having problems I would love you to share your experiences here. If you have a solution please let me know as soon as possible. If I can't fix this issue I am going to have to use a new platform entirely.
Edit 10/2:
After looking further into this issue I have discovered a list of all executions on this project. I can see what functions were executed, when, and how long they took to execute. I can see that when the function that opens the HTML service is ran, the next function that should run does not always appear in the list. And when it doesn't, I can see that the user repeated their steps until it did run. This supports my theory that the function just isn't running when it should be after being called my script.run
Tl;dr: The affected computers are running so slowly that google.script.host.close would run before google.script.run.functionName() is able to be called and the information passed from the client to server, causing the function to never run but also not return an error. Adding Utilities.sleep(1000) fixes the issue.
I'm answering here in the situation that someone stumbles upon this thread in the future because they're having similar problems.
I was able to fix the issue by adding two lines of code between
google.script.run and google.script.host.close.
I added Google's Utilities.sleep(1000) to force the computer to wait one second between executing the function and closing the HTML window. I also added an HTML alert that shows that the function was called and didn't suffer from a runtime error.
I don't know exactly why this seems to have fixed the issue but I have a theory.
I have about 20 computers this spreadsheet runs on. Only about 6 of them were having the issue, and this wasn't brought to my attention until recently. As it turns out the 6 computers that were having the issue were the slowest computers of the bunch.
My theory is that the computers were so slow, and the internet bandwidth was fluctuating so much that the computer simply didn't have time to call google.script.run and pass off the information from the client sided HTML window that it simply got closed and cut off when google.script.host.close was run. This means that the function will not exist in the execution transcripts or history, nor will there be any sort of runtime error. All of those things were true in my situation. This also explains why I never had the issue on any of my own equipment in a testing environment since it didn't suffer from any slowdowns the other computers were having.
By adding both Utilities.sleep(1000) and the UI alert this forces the javascript to not continue to google.script.host.close until the user interacts with the UI alert (Which is just a confirmation window with an OK button) and afterwards waits a full second. This sacrifices a tiny bit of user friendly-ness for a more functional script. Since I have implemented this "fix" none of my users are reporting any issues and all of my execution history looks just fine.
Hopefully this helps any future passerbys.
In the comments you posted this function snippet:
Here is a basic copy of the script that utilizes google.script.run:
function onFailure(error) {
MailApp.sendEmail("sparkycbass#gmail.com", "Order book eror", "ERROR: " + error.message);
google.script.host.close();
}
function handleFormSubmit(formObject) {
google.script.run.withFailureHandler(onFailure).processForm(formObject)
google.script.host.close();
}
The problem here is that google.script.run is asynchronous - the call to your server-side function processForm is not guaranteed to be even initiated before the call to google.script.host.close() is made:
Client-side calls to server-side functions are asynchronous: after the browser requests that the server run the function doSomething(), the browser continues immediately to the next line of code without waiting for a response. This means that server function calls may not execute in the order you expect. If you make two function calls at the same time, there is no way to know which function will run first; the result may differ each time you load the page. In this situation, success handlers and failure handlers help control the flow of your code.
A proper pattern is to only call "destructive" commands - such as closing the host and therefore unloading all the relevant Apps Script instances - after the server has indicated the async operation completed. This is within the success handler of the google.script.run call:
.html
function onFailure(error) { // server function threw an unhandled exception
google.script.run.sendMeAnEmail("Order book error", "ERROR: " + error.message);
console.log(error);
document.getElementById("some element id").textContent = "There was an error processing that form. Perhaps try again?"
}
function onSuccess(serverFunctionOutput, userObj) {
// do stuff with `serverFunctionOutput` and `userObj`
// ...
google.script.host.close();
}
function handleFormSubmit(formObject) {
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(onSuccess)
.processForm(formObject);
}
.gs
function processForm(formData) {
console.log({message: "Processing form data", input: formData});
// ...
}
function sendMeAnEmail(subject, message) {
console.log({message: "There was a boo-boo", email: {message: message, subject: subject}});
MailApp.sendEmail("some email", subject, message);
}

How should I perform an asynchronous action within an accessor?

I have a simple accessor in my class:
public function get loggedIn():Boolean
{
var loggedIn:Boolean = somePrivateMethodToCheckStatus();
return loggedIn;
}
The API I'm now working with checks login status in an asynchronous fashion:
API_Class.addEventListener(API_Class.LOGIN_STATUS,onStatusCheck);
API_Class.checkLoginStatus();
function onStatusCheck(evt:API_Event):void
{
//evt.loggedIn == true or false
}
Is there a way I can perform this asynchronous request without exiting my accessor?
Simple answer: No, there is not. You will have to set up login verification in an asynchronous fashion.
I am a bit curious: Why is there a need to repeatedly poll the login status remotely? If your user logged in from within the Flash application, the status should be known. Same goes for logging out. If login and logout is handled from outside the Flash app, why not implement a notification mechanism (via JavaScript or socket connection)?
Also, if not being logged in prevents users from performing actions on the server, you could check for authorization on the server, whenever remote calls are made, and return an error if the session has expired. This would still be more efficient than repeatedly polling status info.
Not really, no. Flash runs in a single thread, and every function has to finish before events etc will be called.
One (sort of) solution would be to return three values; "yes", "no" and "pending". If it's pending the loggedIn()-method would start a check, and the client of that method should check again in a little while.
Another way would be to have the loggedIn-method send the answer to a callback instead. Eg "getLoggedInStatus(callback:Function)"
You may be interested in http://www.as3commons.org/as3-commons-eventbus/index.html
It is a handy lib that focuses on asynchronous jobs.

AJAX call in a continuous loop?

I want to create some kind of AJAX script or call that continuously will check a MySQL database if any new messages has arrived. When there is a new message in the database, the AJAX script should invoke a kind of alert box or message box.
I’m not quite a AJAX expert (yet anyway) and have Googled around to find a solution but I’m having a hard time to figure out where to begin. I imagine that it is kind of the same method that an AJAX chat is using to see if any new chat-message has been send.
I’ve also tried to search for AJAX (httpxmlrequest) call in a continuously and infinity loop but still haven’t got a solution yet.
I hope there is someone, which can help me with such a AJAX script or maybe nudge me in the right direction.
Thanks
Sincerely
Mestika
Step 1 - You need a server-side page that you can call that checks to see if something new has arrived.
Step 2 - You could adapt the sequential AJAX request script from here (it uses jQuery to simplify the AJAX requests):
http://www.stevefenton.co.uk/Content/Blog/Date/201004/Blog/AJAX-and-Race-Conditions/
Currently, this script is for queuing a list of sequential AJAX requests, but you could use it to continually check by changing it like this...
var InfiniteAjaxRequest = function (uri) {
$.ajax({
url: uri,
success: function(data) {
// do something with "data"
if (data.length > 0) {
alert(data);// Do something sensible with it!
}
InfiniteAjaxRequest (uri);
},
error: function(xhr, ajaxOptions, thrownError) {
alert(thrownError);
}
});
};
InfiniteAjaxRequest ("CheckForUpdate.php");
What are the benefits of using this script?
Well, rather than checking every "x" seconds, it will only check once the previous request has been received, so it chains the requests. You could add in a delay to throttle this constant request, which I would highly recommend you do - otherwise you will be hitting your site with way too much traffic. You would add that delay in AFTER you've done something with the response, but BEFORE you call back into "InfiniteAjaxRequest".
Here's your nudge:
Get one of the available JavaScript frameworks (jQuery seems to be the most common, but there are others)
flip though the documentation on the AJAX methods it provides, choose a method for your task that seems appropriate
build a request to your site that fetches the info and reacts on the response (shows a message box or updates some part of your page), wrap that in a function
make sure request errors do not go unnoticed by implementing an error handler
check out setInterval() to call that function you've just made repeatedly
final step: make sure that the interval will be stopped in case of an error condition (or provide a on/off button for the user, even) so the server is not hammered needlessly
There is a technique called Comet where-by your client-side script would instantiate a HTTP request which remains open for a long time. The server can then push data into the response as they happen. It's a technique to deliver a push notification.
The Wikipedia link has more information on real-world implementations.
Instead of polling the server with AJAX calls you could also use push technology (COMET).
This way you can push the results to the client(s) as soon as the server is done with it's work.
There are many frameworks available like:
JQuery plugin
Cometd
Atmosphere (if your on java)