Closed chris-eaton closed 6 years ago
@chris-eaton what happens if you force the Common asm to be loaded at the entry point of the program by calling something like Console.WriteLine(typeof(Plot))
?
Hey @ReubenBond thats a good idea, and thanks for the help, but unfortunately it doesnt work.
Interestingly, I restarted it and out of nowhere got this error message in another client [one that sends Plots to Orleans]. Note that this client has worked without fail [and is working in production under the same code] for some time. Not that simply cleaning and building made this specific error go away but the streaming still fails to work
var grain = this.grainClient.GetGrain<IUnitGrain>(plot.Imei);
await grain.Process(plot.AsImmutable());
Orleans.Runtime.OrleansMessageRejectionException: 'Unexpected error serializing message to gateway gwy.tcp://127.0.0.1:40000/0. System.ArgumentException: No serializer found for object of type xxx.Common.Models.Plot. Perhaps you need to mark it [Serializable] or define a custom serializer for it?
at Orleans.Serialization.SerializationManager.SerializeInner(Object obj, ISerializationContext context, Type expected) at Orleans.Serialization.BuiltInTypes.SerializeImmutable[T](Object original, ISerializationContext context, Type expected) at Orleans.Serialization.BuiltInTypes.SerializeGenericImmutable(Object original, ISerializationContext context, Type expected) at Orleans.Serialization.SerializationManager.SerializeInner(Object obj, ISerializationContext context, Type expected) at Orleans.Serialization.BuiltInTypes.SerializeInvokeMethodRequest(Object obj, ISerializationContext context, Type expected) at Orleans.Serialization.SerializationManager.SerializeInner(Object obj, ISerializationContext context, Type expected) at Orleans.Serialization.SerializationManager.Serialize(Object raw, BinaryTokenStreamWriter stream) at Orleans.Runtime.Message.Serialize(SerializationManager serializationManager, Int32& headerLengthOut, Int32& bodyLengthOut) at Orleans.Messaging.OutgoingMessageSender.Process(Message msg)'
Just to test, I changed the stream to accept a string and then manually serialize and deserialize the Plot myself into JSON [using NewtonSoft] and this instantly works and decodes correctly after reading the stream.
await this.plotPointDataStream.OnNextAsync(Newtonsoft.Json.JsonConvert.SerializeObject(plot));
Here is the encoded json:
"{ \"Id\": 2256638137, \"UtcHost\": \"2017-08-02T08: 59: 44.4755029Z\", \"Utc\": \"2017-08-02T08: 59: 42Z\", \"UtcQueueReader\": \"2017-08-02T08: 59: 44.6604392Z\", \"Odometer\": 619401521, \"Velocity\": 77, \"Satfix\": 1, \"Sats\": 8, \"Rssi\": 1000, \"Reason\": 1, \"Direction\": 323, \"PlaceName\": \"M1, Northampton NN6 7UH, UK\", \"District\": null, \"RoadName\": null, \"PostSector\": null, \"GeofenceName\": null, \"VehicleId\": 18387, \"DriverId\": null, \"Imei\": \"355060010829732\", \"ReasonTextLegacy\": null, \"MdtMessageLegacy\": null, \"LocationTextLegacy\": null, \"DirectionTextLegacy\": null, \"MaxVelocityInPeriod\": null, \"BatteryLevel\": null, \"VehicleBatteryLevel\": null, \"MessagingDeviceConnected\": false, \"PlotValidity\": 1, \"GeocodedAddressId\": 74576, \"IsIgnitionOn\": true, \"DriverLogonInfo\": null, \"GeocodedAddress\": { \"Id\": 74576, \"Center\": { \"Latitude\": 52.3188732, \"Longitude\": -1.1344806 }, \"Bounds\": [ { \"Latitude\": 52.3220709, \"Longitude\": -1.1306657 }, { \"Latitude\": 52.3220709, \"Longitude\": -1.1381608 }, { \"Latitude\": 52.3157345, \"Longitude\": -1.1381608 }, { \"Latitude\": 52.3157345, \"Longitude\": -1.1306657 }, { \"Latitude\": 52.3220709, \"Longitude\": -1.1306657 } ], \"North\": 52.3220709, \"East\": -1.1306657, \"South\": 52.3157345, \"West\": -1.1381608, \"PlaceId\": \"ChIJSzUW4QUVd0gRyWF7SXwetCo\", \"UtcUpdated\": \"2017-07-25T13: 42: 43.897Z\", \"FormattedAddress\": \"M1, Northampton NN6 7UH, UK\", \"PostCode\": \"NN6 7UH\", \"BoundsSource\": 1 }, \"CanParams\": null, \"Temperatures\": null, \"GarminMessage\": null, \"GarminJob\": null, \"JobEta\": null, \"Telematics\": null, \"Latitude\": 52.317308333333337, \"Longitude\": -1.1323722222222223 }"
@chris-eaton is the type marked as [Serializable]
? What happens if you enable build-time codegen by installing the Microsoft.Orleans.OrleansCodeGenerator.Build
nuget package into the assembly containing that type?
@ReubenBond No, but its able to be passed around grains easily enough and has been for months.
The type is actually contained in another nuget package [that we author] that I'd ideally like to keep free of any Orleans code. Unless you mean installing that package into my Orleans project? If so should it go into the project containing the grains or all projects that talk to Orleans?
@chris-eaton no worries. In your Orleans project (which is loaded by the client), try adding this [assembly: KnownAssembly(typeof(Plot))]
and installing the aforementioned nuget package.
@ReubenBond
I've put [assembly: KnownAssembly(typeof(Plot))]
into
I've also installed Microsoft.Orleans.OrleansCodeGenerator.Build
into all projects. Note I also have Microsoft.Orleans.OrleansCodeGenerator
installed
I still get no Plots sent via streaming and the same exception thrown in logs
System.TypeAccessException: Named type "xxx.Common.Models.Plot
@chris-eaton is there a time we can skype/IM to solve this?
One issue is that the type is not having a serializer generated for it because it's not marked as [Serializable]
. You can change that behavior by adding an assembly-level attribute:
[assembly: GenerateSerializer(typeof(Plot))]
.
I'm still unsure about the TypeAccessException
, it seems that the assembly containing that type isn't being processed.
@ReubenBond Hey Reuben, sorry I hadn't realised you'd written this. I'm not working on that project right now but as soon as I am I'll give you a shout if the offer is still available. Thank you!
No worries, @chris-eaton :) Should we close this for now until you get a chance to revisit it?
Note
This may just be anecdotal, but I'm fairly sure this used to work [although I had only got it working in test / POC setups] and I feel like this only happened after I switched from using
GrainClient
toClientBuilder
...Problem Description
I have a Silo and a Client that I am connecting to the Silo. The client is very lightweight and simply connects to the Silo and then subscribes to a stream like so:
When data is sent to the stream I get this error message
All of the properties on
Plot
are primitive except forDateTime
. When this didn't work I tried another simpler modelUser
but this also failed in the same way.Interestingly if I subscribe to this stream from another grain within the Silo it works perfectly. So it seems to only be an issue to a client application connecting in.
If it helps here is the package.config for the test stream client