Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug with generic state parameter caused by inconsistent use of grainClassName / genericArgument / genericInterface #1897

Merged
merged 2 commits into from
Jul 7, 2016

Conversation

Maarten88
Copy link
Contributor

After lots of debugging on an issue I have with a generic grain that uses storage, I think that this change fixes the issue. The genericArgument was used inconsistently, and sometimes contained the genericInterface value. Also the grainClass parameter did not include the genericArguments during setup of the state, causing the grainType parameter in the first ReadStateAsync to be incorrect.

I moved the location where the conversion was made from SetupActivationInstance() into catalog.GetOrCreateActivation(), passed genericArguments in some functions and fixed the naming.

I think this fixes several bugs, including #1579.

Please test thoroughly, this "works on my machine" but the change might do things that I don't really understand and this is my first pull request on orleans.

(cherry picked from commit af6e2fa)

Added test that explicitly blocks for a response to make sure the client does not deadlock.
(cherry picked from commit 15a5872)
@dnfclas
Copy link

dnfclas commented Jul 2, 2016

Hi @Maarten88, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution!

In order for us to evaluate and accept your PR, we ask that you sign a contribution license agreement. It's all electronic and will take just minutes. I promise there's no faxing. https://cla2.dotnetfoundation.org.

TTYL, DNFBOT;

@dnfclas
Copy link

dnfclas commented Jul 2, 2016

@Maarten88, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR.

Thanks, DNFBOT;

@veikkoeeva
Copy link
Contributor

@Maarten88 I'll cross-link so I remember to remove the fix I put straight into the storage provider at #1682. Very nice you went throgh the trouble to the bottom of this!

@@ -422,8 +422,8 @@
<Message Text="[OrleansDllBootstrapUsingCodeGen] - Compiling Orleans.dll for bootstrap" Importance="high" />
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Build" Properties="Bootstrap=true;BootstrapOutputPath=$(BootstrapOutputPath);DefineConstants=$(ExcludeCodeGen)" UnloadProjectsOnCompletion="true" UseResultsCache="false" />
<Message Text="[OrleansDllBootstrapUsingCodeGen] - Compiling code generators for bootstrap" Importance="high" />
<MSBuild Projects="$(SolutionDir)\OrleansCodeGenerator\OrleansCodeGenerator.csproj" Targets="Build" Properties="Bootstrap=true;BootstrapOutputPath=$(BootstrapOutputPath);OutputPath=$(BootstrapOutputPath);OutDir=$(BootstrapOutputPath);DefineConstants=$(ExcludeCodeGen)" UnloadProjectsOnCompletion="true" UseResultsCache="false" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need for this change, is there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did that to make it possible to reference the csproj file from another solution, in another directory. I thought this would come handy for others trying to debug/reference orleans inside their own project.

It's not needed for the fix itself.

@sergeybykov
Copy link
Contributor

LGTM minus the minor code cleanup comments. I fired a functional test run for just in case.

@sergeybykov sergeybykov self-assigned this Jul 6, 2016
@sergeybykov sergeybykov added this to the 1.3.0 milestone Jul 6, 2016
…nericArgs

translation deeper into GrainFactoryBase. Enabled testcase for dotnet#1579
@veikkoeeva
Copy link
Contributor

@Maarten88, @sergeybykov So, if I understand correctly, I wouldn't need d5cff4b#diff-bf7a979df10dd018220615846b992e2bR459 anymore after this gets in?

@Maarten88
Copy link
Contributor Author

Maarten88 commented Jul 7, 2016

@veikkoeeva with this change, grainType will always have the full typename, including generic arguments, in both ReadStateAsync and WriteStateAsync, so you should not need that anymore. Removing it would result in a different keyvalue that your current code (the non-generic typeName).

I wonder, does your workaround work currently with generic grains? You still seem to calculate a hash over the unnormalized grainType, which, before this, was different between read and write in the case of generic grain. Also normalizing the grainType would give MyGrain<int> and MyGrain<string> the same key.

@veikkoeeva
Copy link
Contributor

veikkoeeva commented Jul 7, 2016

@Maarten88 You are right! I seriously overlooked that when I just looked the grain reference and got things mixed up in my mind while putting in something that allowed to carry on.

There is another thing with this too, namely having grains of type MyGrain<int> and MyGrain<string> and having a generic state, e.g.

public class MyGrain<T>: Grain<SomeState<int>>, IMyGrain<T>
[...]
var grain1 = GrainClient.GrainFactory.GetGrain<IMyGrain<int>>(0);
var grain2 = GrainClient.GrainFactory.GetGrain<IMyGrain<string>>(0);

will throw an AggregateException telling

"Error creating activation for MyGrain`1. Message NewPlacement Request S127.0.0.1:22222:205585603_cli/4c2c27a2@37bc2787->S127.0.0.1:22222:205585603_grn/81758359/00000000@62053eae #4: global::IMyGrain:GetSomeType()"}
and so forth.

One way to reproduce this is to go the StorageProviders sample and make both Person and PersonState generic and then try to create those two grains. Looks like a bug or a limitation.

@Maarten88
Copy link
Contributor Author

@veikkoeeva @sergeybykov I have wondered many times in the past days why activation does all these state related things at all. Why was that not implemented by simply calling ReadStateAsync from OnActivateAsync in the base class for a PersistentGrain? The read-side of GrainStateStorageBridge is mostly unused the way the code works now.

@sergeybykov sergeybykov merged commit d1b0915 into dotnet:master Jul 7, 2016
@sergeybykov
Copy link
Contributor

Thank you, @Maarten88! This was an embarrassing and non-trivial to root-cause bug.

@veikkoeeva
Copy link
Contributor

veikkoeeva commented Jul 8, 2016

@Maarten88, probably @sergeybykov too, I wonder if it is problematic to have the version numbers there. This is grainType snatched from one of the tests

UnitTests.Grains.AzureStorageGenericGrain`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

Wouldn't this mean that when the version of the assembly is updated, the saved stated is rendered inaccessible?

@Maarten88
Copy link
Contributor Author

Maarten88 commented Jul 8, 2016

@veikkoeeva @sergeybykov yes, I think using FullName for the type still causes problems (like you say: compatibility when using assembly versioning, but also the key length in TableStorage for generic grains getting too long because the .FullName ends up inside the partition key). This generic stuff certainly is not done yet, there also are still several tests disabled.

I think the next improvement / fix here would be to use type.ToString() instead of type.FullName, which gives a generic type that looks much saner, in your example it gives UnitTests.Grains.AzureStorageGenericGrain```1[System.Int32] which is what I'd expect it to be. I did a short spike yesterday to find out how much impact this change would have, only to find out that there's more .FullType and type string parsing going on than I can test before my vacation.

@veikkoeeva
Copy link
Contributor

To save @ReubenBond's time, here's a a suggestion from him

We could just use TypeUtils.GetParseableName(type, options) and get back the (optionally fully qualified) C#-parseable type name without assembly-qualifications.

@veikkoeeva
Copy link
Contributor

@Maarten88 Ah, see the comment. That function might be the solution. Whatever it is, I think we should have a visible function for it.

jdom added a commit to jdom/orleans that referenced this pull request Mar 22, 2017
By doing this, I encountered that this is still failing on the call to ClearState
ReubenBond pushed a commit that referenced this pull request Mar 22, 2017
…1897) (#1915)

* Cleanup for PR #1897 (generic state parameter bug)

* Add tests for azure blob storage & skip tests if being run in the emulator
@github-actions github-actions bot locked and limited conversation to collaborators Dec 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants