Wrap a call in a task, to add a timeout? - async-await

We have an SDK that we are using from a 3rd-party. We have no access or insight into the code at all, or ability to change anything with it.
We're running into a problem where we make a bunch of updates to an object in the SDK, and then when we call their .Commit() method, it goes off into oblivion, and never comes back. Their Commit has no timeout parameter or anything to tell it - hey, give up already.
So when their code goes into oblivion, so too does our program.
I'm wondering if there is a way that I can use async/await stuff to essentially add a timeout to the call to their Commit. I've not done any of async stuff before though, so I'm not sure this is possible. I would still need it to be synchronous in terms of our program's process flow.
Essentially, I'm envisioning something along the lines of
... <setting a bunch of sdkObject fields> ...
var done = false;
await new Task(function(ref sdkObject, ref done) {
sdkObject.Commit();
done = true;
}, timeout: 60000);
if (done) {
<perform post-success code>
} else {
<perform post-failure code>
}
This then would allow us to artificially put a timeout around their Commit method, so that even if it goes off into oblivion, never to be seen again, our code would at least be able to try to wrap up gracefully and continue on with the next record to process.

I'm wondering if there is a way that I can use async/await stuff to essentially add a timeout to the call to their Commit.
Well... sort of.
You can wrap the call into a Task.Run and then use WaitAsync to create a cancelable wait, as such:
try {
await Task.Run(() => sdkObject.Commit()).WaitAsync(TimeSpan.FromSeconds(60));
<perform post-success code>
} catch (TimeoutException {
<perform post-failure code>
}
However, this will probably not work as expected. WaitAsync gives you a way to cancel the wait - it doesn't give you a way to cancel Commit. The Commit will just keep on executing - it's just that your application no longer cares if or when or how it complete.
The library you're using may or may not like having another Commit called when the last one is still running. So this may not actually work for your use case.
The only way to truly cancel uncancelable code is to wrap the code into a separate process and kill the process when you want to force cancellation. This is quite involved but sometimes you have no choice.

Related

FireAndForget call to WebApi from Azure Function

I want to be able to call an HTTP endpoint (that I own) from an Azure Function at the end of the Azure Function request.
I do not need to know the result of the request
If there is a problem in the HTTP endpoint that is called I will log it there
I do not want to hold up the return to the client calling the initial Azure Function
Offloading the call of the secondary WebApi onto a background job queue is considered overkill for this requirement
Do I simply call HttpClient.PutAsync without an await?
I realise that the dependencies I have used up until the point that the call is made may well not be available when the call returns. Is there a safe way to check if they are?
My answer may cause some controversy but, you can always start a background task and execute it that way.
For anyone reading this answer, this is far from recommended. The OP has been very clear that they don't care about exceptions or understanding what sort of result the request is returning ...
Task.Run(async () =>
{
using (var httpClient = new HttpClient())
{
await httpClient.PutAsync(...);
}
});
If you want to ensure that the call has fired, it may be worth waiting for a second or two after the call is made to ensure it's actually on it's way.
await Task.Delay(1000);
If you're worried about dependencies in the call, be sure to construct your payload (i.e. serialise it, etc.) external to the Task.Run, basically, minimise any work the background task does.

Why am I not allowed to break a Promise?

The following simple Promise is vowed and I am not allowed to break it.
my $my_promise = start {
loop {} # or sleep x;
'promise response'
}
say 'status : ', $my_promise.status; # status : Planned
$my_promise.break('promise broke'); # Access denied to keep/break this Promise; already vowed
# in block <unit> at xxx line xxx
Why is that?
Because the Promise is vowed, you cannot change it: only something that actually has the vow, can break the Promise. That is the intent of the vow functionality.
What are you trying to achieve by breaking the promise as you showed? Is it to stop the work being done inside of the start block? Breaking the Promise would not do that. And the vow mechanism was explicitly added to prevent you from thinking it can somehow stop the work inside a start block.
If you want work inside a start block to be interruptible, you will need to add some kind of semaphore that is regularly checked, for instance:
my int $running = 1;
my $my_promise = start {
while $running {
# do stuff
}
$running
}
# do other stuff
$running = 0;
await $my_promise;
Hope this made sense.
The reason why you cannot directly keep/break Promise from outside or stop it on Thread Pool are explained here in Jonathans comment.
Common misuse of Promises comes from timeout pattern.
await Promise.anyof(
start { sleep 4; say "finished"; },
Promise.in( 1 )
);
say "moving on...";
sleep;
This will print "finished". And when user realize that the next logical step for him is to try to kill obsolete Promise. While the only correct way to solve it is to make Promise aware that its work is no longer needed. For example through periodically checking some shared variable.
Things gets complicated if you have blocking code on Promise (for example database query) that runs for too long and you want to terminate it from main thread. That is not doable on Promises. All you can do is to ensure Promise will run in finite time (for example on MySQL by setting MAX_EXECUTION_TIME before running query). And then you have choice:
You can grind your teeth and patiently wait for Promise to finish. For example if you really must disconnect database in main thread.
Or you can move on immediately and allow "abandoned" Promise to finish on its own, without ever receiving its result. In this case you should control how many of those Promises can stack up in background by using Semaphore or running them on dedicated ThreadPoolScheduler.

Possible to use Promise.in with infinite time?

Is there a direct way to use Promise.in (or other sub/method/class) to achieve an indefinite amount of time? In other words the Promise is never resolved.
Currently I'm checking the $time when the promise is kept to see if an indefinite time was requested (indicated by negative or 0 value) and preventing the react block from exiting.
Is isn't a terrible solution, but is there are more idiomatic way of achieving this?
my $time=0;
react {
whenever Promise.in($time) {
#check if time is 0
done if $time > 0;
}
whenever signal(SIGINT) {
done;
}
#whenever Supply...{
#}
}
You can actually pass Inf to Promise.in, like this:
await Promise.in(Inf);
say "never happens";
whenever Promise.new {
pretty much gives you a promise that will never be kept, so the associated code will never fire. Not sure why you would do that, though.
If you want a promise that is never fulfilled, simply running Promise.new gives you one.
Somebody could still call .keep on that promise, unless you obtain a vow to prevent that.

Synchronous XMLHttpRequest deprecated

Today, I had to restart my browser due to some issue with an extension. What I found when I restarted it, was that my browser (Chromium) automatically updated to a new version that doesn't allow synchronous AJAX-requests anymore. Quote:
Synchronous XMLHttpRequest on the main thread is deprecated because of
its detrimental effects to the end user's experience. For more help,
check http://xhr.spec.whatwg.org/.
I need synchronous AJAX-requests for my node.js applications to work though, as they store and load data from disk through a server utilizing fopen. I found this to be a very simplistic and effective way of doing things, very handy in the creation of little hobby projects and editors... Is there a way to re-enable synchronous XMLHttpRequests in Chrome/Chromium?
This answer has been edited.
Short answer:
They don't want sync on the main thread.
The solution is simple for new browsers that support threads/web workers:
var foo = new Worker("scriptWithSyncRequests.js")
Neither DOM nor global vairables aren't going to be visible within a worker but encapsulation of multiple synchronous requests is going to be really easy.
Alternative solution is to switch to async but to use browser localStorage along with JSON.stringify as a medium. You might be able to mock localStorage if you allowed to do some IO.
http://caniuse.com/#search=localstorage
Just for fun, there are alternative hacks if we want to restrict our self using only sync:
It is tempting to use setTimeout because one might think it is a good way to encapsulate synchronous requests together. Sadly, there is a gotcha. Async in javascript doesn't mean it gets to run in its own thread. Async is likely postponing the call, waiting for others to finish. Lucky for us there is light at the end of the tunnel because it is likely you can use xhttp.timeout along with xhttp.ontimeout to recover. See Timeout XMLHttpRequest
This means we can implement tiny version of a schedular that handles failed request and allocates time to try again or report error.
// The basic idea.
function runSchedular(s)
{
setTimeout(function() {
if (s.ptr < callQueue.length) {
// Handles rescheduling if needed by pushing the que.
// Remember to set time for xhttp.timeout.
// Use xhttp.ontimeout to set default return value for failure.
// The pushed function might do something like: (in pesudo)
// if !d1
// d1 = get(http...?query);
// if !d2
// d2 = get(http...?query);
// if (!d1) {pushQue tryAgainLater}
// if (!d2) {pushQue tryAgainLater}
// if (d1 && d2) {pushQue handleData}
s = s.callQueue[s.ptr++](s);
} else {
// Clear the que when there is nothing more to do.
s.ptr = 0;
s.callQueue = [];
// You could implement an idle counter and increase this value to free
// CPU time.
s.t = 200;
}
runSchedular(s);
}, s.t);
}
Doesn't "deprecated" mean that it's available, but won't be forever. (I read elsewhere that it won't be going away for a number of years.) If so, and this is for hobby projects, then perhaps you could use async: false for now as a quick way to get the job done?

Does Labjs postpone the execution of the loaded scripts til the DOM is ready?

The question is regarding the http://labjs.com – an awesome library for non-blocking JavaScript loading and dependencies managing.
I've read the docs, but I must be too tired or something – I couldn't find anything regarding DOM ready event. Are the scripts executed after the DOM's ready or not?
Perhaps if I do:
$LAB.script('my-library.js').wait(function(){
// interacting with DOM
});
Will it be safe? Or should I use some kind of $(function() {}) etc.?
Any script loader, by default, acts to unblock script loading from the page's DOM-ready and onload events, at least by intent/definition.
So, the straightforward answer is, NO, LABjs will not block script execution until DOM-ready. Some scripts loaded by LABjs may run before DOM-ready, while others may run after DOM-ready.
If you truly have cases where your code needs to wait for the DOM, you should use a framework like jQuery and use its built-in DOM-ready wrapper $(document).ready(...) to make that logic DOM-ready-safe.
However, there are many cases where people think they need to wait for DOM-ready, when they really don't:
Most people conflate DOM-ready with "all scripts are done loading". If you are simply waiting for DOM-ready because you need to ensure that all your scripts have loaded, this is a mistaken and incorrect assumption to be making. Instead, use the facility of your script loader to determine when all scripts are loaded, and run them at the appropriate time, regardless of the DOM loading. With LABjs, this is as simple as having all your scripts in a single $LAB chain, and having a final .wait() at the end of the chain -- you can be assured that your code in that .wait() callback will not run until all the scripts have loaded and run.
Most people think they need to wait for DOM-ready to do things like attaching event handlers, or firing off Ajax requests. This is also an incorrect assumption. If your code simply queries the DOM for elements to attach event handlers to, or if you are doing nothing with the DOM at all, but are instead making Ajax calls, don't wrap your logic in a DOM-ready wrapper.
On the flip side, many people assume that if your code runs at the end of the body tag, then you don't need to wait for DOM-ready. Wrong. DOM-ready is DOM-ready, regardless where your code is specified.
In general, the only time your code really needs to be wrapped in a DOM-ready wrapper is if it is going to modify the DOM. Otherwise, don't wait for DOM-ready to run your code. Be smart about what is wrapped and what isn't.
How about using jQuery's awesome Deferred object?
This works like a charm:
var waitThenLaunch = function() {
var deferredDocReady = $.Deferred();
$(document).ready(function() {
deferredDocReady.resolve();
});
var deferredScriptsReady = $.Deferred();
// Load your last remaining scripts and launch!!!
$LAB.script('last.js').wait(function(){ deferredScriptsReady.resolve(); });
$.when(deferredDocReady, deferredScriptsReady).done(function() { launchApp(); });
};
$LAB.script('jquery.min.js')
.script('another_script.js')
.script('another_script.js').wait()
.script('another_script.js')
.script('another_script.js').wait(function(){ waitThenLaunch(); });
Find an excellent explanation here: http://www.erichynds.com/jquery/using-deferreds-in-jquery/

Resources