LoadBalancingChannel exception on DocumentClient.Dispose() - azure-cosmosdb

We have hit an issue where after using CosmosDb, an exception occurs if we try to dispose of the DocumentClient shortly after. Waiting a few seconds before disposing causes no exceptions. We have confirmed that we are using await with every asynchronous call.
Psuedo-code:
using(DocumentClient documentClient = new DocumentClient(...params)) {
IOrderedQueryable<T> query = this.documentClient.CreateDocumentQuery<T>(...params);
IList<T> documents;
using (IDocumentQuery<T> documentQuery = query.AsDocumentQuery()) {
documents = (await documentQuery.ExecuteNextAsync<T>()).ToList();
}
// Processing...
}
The exception states:
LoadBalancingChannel rntbd://[ip].documents.azure.com:[port]/ in use
The API that makes the call successfully returns before DocumentClient.Dispose is called (all of the documents are correctly returned).
Has anyone seen this exception before? A search revealed no hits.

It can happen if the DocumentClient is disposed while pending requests. this was addressed in SDK version 2.2.2, please upgrade to latest SDK version.

Related

This MongoDB deployment does not support retryable writes Exception on ASP.net core

I am working on asp.net core and mongo db. Here I am trying to implement transaction support using the below code
using (var session = await _mongoClient.StartSessionAsync())
{
try
{
session.StartTransaction();
await _dbCollection.InsertOneAsync(session,obj);
//throw new Exception("No document found");
await session.CommitTransactionAsync();
}
catch (Exception ex)
{
//session.AbortTransaction();
await session.AbortTransactionAsync();
}
}
But it is throwing exception
MongoDB.Driver.MongoCommandException: This MongoDB deployment does not
support retryable writes. Please add retryWrites=false to your
connection string.
The below code, I am using to create connection
_mongoClient = new MongoClient(config.GetConnectionString("CarGalleryDb"));
//MongoClientSettings mongoClientSettings = new MongoClientSettings();
//mongoClientSettings.RetryWrites = false;
_db = _mongoClient.GetDatabase(config.GetConnectionString("DBName"));
And my connection string is
"ConnectionStrings": {
"CarGalleryDb": "mongodb://localhost:27017?retryWrites=false",
"DBName": "MongoTestDB"
},
Can anybody support me to resolve this one?
You need to add retryWrites=false at the end of the your connection string.
See Retryable Writes in Mongo
The official MongoDB 3.6 and 4.0-compatible drivers required including
the retryWrites=true option in the connection string to enable
retryable writes for that connection.
The official MongoDB 4.2-compatible drivers enable Retryable Writes by
default. Applications upgrading to the 4.2-compatible drivers that
require retryable writes may omit the retryWrites=true option.
Applications upgrading to the 4.2-compatible drivers that require
disabling retryable writes must include retryWrites=false in the
connection string.
Or you can set in code by using MongoClientSettings.RetryWrites:
https://mongodb.github.io/mongo-csharp-driver/2.7/apidocs/html/P_MongoDB_Driver_MongoClientSettings_RetryWrites.htm
This error is produced when you are using the deprecated MMAPv1 storage engine. If you can you should upgrade to WiredTiger (and a newer MongoDB version since MMAPv1 is removed in 4.2 altogether).

Realm doesn’t work with xUnite and .net core

I’m having issues running realm with xUnite and Net core. Here is a very simple test that I want to run
public class UnitTest1
{
[Scenario]
public void Test1()
{
var realm = Realm.GetInstance(new InMemoryConfiguration("Test123"));
realm.Write(() =>
{
realm.Add(new Product());
});
var test = realm.All<Product>().First();
realm.Write(() => realm.RemoveAll());
}
}
I get different exceptions on different machines (Windows & Mac) on line where I try to create a Realm instace with InMemoryConfiguration.
On Mac I get the following exception
libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.
On Windows I get the following exception when running
ERROR Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. at
System.Net.Sockets.NetworkStream.Read(Span1 destination) at
System.Net.Sockets.NetworkStream.ReadByte() at
System.IO.BinaryReader.ReadByte() at
System.IO.BinaryReader.Read7BitEncodedInt() at
System.IO.BinaryReader.ReadString() at
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.LengthPrefixCommunicationChannel.NotifyDataAvailable() at
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TcpClientExtensions.MessageLoopAsync(TcpClient client, ICommunicationChannel channel, Action1 errorHandler, CancellationToken cancellationToken) Source: System.Net.Sockets HResult: -2146232800 Inner Exception: An existing connection was forcibly closed by the remote host HResult: -2147467259
I’m using Realm 3.3.0 and xUnit 2.4.1
I’ve tried downgrading to Realm 2.2.0, and it didn’t work either.
The solution to this problem was found in this Github post
The piece of code from that helped me to solve the issue
Realm GetInstanceWithoutCapturingContext(RealmConfiguration config)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
Realm realm = null;
try
{
realm = Realm.GetInstance(config);
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}
Though it took a while for me to apply this to my solution.
First and foremost, instead of just setting the context to null I am using Nito.AsyncEx.AsyncContext. Because otherwise automatic changes will not be propagated through threads, as realm needs a non-null SynchronizationContext for that feature to work. So, in my case the method looks something like this
public class MockRealmFactory : IRealmFactory
{
private readonly SynchronizationContext _synchronizationContext;
private readonly string _defaultDatabaseId;
public MockRealmFactory()
{
_synchronizationContext = new AsyncContext().SynchronizationContext;
_defaultDatabaseId = Guid.NewGuid().ToString();
}
public Realm GetRealmWithPath(string realmDbPath)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
Realm realm;
try
{
realm = Realm.GetInstance(new InMemoryConfiguration(realmDbPath));
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}
}
Further, this fixed a lot of failing unit tests. But I was still receiving that same exception - Realm accessed from incorrect thread. And I had no clue why, cause everything was set correctly. Then I found that the tests that were failing were related to methods where I was using async realm api, in particular realm.WriteAsync. After some more digging I found the following lines in the realm documentation.
It is not a problem if you have set SynchronisationContext.Current but
it will cause WriteAsync to dispatch again on the thread pool, which
may create another worker thread. So, if you are using Current in your
threads, consider calling just Write instead of WriteAsync.
In my code there was no direct need of using the async API. I removed and replaced with sync Write and all the tests became green again! I guess if I find myself in a situation that I do need to use the async API because of some kind of bulk insertions, I'd either mock that specific API, or replace with my own background thread using Task.Run instead of using Realm's version.

Maintain dependency object instance within the thread

Need help on below issue, I have below method:
public IHttpActionResult Test()
{
Task.Run(() => DoTheStuff())
Return Ok()
}
Note: Here I don't want to use async/await keyword, as I don't care about the result of DoTheStuff() method. I just need to open one thread and execute the code.
DoTheStuff() method refers the objects which are injected through dependency injection (Autofac). and in Module.Config I have registered all the required dependencies with lifetimescope.
Below issue I am facing call to Task.Run(() => DoTheStuff()) starts new thread executing DoTheStuff() method.
At the same time Test() method completes it execution with return Ok(), but DoTheStuff method is still running asynchronously.
With execution of Test() method, the registered dependencies gets disposed, and DoTheStuff() method throws below exception:
Nested lifetime cannot be created from the LifetimeScope as it has
already been disposed
Can someone please let me know how to maintain dependency object instance within the thread?
I can see a couple options.
Extract DoTheStuff into its own service. Register the services that you're injecting and using in DoTheStuff as InstancePerDependency so that the service gets its own instance. See https://autofaccn.readthedocs.io/en/latest/lifetime/instance-scope.html.
Add a Wait:
var t = Task.Run(() => DoTheStuff());
t.Wait();
return Ok();
Let me know if neither of those works.

Azure / Xamarin - SyncContext.InitializeAsync Deadlock

I have a Xamarin.Forms App which use Azure App Service with SQLLite Offline Sync.
When calling SyncContext.InitializeAsync a deadlock appears and the function InitializeAsync never finished.
In this Thread in found the solution: Azure/Xamarin Mobile App Hangs at SyncContext.InitializeAsync
This works:
System.Threading.Tasks.Task.Run(() => this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler)).Wait();
This not:
await this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler);
Whole function:
public override async System.Threading.Tasks.Task Init()
{
string storePath = System.IO.Path.Combine(Microsoft.WindowsAzure.MobileServices.MobileServiceClient.DefaultDatabasePath, localStoreName);
Microsoft.WindowsAzure.MobileServices.SQLiteStore.MobileServiceSQLiteStore localStore = new Microsoft.WindowsAzure.MobileServices.SQLiteStore.MobileServiceSQLiteStore(storePath);
localStore.DefineTable<CPM.Recruitment.Mobile.Freelancer.DataObjects.Entities.Promoter>();
System.Threading.Tasks.Task.Run(() => this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler)).Wait();
//await this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler);
_promoters = new Azure.AppService.DataObjects.Client.Sync.List<CPM.Recruitment.Mobile.Freelancer.DataObjects.Entities.Promoter>(this, this.IDataProvider.IMobileServiceClient.GetSyncTable<CPM.Recruitment.Mobile.Freelancer.DataObjects.Entities.Promoter>());
}
But why? I dont want to use Wait();
The differences between await and Wait method are:
await means the current task will be executed in a separated thread asynchronously and the calling thread won't be blocked. If the calling thread is UI thread. the UI thread will continue to run other operations.
Wait method are synchronization method. It causes the calling thread to wait until the current task has completed. If the calling thread is UI thread, UI operations will be blocked.
It seems that a deadlock will be caused if you use await to run the task which will not block UI thread.

SDL Tridion 2009: Creating components through TOM API (via Interop) fails

Am facing a problem, while creating components through TOM API using .NET/COM Interop.
Actual Issue:
I have 550 components to be created through custom page. I am able to create between 400 - 470 components but after that it is getting failed and through an error message saying that
Error: Thread was being aborted.
Any idea / suggestion, why it is getting failed?
OR
Is there any restriction on Tridion 2009?
UPDATE 1:
As per #user978511 request, below is error on Application event log:-
Event code: 3001
Event message: The request has been aborted.
...
...
Process information:
Process ID: 1016
Process name: w3wp.exe
Account name: NT AUTHORITY\NETWORK SERVICE
Exception information:
Exception type: HttpException
Exception message: Request timed out.
...
...
...
UPDATE 2:
#Chris: This is my common function, which is called in a loop by passing list of params. Here am using Interop dll's.
public static bool CreateFareComponent(.... list of params ...)
{
TDSE mTDSE = null;
Folder mFolder = null;
Component mComponent = null;
bool flag = false;
try
{
mTDSE = TDSEInitialize();
mComponent = (Component)mTDSE.GetNewObject(ItemType.ItemTypeComponent, folderID, null);
mComponent.Schema = (Schema)mTDSE.GetObject(constants.SCHEMA_ID, EnumOpenMode.OpenModeView, null, XMLReadFilter.XMLReadAll);
mComponent.Title = compTitle;
...
...
...
...
mComponent.Save(true);
flag = true;
}
catch (Exception ex)
{
CustomLogger.Error(String.Format("Logged User: {0} \r\n Error: {1}", GetRemoteUser(), ex.Message));
}
return flag;
}
Thanks in advance.
Sounds like a timeout, most likely in IIS which is hosting your custom page.
Are you creating them all in one synchronous request? Because that is indeed likely to time out.
You could instead create them in batches - or make sure your operations are done asynchronously and then polling the status regularly.
The easiest would just be to only create say 10 Components in one request, wait for it to finish, and then create another 10 (perhaps with a nice progress bar? :))
How you call TDSE object. I would like to mention here "Marshal.ReleaseComObject" procedure. Without releasing COMs objects can lead to enormous memory leaks.
Here is code for component creating:
private Component NewComponent(string componentName, string publicationID, string parentID, string schemaID)
{
Publication publication = (Publication)mTdse.GetObject(publicationID, EnumOpenMode.OpenModeView, null, XMLReadFilter.XMLReadContext);
Folder folder = (Folder)mTdse.GetObject(parentID, EnumOpenMode.OpenModeView, null, XMLReadFilter.XMLReadContext);
Schema schema = (Schema)mTdse.GetObject(schemaID, EnumOpenMode.OpenModeView, publicationID, XMLReadFilter.XMLReadContext);
Component component = (Component)mTdse.GetNewObject(ItemType.ItemTypeComponent, folder, publication);
component.Title = componentName;
component.Schema = schema;
return component;
}
After that please not forget to release mTdse ( in my case it is previously created TDSE object). Disposing "Components" object can be useful also after finish working with them.
For large Tridion batch operations I always use a Console Application and run it directly on the server.
Use Console.WriteLine to write to the output window and Console.ReadLine as the last line of code in the app (so the window stays open). I also use Log4Net as the logger.
This is by far the best approach if you have access to a remote session on the server - or can ask an admin to run it for you and give you access to the log folder via a network share.
As per #chris suggestions and part of immediate fix I have changed my web.config execution time out to 8000 seconds.
<httpRuntime executionTimeout="8000"/>
With this change, custom page is able to handle as of now.
Any more best suggestion, please post it.

Resources