How do i ensure that an async objectify API call like "delete" completed successfully? - objectify

How do i ensure that an async objectify API call like "delete" completed successfully?
So, will "ofy().delete" throw some exception if it does not complete successfully?

Call now().
ofy().delete().key(thing).now()
This will perform a synchronous delete operation. Otherwise the async operation will be completed at the end of the request (make sure you install the ObjectifyFilter) and you will get an exception (say, a timeout) then.

Related

Nullreference exception does not show up when async Task discarded

I have an async Task with a method signature defined like this:
public async Task<bool> HandleFooAsync()
When executing this task in an async way and discarding the results, exceptions happening in this task do not show up in our logs.
_ = _slackResponseService.HandleFooAsync();
When I await the execution of the task I see the error in our logs
var result = await _slackResponseService.HandleFooAsync();
Is this expected behaviour? Is there a way to achieve a solution in between: "do not wait for the result, but log errors nevertheless.." ? We invested hours debugging our logging setup, just to learn that our logging setup is correct, but discard means in dotnet that everything is discarded - even logs. Which is a quite a new perspective for us, coming from a Python background.
Our logging setup follows the default logging setup for dotnet core 3 https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1
Yes, it is an expected behavior. Call in that way can be considered like an anti-pattern. You can read about it C# Async Antipatterns
You need something which is called as "Fire and forget". One of its implementation can be find in repo AsyncAwaitBestPractices (nuget available too).
A Task in .net and netcore is meant to be awaited. If it is not awaited, the scope might be destroyed before the async method has finished.
If you want to run tasks in the background and not wait for a result you can use BackgroundService in .netcore or a third party such as Hangfire which supports fire and forget jobs out of the box
https://medium.com/#daniel.sagita/backgroundservice-for-a-long-running-work-3debe8f8d25b
https://www.hangfire.io/
One solution is to subscribe to the TaskScheduler.UnobservedTaskException event. It is not ideal because the event is raised when the faulted Task is garbage collected, which may happen long after the actual fault.
Another solution could be to use an extension method every time a task is fired and forgotten. Like this:
_slackResponseService.HandleFooAsync().FireAndForget();
Here is a basic implementation of the FireAndForget method:
public async static void FireAndForget(this Task task)
{
try
{
await task;
}
catch (Exception ex)
{
// log the exception here
}
}

WinRT assigning a token to asynchronous task

I wonder about the reason of assigning a token to an asynchronous task, as in the following example:
var ctSource = new CancellationTokenSource();
Task.Factory.StartNew(() => doSomething(), ctSource.Token);
The MSDN documentation insists on passing a token to the running method in addition to assigning it to task, but to me it appears as an unnatural duplication.
If a token is assigned to a task, does it mean, that ctSource.Cancel()automatically triggers TaskCancelledException for the task?
Is there a way to retrieve the assigned token from the task (other than by sending it as an argument) ?
If neither of those, what is the reason of assigning a token to a task?
If a token is assigned to a task, does it mean, that ctSource.Cancel()automatically triggers TaskCancelledException for the task?
The task could start anytime, now or later. So if it happens that the token has a cancellation request before that task has started, the scheduler itself will throw the OperationCanceledException, and your action () => doSomething() is never invoked. So, the token is being passed to the factory, not the task. This is used by the StartNew(...) method.
Is there a way to retrieve the assigned token from the task (other than by sending it as an argument) ?
No. Tasks do not know about CancellationToken, only the implementation. Tasks do not auto-cancel themselves. The function running within a task is responsible for exiting when a cancellation is requested.
You are the owner of the CancellationTokenSource. So pass it to whomever needs it.
Task.Factory.StartNew(() => doSomething(ctSource.Token), ctSource.Token);
If you are not the owner of doSomething() (from 3rd party DLL), then you cannot cancel that operation, unless it accepts a CancellationToken.

RxJava retry based on logic

Here is the case, I have an API call using Retrofit that might fail due to a network error. If it fails we will show an error message with a retry button. When the user presses the retry button we need to retry the latest Observable again.
Possible Solutions:
Retry: Retry should be used before subscribing to the observable and it will immediately resubscribe again if an error happens and that is what I don't want, I need to resubscribe only if the user pressed the Retry button.
RetryWhen: It Will keep trying as you emit items until you emit an Observable error then it will stop. Same issue here, I need to not start the retry process unless the user decides to.
Resubscribe to the same Observable: This solution will start emitting the Observable items, the problem with this is that we are using the cache operator, so if one Observable failed, we got the failed item cached and when we do subscribe again, we got the same error again.
Are there any other solutions to go with?
You can go with retryWhen, which parameter - Func1 - returns an Observable which indicates when a retry should happen. For example :
PublishSubject<Object> retryButtonClicked = PublishSubject.create();
Observable
.error(new RuntimeException())
.doOnError(throwable -> System.out.println("error"))
.retryWhen(observable -> observable.zipWith(retryButtonClicked, (o, o2) -> o))
.subscribe();
retryButtonClicked.onNext(new Object());
every time retryButtonClicked emmits an event, Observable will be retried
Here's also an example - https://gist.github.com/benjchristensen/3363d420607f03307dd0

What awaits the Task returned by an IHandleWithTask event handler

I've searched all over the CM source both version 1.5.2 and 2.0 and I cannot find anything that awaits the Task returned by an event Subscriber using the public Task IHandleWithTask signature. If nothing is awaiting the task, what is the point of returning a Task at all. Why not just use the public void IHandle signature?
John
It is awaited.
The bootsrapper or CaliburnApplication registers a handler to EventAggregator.HandlerResultProcessing. The task is not awaited but it is wrapped by a Coroutine and the Coroutine.Completed handler writes a log entry.

ASP.NET CacheDependency out of ThreadPool

In an async http handler, we add items to the ASP.NET cache, with dependencies on some files. If the async method executes on a thread from the ThreadPool, all is fine:
AsyncResult result = new AsyncResult(context, cb, extraData);
ThreadPool.QueueUserWorkItem(new WaitCallBack(DoProcessRequest), result);
But as soon as we try to execute on a thread out of the ThreadPool:
AsyncResult result = new AsyncResult(context, cb, extraData);
Runner runner = new Runner(result);
Thread thread = new Thread(new ThreadStart(runner.Run());
... where Runner.Run just invokes DoProcessRequest,
The dependencies do trigger right after the thread exits. I.e. the items are immediately removed from the cache, the reason being the dependencies.
We want to use an out-of-pool thread because the processing might take a long time.
So obviously something's missing when we create the thread. We might need to propagate the call context, the http context...
Has anybody already encountered that issue?
Note: off-the-shelf custom threadpools probably solve this. Writing our own threadpool is probably a bad idea (think NIH syndrom). Yet I'd like to understand this in details, though.
Could not figure out the details...
Found a workaround, though: in most IAsyncResult implementation, once the operation is completed there is a direct call to the callback. We replaced this, and now queue the callback into the ThreadPool. Hence, the callback executes within the ThreadPool and can register dependencies that last.

Resources