-
-
Notifications
You must be signed in to change notification settings - Fork 23
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
Default IConfiguration based tenant implementation #68
Comments
This feature will need to evolve a bit, as I found I need to map different startups. For example, I'd like something like the following: mappings.json:
and
So, when the "IsSystemSetup" condition returns false, this enables the following mapping:
Which matches all domains, and specifies "Startup: "SystemSetup" as the startup type. And you'd write that something like:
Then
I'm thinking of referring to these classes as forms of
But for now, that part will be beyond scope. |
This will come in two parts.
The first part will be to provide a default way out of the box for identifying tenants that is based on configurable pattern matching on the incoming request Authority (essentially hostname or ip address:port portion). This is because this is the most common way tenants are mapped in my experience.
To achieve this, we will first need to model a class structure to use with the Microsoft.Extensions.Options system and that can therefore be bound to IConfiguration.
I am thinking of something like the following:
Note
TKey
- i've left that generic because this key will be then be used to lookup the current TenantShell for an inbound request from a cache (if not present the tenant's TenantShell is initialised), so the datatype chosen can have an impact on performance in terms of lookup from the cache. Some might be happy with a GUID, some might want an integer, so a small int for those with not many tenants etc etc. The important thing is that this will be a unique value that identifies the tenant.The patterns are glob patterns (I use my own dotnet.glob library for evaluating these), that will be evaluated against the inbound request Authority: https://docs.microsoft.com/en-us/dotnet/api/system.uri.authority?view=netcore-3.1 when any pattern matches, then the tenant is identified, and the corresponding tenant Key is returned as an identifier for that tenant.
This class structure will map to the following json config:
If you used the same TKey value for multiple entries in the mapping, then they would in effect map to the same tenant so you might as well condense the mapping into one, for example:
might as well be:
In order to start using this you'd do something like this in startup:
This will register a custom IdentifierFactory that will have an
IOptionsMonitor<TenantMappingOptions>
injected, that it will use to evaluate the patterns on an incoming request and to return the matching tenants TKey value as the TenantIdentifier. This basically has to be aUri
but it can be any value, so in this case theUri
will contain the TKey as a string in some portion of it easily retreived. If a matching TKey cannot be found it will set a special string value / constant instead of the key value, so that no match can be determined.Because this uses IOptionsMontitor.CurrentValue - it will always be using the latest configuration when evaluating an incoming request, this means the configuration can change whilst the application is running and it should take effect immediately without a restart.
The next piece of the puzzle is to provide a new base class for a
TenantShellFactory
that can load a TenantShell based on the TKey supplied in the TenantIdentifier when using this new mechanism.You'd implement this class something like so in your application:
You could also override
GetDefaultTenant
if you still want to create a default instance ofTTenant
class to represent a non-mapped tenant. The default behaviour will be to return a instance NULL which means if injectingTask<TTenant>
into controllers etc, if the current tenant has not been mapped successfully, theTask.Result
will be a NULL instance. By overridingGetDefaultTenant
you could return anew TTenant {Name = "Unknown"}
etc or whatever you need.So usage in your application then becomes something like:
Note: MapTenantsByRequestAuthority is sugar that does the equivalent of:
Most likely the default non generic overload will be GUID based keys:
What does this enable
Once dotnettency can be hooked up to the
IConfiguration
/IOptions
system like this, you could easily plugin something like apache zookepper for managing tenants accross a cluster.For example, if a new tenant is added to the zookeeper record, this will be distributed and become available to all nodes.
That would be a case of using something like this: https://github.com/fglaeser/Extensions.Configuration.Zookeeper for this.
The text was updated successfully, but these errors were encountered: