Scoped promises for cancellation - embed

Imagine the following code:
addEventListener("start", (user) => handler(user),);
async function handler(user) {
await fetch();
await fetch();
await fetch()
.then(x => fetch());
}
For this code I want to have carried timeout. I have a 15 seconds time out budget at start and each promise reduces this time and when we reach zero we just throw exception.
This is trivial to implement if we were handling an event at a time. But I need to handle multiple event concurrently.
I was wondering if there is a way to create a scope per event that contains a start time and when ever request is polled or finished we check if the timeout is reached and if so, we reject all promises in the scope and throw an exception.
NOTE: I'm using latest version of the embedded v8 and have access to native/cpp side

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.

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

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!

Using truffle, how to just get the tx hash of a submitted transaction and not wait for the receipt

I have a token contract that is already deployed, and I am calling the transfer function on the instance.
XYZContract.at(ADDRESS).then(instance => {
return instance.transfer(toAddress, amount);
}).then(result => {
console.log("transferTokens",result);
resolve(result);
})
Now my understanding is that the 'transfer' promise resolves only after the transaction is recorded into a block.
Is there a way to just get the transaction hash right after submission, but not wait for the receipt?
For e.g web3 has a sendTransaction that fires events when transaction is submitted, transaction receipt is obtained, etc.
In truffle documentation, it's mentioned to use instance.sendTransaction to only send ether
(https://truffleframework.com/docs/truffle/getting-started/interacting-with-your-contracts). So curious what is the right approach here
My end goal is, I want to run the transfer in a batch and would like to later check using the transaction hashes how many actually succeeded and also the number of confirmations.

Any workaround for Chrome M40 redirect bug for service workers?

We have images that redirect from our media server to a CDN that I'm trying to exclude from my service worker logic to work around the bug in Chrome 40. In Canary the same worker is able to work just fine. I thought there was an event.default() to fall back to the standard behavior but I don't see that in Chrome's implementation, and reading the spec it seems like the current recommendation is to just use fetch(event.request).
So the problem I have is do I have to wait until 99% of all of our users move to Chrome 41+ in order to use service workers in this scenario, or is there some sort of way I can opt out for certain requests?
The core of my logic is below:
worker.addEventListener('install', function(event){
event.waitUntil(getDefaultCache().then(function(cache){
return cache.addAll(precacheUrls);
}));
});
worker.addEventListener('fetch', function(event){
event.respondWith(getDefaultCache().then(function(cache){
return cache.match(event.request).then(function(response){
if (!response){
return fetch(event.request.clone()).then(function(response){
if (cacheablePatterns.some(function(pattern){
return pattern.test(event.request.url);
})) {
cache.put(event.request, response.clone());
}
return response;
});
}
return response;
});
}));
});
Once you're inside a event.respondWith() you do need to issue a response or you'll incur a Network Error. You're correct that event.default() isn't currently implemented.
A general solution is to not enter the event.respondWith() if you can determine synchronously that you don't want to handle the event. A basic example is something like:
function fetchHandler(event) {
if (event.request.url.indexOf('abc') >= 0) {
event.respondWith(abcResponseLogic);
} else if (event.request.url.indexOf('def') >= 0) {
event.respondWith(defResponseLogic);
}
}
self.addEventListener('fetch', fetchHandler);
If event.respondWith() isn't called, then this fetch handler is a no-op, and any additional registered fetch handlers get a shot at the request. Multiple fetch handlers are called in the order in which they're added via addEventListener, one at a time, until the first one calls event.respondWith().
If no fetch handlers call event.respondWith(), then the user agent makes the request exactly as it normally would if there were no service worker involvement.
The one tricky thing to take into account is that the determination as to whether to call event.respondWith() needs to be done synchronously inside each fetch handler. Anything that relies on asynchronous promise resolution can't be used to determine whether or not to call event.respondWith(). If you attempt to do something asynchronous and then call event.respondWith(), you'll end up with a race condition, and likely will see errors in the service worker console about how you can't respond to an event that was already handled.

nodejs and the non-blocking nightmare

I'm currently developing an API using node.js and MySQL. I'm new to this non-blocking stuff, and I have a question. I'm using node and MySQL module.
Say that we have a function like this:
function doQuery(sql, callback) {
connect(); //does the Client.connect()
client.query(sql, function(err, results, fields) {
if (err) {
errorLog.trace(err, __filename);
throw err;
} else {
logger.trace('DATABASE ACCESS: {query: ' + sql + '} result: OK', __filename);
}
client.end();
callback(results);
});
}
Everything runs ok, callback handles the return of the values, but there's something that bothers me. My browser what till the response is back and i don't know if this is because during this time node is actually blocked, or not.
So, how can I know if an operation is actually blocking my node process? I thought that when you pass a callback to a function, node automatically handles it and puts the execution of this callback at the queue of the event loop. But I'm not actually sure about that
Does all this make any sense to you?
There is a difference between the browser waiting and node.js blocking.
The browser has to wait because it can't get the data back instantly. The browser will stop waiting once you send the response back. Just because the browser is waiting doesn't mean that node.js is blocking. It just means that the connection is still open
Node.js idles whilst your waiting for the callback. it does not block.
node.js can have thousands of open connections with browsers clients. This does not mean it's blocking on each one. It simply means that is idling until it has a callback to handle or a new request to handle.