dotnet / orleans

Cloud Native application framework for .NET
https://docs.microsoft.com/dotnet/orleans
MIT License
10.07k stars 2.03k forks source link

[Question] What is the suggested pattern to use and query multiple unique keys in a single Grain? #3877

Closed Xanatus closed 6 years ago

Xanatus commented 6 years ago

Lets say I have a simple Grain for an user account that stores data like this:

For every user:

Now lets say I want to be able to do all of this:

  1. Get Name from UserID
  2. Get UserID from Name
  3. Get Name and/or ID from Email Addr

Now what is the best approach here to store the data in a scalable way (not a single grain for all users), gaurantee each Fields uniqueness and also be able to query them using Orleans?

I assume it's not possible with Orleans by itself, unless I make multiple mapping Grains that are shitty to maintain and require data duplications, but what would be the suggested way to implement this functionalty?

enewnham commented 6 years ago

I know of https://github.com/OrleansContrib/Orleans.Indexing

I have not personally tried it, and there is a big warning stating don't use it in production, but that hasn't stopped the Javascript community, so why should it stop us? lol.

I traditionally have a UserActor, and a UsersActor, the UsersActor keeps a dictionary/hashmap of GrainReferences... Something like

public class UsersActor : Actor, IUsersActor
{
    private readonly Dictionary<int, IUserActor> _usersById ...
    private readonly Dictionary<string, IUserActor> _usersByName ...

    public async Task<IUserActor> GetById( int id ) => Task.FromResult( _usersById[id]);

    public async Task<IUserActor> GetByName( string name ) => Task.FromResult( _usersByName[name] )
}

From there, you are going to need to wire up some broadcasting stream events to make sure everything is kept in sync, like if you delete a User, the UsersActor will need to be notified about it... which sucks.

sergeybykov commented 6 years ago

I assume it's not possible with Orleans by itself

Not today. There is an effort underway to bring https://github.com/OrleansContrib/Orleans.Indexing into the main codebase.

Other than that, there's a cheating workaround option of querying grain ID directly from the grain state storage. Feasibility of that, of course, depends on what kind of storage tech is used for grain state.

Xanatus commented 6 years ago

@enewnham That's not what i want to do since it looks like a very bad anti pattern to the actor model.

@sergeybykov Good to see this is beeing worked on. I hope it will make it into orleans better sooner than later as this seems a necessity for a framework that is supposed to replace manual DB interactions.

I guess querying directly from the storage is my best bet for now. Is there an easy way to get the reference to an IStorageProvider from within a grain (since i'm already using a custom storage provider, I guess I could just extend it) or do I need to figure something out with DI?

sergeybykov commented 6 years ago

this seems a necessity for a framework that is supposed to replace manual DB interactions.

Well, we never quite claimed that. Although https://www.microsoft.com/en-us/research/publication/indexing-in-an-actor-oriented-database/ talks about "Actor Oriented DB". :-)

Is there an easy way to get the reference to an IStorageProvider from within a grain (since i'm already using a custom storage provider, I guess I could just extend it) or do I need to figure something out with DI?

DI is the preferred way.