Multitenancy and IAppSettings pattern

This question is really primarily for the maintainers/designers of ServiceStack. Since I’d like to identify and repeat a pattern if it exists, in the ServiceStack.Webhooks project.

My question is about what pattern to use to handle configuration using IAppSettings to support consumers with multi-tenanted services.

Where the general architectural pattern is to change the instance of the IAppSettings for each IRequest. So that any configuration that is read using IAppSettings in the scope of any IRequest, will read from the configuration setting for the specific tenant for that request.

The scheme works when dependencies read configuration settings every time a setting value is needed.

So for example (notionally), I might have a dependency like this:

internal class StorageTableReader
{
    private IAppSettings settings;

    public StorageTableReader(IAppSettings settings)
    {
        this.settings = settings;
    }

    public string Get(string key)
    {
        var connectionString = this.settings.Get<string>("Storage.ConnectionString");
        var connection = CreateStorage(connectionString);

        return connection.Get(key);
    }
}

So the general pattern requires that the code fetches the "Storage.ConnectionString" from IAppSettings each time it is needed. And, as long as that is the case, the correct value of "Storage.ConnectionString" for each tenant will be used each time.

This example is hypothetical, because in practice, there will be caching of configuration going on, but it shows the general idea.

Now, my question is this. For many of the plugins/dependencies that we use in ServiceStack, we see their ctors taking an instance of IAppSettings, and initializing public variables at instantiation. Then, some of them provide Action<T> to override the initialized values in some kind of handler.

Is there a general known pattern that I can adopt in the various plugins/dependencies of ServiceStack.Webhooks, that allows consumers to either let the ctor do the default thing for them, that applies in most (single-tenanted) scenarios, but that would also support consumers who employed the general pattern above for multi-tenancy?

I’ve got a number of classes in ServiceStack.Webhooks that could benefit from a general pattern for handling IAppSettings, and more than anything I wanted it to follow in lock-step with the rest of the ServiceStack libraries for consistency (if that is achievable).

Can you suggest and describe a general pattern or point me to one already in ServiceStack?

Any provider that isn’t retrieved at runtime with the IRequest isn’t “multi-tenant aware”. i.e. You’re not going to be able to configure a multi-tenant IAppSettings injected in your classes as it’s a static dependency registered in your AppHost which can’t be configured to use the tenant that’s only known at runtime.

You would need to use a configuration that is multi-tenant aware like the GetRuntimeConfig API added earlier which allows different JWT Configuration at runtime.

The easiest approach for any multi-tenant dependency is to register a factory which accepts an IRequest and returns a multi-tenant configured instance, which for configuration I’d just return a POCO configuration class:

public class MultitentAppConfig
{
    public AppConfig GetTenantConfig(IRequest req) => ...
}

public class MyServices : Service
{
    public MultitentAppConfig AppConfig { get; set; }

    public object Any(MyRequest) 
    {
        var tenantConifg = AppConfig.GetTenantConfig(Request);
    }
}

You could use the same approach if you wanted to re-use the IAppSettings API:

public class MultitenantAppSettings
{
    public IAppSettings GetTenantAppSettings(IRequest request) => ...
}