Trying to catch concurrent modification exception in Firestore in Datastore mode - google-cloud-datastore

I am trying to catch a concurrent modification exception in Firestore in Datastore mode with Objectify. I created a method and ran it 50 times in 1 second to try and catch the exception. I found that I can only catch the exception if I use a transaction.
Is there a way to catch the CME without a transaction?
This does not catch the exception when ran 50 times in 1 second (even though I can see in the logs the entity is not always updated due to the 1/sec write limit):
try {
Entity entity = ofy().load().type(Entity.class)
.filter("username", "username1")
.first()
.now();
entity.setName("username2")
ofy().save().entity(newEntity).now();
} catch (com.google.cloud.datastore.DatastoreException datastoreException) {
// Never catches anything
} catch (Exception e) {
// Never catches anything
}
This catches the exception when ran 50 times in 1 second:
try {
ofy().transact(new VoidWork() {
public void vrun() {
Entity entity = ofy().load().type(Entity.class)
.filter("username", "username1")
.first()
.now();
entity.setName("username2")
ofy().save().entity(newEntity).now();
}
}
});
} catch (com.google.cloud.datastore.DatastoreException datastoreException) {
// Catches this error: Aborted due to cross-transaction contention. This occurs when multiple transactions attempt to access the same data, requiring Firestore to abort at least one in order to enforce serializability.
} catch (Exception e) {
}

Without a transaction the write is concerned a blind write. A blind write writes the content of the write even if another write has happened between your read & your write.
You should not expect a concurrent modification exception without a transaction.

Related

Configure Windows Service to restart on both graceful AND ungraceful shutdown

I am aware of the Recovery section of the Service control, and how we can set an app to restart after failure.
I have created a .NET 6 worker service to run as a windows service. The problem is that whenever there is an exception in the code, the app logs the error but then shuts down gracefully. This does not signal to windows that the service should be restarted since it returns an exit code of 0.
I've tried returning an exit code of -1 (by setting Environment.ExitCode and returning -1 from Main()) but it's ignored.
I've also tried setting the exit code of the underlying WindowsServiceLifetime and that also does not work.
Are there any ways to have the SCM restart the service no matter how it shut down?
Exceptions should not bring down the host. Exceptions do not bring down IIS and they should not bring down a Windows Service.
You should put try/catch where work begins – every endpoint and background service. In the catch you should log the error.
Here is an endpoint example:
[Route("Get")]
[HttpGet]
public async Task<IActionResult> GetAsync()
{
try
{
return Ok(await BusinessRules.GetSomethingAsync());
}
catch (Exception e)
{
_logger.LogError(e, e.Message);
throw;
}
}
Here is a background service example:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
//Need a try/catch round Task.Delay because exception will the thrown
//if stoppingToken is activated and we don't care about logging this exception.
try
{
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
catch { }
await BusinessRules.DoSomethingAsync(stoppingToken);
}
catch (Exception e)
{
_logger.LogError(e, e.Message);
//In a loop, log file can fill up quickly unless we slow it down after error.
try
{
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
}
catch { }
}
}
}

How to make mono timeout works

