Skip to content

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

Merged
sergeybykov merged 2 commits into
dotnet:masterfrom
Maarten88:genericgrainfix
Jul 7, 2016
Merged

Fix bug with generic state parameter caused by inconsistent use of grainClassName / genericArgument / genericInterface#1897
sergeybykov merged 2 commits into
dotnet:masterfrom
Maarten88:genericgrainfix

Conversation

@Maarten88

Copy link
Copy Markdown
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

dnfclas commented Jul 2, 2016

Copy link
Copy Markdown

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

dnfclas commented Jul 2, 2016

Copy link
Copy Markdown

@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
Copy Markdown
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!

Comment thread src/Orleans/Orleans.csproj Outdated

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor

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

@Maarten88

Maarten88 commented Jul 7, 2016

Copy link
Copy Markdown
Contributor Author

@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

veikkoeeva commented Jul 7, 2016

Copy link
Copy Markdown
Contributor

@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
Copy Markdown
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
Copy Markdown
Contributor

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

@veikkoeeva

veikkoeeva commented Jul 8, 2016

Copy link
Copy Markdown
Contributor

@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

Maarten88 commented Jul 8, 2016

Copy link
Copy Markdown
Contributor Author

@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
Copy Markdown
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
Copy Markdown
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.

6 participants