Dependency Tracking when using Task.Run in ASP.NET - azure-application-insights

I have a requirement to use Task.Run(...) to force some non-async code to run in parallel with some other async code.
var task1 = Task.Run(() => synchronous code);
var task2 = await DoSomethingAsync();
await Task.WhenAll(task1, task2);
The dependency calls in the sync synchronous code are not being tracked. It seems the Application Insights SDK (2.4) uses System.Diagnostics.Activity. Is there a way create a new activity start/stop it so that in the synchronous code, the Activity.Current is setup properly and dependency telemetry is associated with the correct parent?
PS I cannot change the synchronous code to be asynchronous. It is calling into Microsoft CRM and the CRM SDK functions I am using do not have asynchronous versions.

Related

The configured execution strategy 'SqlRetryingExecutionStrategy' does not support user-initiated transactions

I have ASP.Net 4.7.2 window service which is processing NServiceBus messages. Currently it is deployed to On-Premise server. It has retry mechanism as well and working fine. Now I am going to containerizing it. While running into docker window container, it is doing SQL operation using Entity framework and giving exception as mentioned below:
The configured execution strategy 'SqlRetryingExecutionStrategy' does not support user-initiated transactions. Use the execution strategy returned by 'DbContext.Database.CreateExecutionStrategy()' to execute all the operations in the transaction as a retriable unit.
While running locally by installing manually or on On-Premise server, it is working fine but in container it is throwing exception.
Can any one help me what can be the root cause?
It sounds like the piece of code does manual transaction management and is not wrapped within an execution strategy execute.
if your code initiates a transaction using BeginTransaction() you are defining your own group of operations that need to be treated as a unit, and everything inside the transaction would need to be played back shall a failure occur.
The solution is to manually invoke the execution strategy with a delegate representing everything that needs to be executed. If a transient failure occurs, the execution strategy will invoke the delegate again.
https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency#execution-strategies-and-transactions
using var db = new SomeContext();
var strategy = db.Database.CreateExecutionStrategy();
strategy.Execute(
() =>
{
using var context = new SomeContext();
using var transaction = context.Database.BeginTransaction();
context.SaveChanges();
transaction.Commit();
});
``

Cosmos DB - stopping IChangeFeedProcessor instance

I am using Change feed processor library to consume Cosmos DB change feed. The IChangeFeedProcessor creation code looks like this:
var builder = new ChangeFeedProcessorBuilder();
processor = await builder
.WithHostName(hostName)
.WithFeedCollection(feedCollectionInfo)
.WithLeaseCollection(leaseCollectionInfo)
.WithObserverFactory(observerFactory)
.BuildAsync();
await processor.StartAsync();
In the ProcessChangesAsync() method of IChangeFeedObserver implementation, I call an external API for each document in the batch.
I would like stop the processor when the external API is down so that I don't read the documents from change feed when I can't process them.
How can I stop the processor(using StopAsync() method) when the IChangeFeedObserver.ProcessChangesAsync() implementation throws Exception?
Not sure about the actual issue, but if the problem is how to access processor inside observer, how about this. You can decorate the observer, pass CFP instance to the decorator, then catch/re-throw all exceptions, but in catch stop CFP.

Microsoft Azure .NET SDK Sync on Async

I am using the Azure Blob Storage SDK Microsoft.WindowsAzure.Storage for my ASP.NET application. I have seen some synchronous method calling asynchronous method. They use an helper method named RunWithoutSynchronizationContext from Microsoft.WindowsAzure.Storage.Core.Util.
The code is basically doing something like
SynchronizationContext current = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext((SynchronizationContext) null);
methodAsync().Wait();
}
finally
{
SynchronizationContext.SetSynchronizationContext(current);
}
I was just wondering if this is a way to avoid deadlock in .NET Framework when blocking on asynchronous code? If not, then what is it the purpose of this method?
One of the common API developer pitfalls in asynchronous development with the .Net TPL is deadlocks. Most commonly, this is caused by SDK consumers using your asynchronous SDK in a synchronous manner.
You could use ConfigureAwait(false) to avoid deadlocking. Calling this routine before awaiting a task will cause it to ignore the SynchronizationContext.
var temp = await methodAsync().ConfigureAwait(false);
However, you need to place ConfigureAwait(false) calls throughout the SDK, and it is easy to forget.
So the trick is understanding how the SynchronizationContext works. Anytime it is used, a call will be made to either it’s Send or Post method.
So, all we need to do is ensuring that these methods never get called:
public void Test_SomeActionNoDeadlock()
{
var context = new Mock<SynchronizationContext>
{
CallBase = true
};
SynchronizationContext.SetSynchronizationContext(context.Object);
try
{
context.Verify(m =>
m.Post(It.IsAny<SendOrPostCallback>(), It.IsAny<object>()), Times.Never);
context.Verify(m =>
m.Send(It.IsAny<SendOrPostCallback>(), It.IsAny<object>()), Times.Never);
}
finally
{
SynchronizationContext.SetSynchronizationContext(null);
}
}
Now we have a way to guarantee that ConfigureAwait(false) was used throughout the SDK method, so long as we get 100% test coverage through the logical paths in the method.

Meteor synchronous method calls

Meteor docs about methods say:
On the server, this function can be run either synchronously or asynchronously. If the callback is omitted, it runs synchronously and the results are returned once the request completes successfully. If the request was not successful, an error is thrown. This is useful when making server-to-server HTTP API calls from within Meteor methods, as the method can succeed or fail based on the results of the synchronous HTTP call. In this case, consider using this.unblock() to allow other methods on the same connection to run in the mean time. On the client, this function must be used asynchronously by passing a callback.
But I find it pretty ambiguous and unobvious, does it just look sync but runs async using fibers, or does it really become sync?
E.g. if I make a server-to-server DDP method call to a meteor app from a meteor app:
const data = anotherMeteorApp.call(...)
Does the code above run sync, blocking the event loop and slowing things down? If it's in a method, would adding this.unblock() before that line of code make it async? If it's not in a method (e.g. if it's in a collection2 hook) would it block?
Yes! the code above runs synchronously (if no callback mentioned.), this will slow down things until operation is completed. You can yourself check the impact of adding this.unblock() by sleeping the process inside meteor call at server.
You can use below code to create a simulation of process taking too much time to execute and return from a method defined on server (Meteor.method()).
var breakTime = 20000; // 20 secs
var Future = Npm.require('fibers/future');
var fut = new Future();
var pause = new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), breakTime);
});
pause.then((1) => {
fut.return(true);
});
let waitHere = fut.wait();
return true;

Document Db async method ExecuteNextAsync() stuck in ASP.NET

I have a Cloud service ASP.NET application which is consuming document db API (Microsoft.Azure.DocumentDB 1.14.0). Here I need to call asynchronous code from synchronous code. My call to execute results on document db is
If I call it from synchronous method:
var result = Task.Run (() => schemaResults.ExecuteNextAsync ()).Result;
If I call it from asynchronous method:
var result = await schemaResults.ExecuteNextAsync ();
OR
var result = await schemaResults.ExecuteNextAsync ().ConfigureAwait (false);
The code works perfectly fine if I run it on localhost on Azure emulator but when I deploy it on Azure, it gets stuck at the above call. Seems like it has gone into a deadlock.
Any help?
I tried updating Microsoft.Azure.DocumentDB 1.14.0 to Microsoft.Azure.DocumentDB 1.14.1
It contains fixes for the deadlocks that occurs in ASP.NET context
Release Notes: https://learn.microsoft.com/en-us/azure/cosmos-db/documentdb-sdk-dotnet#release-notes

Resources