-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Eliminate GrainState #1035
Comments
I agree with all points except related to the ETag. I think ETag is a Storage Provider's Domain and the SP is the only interested on it (if in fact it will use it) to handle conditions like concurrency (not the case in Orleans thanks to the Turn model) and caching, which is a SP responsibility to deal with it, not the grain neither the GrainState. Have a POCO class like |
This is pretty much the same as #865. I agree that there benefits in getting rid of |
+1 for POCO state. |
@sergeybykov keep the State property is not an issue... it will always be T, so I don't see a reason to remove it. Its a nice API IMHO... |
+1 POCO state |
Storage Providers are currently stateless, which is why they can't easily hold ETags or other per-grain context information. What if providers supply their own public interface IGrainState
// ^^^ Use an interface instead of a class. The class is for provider use.
{
object State {get; set; }
}
public class ETaggedGrainState : IGrainState
{
public object State { get; set; }
public string ETag { get; set; }
}
public interface IStorageProvider : IProvider
{
Logger Log { get; }
/// <summary>
/// Creates a new <see cref="IGrainState"/> instance for use by this provider.
/// </summary>
IGrainState CreateGrainState();
// ^^^ Add this method.
Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState);
Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState);
Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState);
} |
@ReubenBond I think that Storage Providers should remain stateless. What do you think about this: public interface IGrainState
{
object State { get; set; }
string ETag { get; set; }
}
public class GrainState<T> : IGrainState
{
public T State { get; set; }
object IGrainState.State
{
get { return State; }
set { State = (T) value; }
}
public string ETag { get; set; }
}
public class Grain<T> : Grain
{
protected Grain()
{
GrainState = new GrainState<T>();
}
protected Grain(IGrainIdentity identity, IGrainRuntime runtime, GrainState<T> state, IStorage storage)
: base(identity, runtime)
{
GrainState = state;
Storage = storage;
}
protected T State
{
get { return (T) GrainState.State; }
set { GrainState.State = value; }
}
protected virtual Task ClearStateAsync()
{
return Storage.ClearStateAsync();
}
protected virtual Task WriteStateAsync()
{
return Storage.WriteStateAsync();
}
protected virtual Task ReadStateAsync()
{
return Storage.ReadStateAsync();
}
}
public interface IStorageProvider : IProvider
{
Logger Log { get; }
//Task ReadStateAsync(string grainType, GrainReference grainReference, GrainState grainState);
Task ReadStateAsync(Type grainType, GrainReference grainReference, IGrainState grainState);
//Task WriteStateAsync(string grainType, GrainReference grainReference, GrainState grainState);
Task WriteStateAsync(Type grainType, GrainReference grainReference, IGrainState grainState);
//Task ClearStateAsync(string grainType, GrainReference grainReference, GrainState grainState);
Task ClearStateAsync(Type grainType, GrainReference grainReference, IGrainState grainState);
} EDIT : fixed a mistake i made with adding an interface with properties to a grain |
lgtm On 24 November 2015 at 11:30, Shay Hazor notifications@github.com wrote:
|
Few things I might add: public class GrainState<T> : IGrainState, new() This will preserve the current behavior that newly created grains can decide how to construct the 'initial state' on first activations (which in my opinion is useful). Also, combining issue #895 (both will break the current public interface IStorageProvider : IProvider
{
Logger Log { get; }
//Task ReadStateAsync(string grainType, GrainReference grainReference, GrainState grainState);
Task ReadStateAsync(Type grainType, GrainReference grainReference, Stream serializedGrainState);
//Task WriteStateAsync(string grainType, GrainReference grainReference, GrainState grainState);
Task WriteStateAsync(Type grainType, GrainReference grainReference, Stream serializedGrainState);
//Task ClearStateAsync(string grainType, GrainReference grainReference, GrainState grainState);
Task ClearStateAsync(Type grainType, GrainReference grainReference, Stream serializedGrainState);
} This will allow decoupling serialization/compression from the persistence layer (double win). And changing more attribues in the form: [StorageProvider(ProviderName="AzureStore"), SerializationProvider(ProviderName="MySerializer"), CompressionProvider(ProviderName="Snappy")] This will require to adjust these protected virtual Task ClearStateAsync()
{
return Storage.ClearStateAsync();
}
protected virtual Task WriteStateAsync()
{
return Storage.WriteStateAsync();
}
protected virtual Task ReadStateAsync()
{
return Storage.ReadStateAsync();
} |
You meant |
@dVakulen - Yes, I forgot the "where" keyword. Yes I agree that not every storage provider would be interested in receiving serialized values. But currently there is no way to decouple the read/write operations without creating a common abstract storage provider, since every storage provider is expecting to get "un-serialized" objects. |
By the way, guys - this is huge because, among other things, people can now do their domain models in F#, and use Orleans for the service/storage! Very powerful! Thank you! |
@armona Using of the parameterless constructor constraint on grain state will prevent users from using F# DU types, and will break some already existing code. |
Resolved by #1060. |
In days of old, Orleans' persistence model would generate
IGrainState
implementations for consumer. That functionality has since been removed and consumers instead store grain state in concrete classes which inherit fromGrainState
.I propose that we eliminate
GrainState
for the following reasons:AsDictionary
andSetAll
, which is not ideal.Grain<SomePoco>
)ETag
property to a stateful grain.The
ETag
property which motivatesGrainState
's existence can be moved to theGrain<T>
class instead. Storage Providers can be updated to operate onobject
instead ofGrainState
, giving them more flexibility over serialization and unifying them with the serialization model used by the rest of Orleans.The text was updated successfully, but these errors were encountered: