OpenTl / OpenTl.ClientApi

The Api client library that implements the MtProto 2.0. To connect to servers, such as Telegram
MIT License
80 stars 24 forks source link

Should we register IClientApi as singleton? #19

Closed micdenny closed 5 years ago

micdenny commented 6 years ago

We are using this server-side and we're getting a lot of these thread-safety errors:

System.InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
   at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
   at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
   at OpenTl.Schema.Serialization.SerializationMap.TryGetSerializator(TypeInfo type, ISerializator& serializator)
   at OpenTl.Schema.Serialization.SerializationMap.GetSerializator(TypeInfo type)
   at OpenTl.Schema.Serialization.Serializators.ObjectTypes.IObjectSerializer.Deserialize(IByteBuffer buffer, SerializationMetadata typeMetadata)
   at OpenTl.Schema.Serialization.Serializators.ObjectTypes.IObjectSerializer.Deserialize(IByteBuffer buffer, SerializationMetadata typeMetadata)
   at OpenTl.Schema.Serialization.Serializators.ObjectTypes.VectorSerializer.Deserialize(IByteBuffer buffer, SerializationMetadata metadata)
   at OpenTl.Schema.Serialization.Serializators.ObjectTypes.IObjectSerializer.Deserialize(IByteBuffer buffer, SerializationMetadata typeMetadata)
   at OpenTl.ClientApi.MtProto.Layers.Messages.Adapters.RpcResultHandler.ChannelRead0(IChannelHandlerContext ctx, TRpcResult msg)
   at DotNetty.Transport.Channels.SimpleChannelInboundHandler`1.ChannelRead(IChannelHandlerContext ctx, Object msg)
   at DotNetty.Transport.Channels.AbstractChannelHandlerContext.InvokeChannelRead(Object msg)
--- End of stack trace from previous location where exception was thrown ---
   at OpenTl.ClientApi.MtProto.Services.RequestSenderService.SendRequestAsync[TResult](IRequest`1 request, CancellationToken cancellationToken)
   at OpenTl.ClientApi.Services.ContactsService.ImportContactsAsync(IReadOnlyList`1 contacts, CancellationToken cancellationToken)
DotNetty.Codecs.EncoderException: Exception of type 'DotNetty.Codecs.EncoderException' was thrown. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at OpenTl.Schema.Serialization.SerializationMap.TryGetSerializator(TypeInfo type, ISerializator& serializator)
   at OpenTl.Schema.Serialization.SerializationMap.GetSerializator(TypeInfo type)
   at OpenTl.Schema.Serialization.Serializer.Serialize(Object obj, IByteBuffer buffer, SerializationMetadata metadata)
   at OpenTl.Schema.Serialization.Serializer.Serialize(Object obj)
   at OpenTl.ClientApi.MtProto.Layers.Secure.Codecs.SecureRequestEncoder.Encode(IChannelHandlerContext context, IObject message, IByteBuffer output)
   at DotNetty.Codecs.MessageToByteEncoder`1.WriteAsync(IChannelHandlerContext context, Object message)
   --- End of inner exception stack trace ---
   at OpenTl.ClientApi.MtProto.Layers.Top.Adapters.TopHandlerAdapter.SendInitConnectionRequest()
   at OpenTl.ClientApi.MtProto.Services.RequestSenderService.SendRequestAsync[TResult](IRequest`1 request, CancellationToken cancellationToken)
   at OpenTl.ClientApi.Services.ContactsService.ImportContactsAsync(IReadOnlyList`1 contacts, CancellationToken cancellationToken)
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Collections.Generic.LinkedList`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at OpenTl.ClientApi.MtProto.Layers.Top.Adapters.TopHandlerAdapter.SendInitConnectionRequest()
   at OpenTl.ClientApi.MtProto.Services.RequestSenderService.SendRequestAsync[TResult](IRequest`1 request, CancellationToken cancellationToken)
   at OpenTl.ClientApi.Services.ContactsService.ImportContactsAsync(IReadOnlyList`1 contacts, CancellationToken cancellationToken)

Does using the IClientApi as singleton resolve this thread-safety issues? maybe because some initialization are non thread-safe?

vik-borisov commented 6 years ago

Hi, @micdenny!

please write a test application with this exception. I think that this is a mistake.

micdenny commented 6 years ago

I will try, it’s hard to me understand what to mock in order to do a proper unit test, I will study your tests project and see if I can reproduce the exception.

vik-borisov commented 6 years ago

@micdenny A console application is sufficient

micdenny commented 6 years ago

Ok

vik-borisov commented 6 years ago

@micdenny Still relevant?

micdenny commented 6 years ago

yes, but need more time, I've scheduled this later

vik-borisov commented 6 years ago

@micdenny try to use new version