I'm first to use webflux in my project, just want to set timeout in case of long period handle.
#GetMapping("/{id}")
private Mono<ResponseEntity<String>> getEmployeeById(#PathVariable
String id) {
return Mono.just(id).map(updateTweet -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new ResponseEntity<>(updateTweet, HttpStatus.OK);
}).timeout(Duration.ofSeconds(3)).onErrorReturn(new ResponseEntity<>("0000", HttpStatus.OK));
}
expect:in 3 seconds later, this function will return.
actual results: in 10 seconds later, this function returned.
In your code the .map and .timeout are all in subscription thread. The .sleep(10) causes the currently executing thread to sleep (temporarily cease execution) for the 10s. So when 3s timeout the thread can't execute.
You should use publishOn shifts .map to scheduler thread.
#GetMapping("/{id}")
private Mono<ResponseEntity<String>> getEmployeeById(#PathVariable
String id) {
Scheduler singleThread = Schedulers.single();
return Mono.just(id).publishOn(singleThread).map(updateTweet -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new ResponseEntity<>(updateTweet, HttpStatus.OK);
}).timeout(Duration.ofSeconds(3)).onErrorReturn(new ResponseEntity<>("0000", HttpStatus.OK));
}
What TimeUnit.SECONDS.sleep(10) does is invoke Thread.sleep(). This puts the current
Thread into sleep mode for 10 seconds.
Since you are doing this inside a map, the Thread that goes to sleep is the current thread. The code that waits for a timeOut is also on the current thread and so doesn't come into effect until the sleep times out. For this reason, you should avoid performing any Thread related operations when doing reactive programming.
If you want to simulate a long running process in the above code, you could either invoke an external API that you control that waits more than 3 seconds before sending a response, or use one of the delay* operators.

Exception not caught using Task from Task.Factory.FromAsync()

I have a task created as follows.
var task = Task.Factory.FromAsync<Request, Response>(
service.BeginOp,
service.EndOp,
request,
null);
When I await the task in a try/catch, the exception is not caught.
try
{
await task;
}
catch (Exception e)
{
// Block never reached
}
However when I use ContinueWith(), the exception is caught.
await task.ContinueWith(t =>
{
if (t.Exception != null)
{
// Block reached
}
});
Why is it not caught in the first case? I have try/caught other Tasks and it catches the exception.
I suspect that further up your call stack, your code is calling Task<T>.Result or Task.Wait. This will cause a deadlock, as I explain on my blog.
By default, await will capture a "context" whenever it awaits a Task. In this case, the "context" is the ASP.NET request context, which only allows one thread in at a time. If your code blocks a thread within that request context (e.g., by calling Result/Wait), then when the task completes, it cannot resume executing the async method because the context only allows one thread in.
Turns out that in the above callstack I was not using await. I am not sure why the compiler allowed this. Adding the await fixed the problem.

Try-Catch error handiling in ASP.NET

I have one doubt regarding Try-Catch block.
Below is my code
private void PopulateDDL()
{
try
{
if (my condition)
{
code
}
else
{
throw new Exception(ErrorMessage);
}
}
catch (Exception ex)
{
logerror(ex);
}
}
Which Catch block will be executed if error for below code
else
{
throw new Exception(ErrorMessage);
}
From MSDN:
When an exception is thrown, the common language runtime (CLR) looks
for the catch statement that handles this exception. If the currently
executing method does not contain such a catch block, the CLR looks at
the method that called the current method, and so on up the call
stack. If no catch block is found, then the CLR displays an unhandled
exception message to the user and stops execution of the program.
The catch block you have defined:
catch (Exception ex)
{
RaiseWebError(ex);
}
will be executed first for the exception throw new Exception(ErrorMessage);
If RaiseWebError re-throws the exception this will then be handled by the next try-catch block found futher up the call stack (i.e. the parent method you refer to). But if RaiseWebError handles the exception in some way (perhaps by logging the exception) execution will continue after the first try-catch.

How to differentiate between various exception while calling a webservice in using .net?

I am consuming one webservice, while consuming there can different types expception might occur depeninding on various situation like.. network failur, invalid soap data or exception from serverside also might occur.
How can I differntiate between these different excpetion?
Because in my application, with these exceptions I need to update the various status Like: if network failure occurs Status will be "unable to connect webservice" so I can try after sometime later. If exception comes from Web server , no need to call/try again.
nRk
What about a try/catch block but with multiple catches for different exceptions? e.g.
try
{
// webservice invocation
}
catch (SoapException ex)
{
// Handle Soap exceptions
}
catch (IOException ex)
{
// Handle IOException
}
catch (Exception ex}
{
// Handler of last resort - any exception not specifically handled above
// will be caught here
}

Resources