I'm building a multi-tenant application using a RavenDB identity store that connects to a different database for each tenant's users.
I register one store, and then use dependency injection to create an IAsyncSession for each tenant:
services.AddScoped(sp => sp.GetRequiredService<IDocumentStore>().OpenAsyncSession(sp.GetService<IOptions<UserStoreOptions>>()?.Value?.DatabaseName));
The library I'm using creates a Compare Exchange Value for each user to reserve the username, but because it's doing the operation against the document store instead of the session, it doesn't know the name of the database I intend, so it's executing it against the default database. Compare exchange values get created in the default database, while users are created in the tenant's database
I'm happy to submit PRs to the library to fix this behavior, just need some guidance.
Solutions and issued:
1. Call .ForDatabase here: DbSession.Advanced.DocumentStore.Operations.SendAsync
- I haven't found a way to get the current database the session is targetting, since Database is an internal property. I can get it if I parse the identifier, but that's too hacky
2. Add an explicit configurable IOptions, and put the database name in there, then modify all the code to use that value if it's set.
- Not sure if the dev of the library would be in favor of it, but likely best option
3. Use session.Advanced.ClusterTransaction.CreateCompareExchangeValue(compareExchangeKey, user.Id);
- Since the IAsyncSession is injected, I can't specify the ClusterWide option in the session constructor, and I can't make every IAsyncSession I inject be cluster-wide since other things depend on it
4. Get fancy with injection and have it figure out the right session to customize based on who's asking for it
- This just sounds like trouble in the long-run, I don't like it
5. Create a separate IDocumentStore for each tenant
- I'm concerned about unnecessary memory usage, extra connections to the ravendb server for things like subscriptions, duplicate cache? Having IAsyncSessions injected sounds a lot lighter than IDocumentStore objects. Let me know if not the case