Version tolerance
ismaelhamed opened this issue · 16 comments
System.IO.FileLoadException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.2.0, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Collections.Immutable, Version=1.2.2.0, PublicKeyToken=b03f5f7f11d50a3a'
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
at System.Type.GetType(String typeName, Boolean throwOnError)
at Hyperion.Extensions.TypeEx.<>c.<GetTypeFromManifestName>b__27_0(ByteArrayKey b)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Hyperion.Extensions.TypeEx.GetTypeFromManifestName(Stream stream, DeserializerSession session)
at Hyperion.Extensions.TypeEx.GetTypeFromManifestVersion(Stream stream, DeserializerSession session)
at Hyperion.Serializer.GetDeserializerByManifest(Stream stream, DeserializerSession session)
at lambda_method(Closure , Stream , DeserializerSession )
at Hyperion.Serializer.Deserialize[T](Stream stream)
at Akka.Serialization.HyperionSerializer.FromBinary(Byte[] bytes, Type type)
@Aaronontheweb should nodes with different versions of a package like System.Collections.Immutable
break remoting serialization?
AFAIK System.Collections.Immutable
is supported purely via reflection. This seems more like the issue in the project using Hyperion (maybe it didn't load immutables assembly before deserializing?), that Hyperion itself.
This happened in an Akka Cluster in which one of the nodes had a different version of System.Collections.Immutable
than the rest. So upon receiving a message with an Immutable property from another node, it thrown. Consolidating this package's version for all the nodes fixed the problem.
So it may seems like Hyperion is serializing the assembly version, hence my question.
@ismaelhamed your observation is correct. And this is a very big problem. Even used as a wire protocol, you can frequently have different assembly versions.
I believe we're supposed to strip the version numbers out of the assembly payloads, via akkadotnet/akka.net#3767 (comment) - but if that's not the case, we need to fix it.
@OnurGumus @Aaronontheweb I opened this issue prior to that PR. Need to check again whether this is still an issue.
@ismaelhamed @Aaronontheweb I just made an experiment. It works fine now. Wow what a great relief! Because of this I was avoiding nuget upgrades in my cluster.
Actually, I'll keep this issue open until @ismaelhamed reports in that all is well too - but that's good to hear @OnurGumus
This seems to have been fixed moving forward, but it's still no possible to deserialize messages prior to version 1.3.17. @Aaronontheweb can we make something in this regard, like ignoring version, if present, during the deserialization?
@ismaelhamed you mean ignore any assembly version information that was included in the original write?
@Aaronontheweb Yep. Does it make sense?
Yes it does - should be a straightforward fix. We'll want a regression test to cover though.
Yea I agree this is essential if we want an upgrade.
Not sure if this is a problem with Hyperion or Akka.
@ismaelhamed I tested this. Basically if you serialize with newer version of hyperion, since it doesn't add the version number, the older version is able to deserialize. However the reverse is not true. If you serialize the older one, the newer version is not able to deserialize since it tries to match the version.
It's purely a hyperion problem.
@OnurGumus you're right. @Aaronontheweb here's a gist to confirm this behavior: serializedString
using Hyperion 0.9.8 will always fail to deserialized if you upgrade the System.Collections.Immutable
assembly version; the one serialized using Hyperion 0.9.11 won't.
Submitted fix for this. Should try to use assembly version, if specified (more details here, otherwise just ignore version.