示例#1
0
        protected override TenantDistinguisher GetTenantDistinguisher(HttpContext context)
        {
            var host     = context.Request.Host.Host.ToLowerInvariant();
            var identity = new TenantDistinguisher(host);

            return(identity);
        }
        protected override TenantDistinguisher GetTenantDistinguisher(HttpContext context)
        {
            var value    = GetHostNameWithPortNumber(context);
            var identity = new TenantDistinguisher(value);

            return(identity);
        }
 public Task <TenantShell <TTenant> > Get(TenantDistinguisher identifier)
 {
     return(Task.Run(() =>
     {
         return _factory(identifier);
     }));
 }
示例#4
0
 public ITenantShellAccessor <TTenant> WithTenant(TenantDistinguisher tenantDistinguisher)
 {
     CurrentTenantShell = new Lazy <Task <TenantShell <TTenant> > >(async() =>
     {
         return(await _tenantResolver.ResolveTenant(tenantDistinguisher, _tenantFactory));
     });
     return(this);
 }
示例#5
0
        public async Task <TenantShell <TTenant> > ResolveTenant(TenantDistinguisher identifier, ITenantShellFactory <TTenant> tenantFactory)
        {
            TenantShell <TTenant> result;

            if (_cache.TryGetValue(identifier, out result))
            {
                return(result);
            }

            try
            {
                await _semaphore.WaitAsync();

                // Double locking
                if (_cache.TryGetValue(identifier, out result))
                {
                    return(result);
                }

                var tenantResult = await tenantFactory.Get(identifier);

                if (tenantResult == null)
                {
                    // don't create null shell tenants - future requests with this identifier will still not find a shell for the tenant,
                    // so they will keep flowing through to ask the factory for the tenant. This is better if you are creating new tenants dynamically and a request is
                    // recieved with the tenants identifier, before the tenant has been set up in the source. It means the request will resolve to a null
                    // tenant for a while (factory may keep returning null), and eventually when a tenant is actually returned from the factory, a new tenant shell will then be created and added to
                    // the cache, at which point the factory will stop being used for subsequent requests.
                    return(null);
                }

                // We got a new shell tenant, so add it to the cache under its identifier, and any additional identifiers.
                _cache.AddOrUpdate(identifier, tenantResult, (a, b) => { return(tenantResult); });

                bool distinguisherFound = false;
                foreach (var item in tenantResult.Distinguishers)
                {
                    if (item.Equals(identifier))
                    {
                        distinguisherFound = true;
                        continue;
                    }
                    _cache.AddOrUpdate(item, tenantResult, (a, b) => { return(tenantResult); });
                }

                if (!distinguisherFound)
                {
                    tenantResult.Distinguishers.Add(identifier);
                }

                return(tenantResult);
            }
            finally
            {
                _semaphore.Release();
            }
        }
        public virtual Task <TenantDistinguisher> IdentifyContext()
        {
            TenantDistinguisher identity = null;

            if (HttpContextAccessor.HttpContext != null)
            {
                identity = GetTenantDistinguisher(HttpContextAccessor.HttpContext);
            }
            return(Task.FromResult(identity));
        }
示例#7
0
 public bool TryGetValue(TenantDistinguisher key, out TenantShell <TTenant> value)
 {
     return(_mappings.TryGetValue(key, out value));
 }
示例#8
0
 public TenantShell <TTenant> AddOrUpdate(TenantDistinguisher key,
                                          TenantShell <TTenant> addValue,
                                          Func <TenantDistinguisher, TenantShell <TTenant>, TenantShell <TTenant> > updateValueFactory)
 {
     return(_mappings.AddOrUpdate(key, addValue, updateValueFactory));
 }
        public async Task <TenantShell <TTenant> > ResolveTenant(TenantDistinguisher identifier, ITenantShellFactory <TTenant> tenantFactory)
        {
            TenantShell <TTenant> result;

            if (_cache.TryGetValue(identifier, out result))
            {
                return(result);
            }

            try
            {
                await _semaphore.WaitAsync();

                // Check again incase this is another thread that got queued at the semephor.
                if (_cache.TryGetValue(identifier, out result))
                {
                    return(result);
                }

                var tenantResult = await tenantFactory.Get(identifier);

                if (tenantResult == null)
                {
                    // don't create null shell tenants - future requests with this identifier will still not find a shell for the tenant,
                    // so they will keep flowing through to ask the factory for the tenant. This is better if you are creating new tenants dynamically and a request is
                    // recieved with the tenants identifier, before the tenant has been set up in the source. It means the request will resolve to a null
                    // tenant for a while (factory may keep returning null), and eventually when a tenant is actually returned from the factory, a new tenant shell will then be created and added to
                    // the cache, at which point the factory will stop being used for subsequent requests.
                    return(null);
                }

                //if (CreateNullTenants)
                //{
                // create a shell for the null tenant, and add to cache. Future requests with same identifier
                // will yeild the cached shell for the null tenant.
                //var defaultTenantValue = default(TTenant);
                //var shellForNullTenant = new TenantShell<TTenant>(defaultTenantValue, identifier);
                //_mappings.AddOrUpdate(identifier, shellForNullTenant, (a, b) => { return shellForNullTenant; });
                //return shellForNullTenant;

                ////  }

                // We got a new shell tenant, so add it to the cache under its identifier, and any additional identifiers.
                _cache.AddOrUpdate(identifier, tenantResult, (a, b) => { return(tenantResult); });
                bool distinguisherFound = false;
                foreach (var item in tenantResult.Distinguishers)
                {
                    if (item == identifier)
                    {
                        distinguisherFound = true;
                    }
                    _cache.AddOrUpdate(item, tenantResult, (a, b) => { return(tenantResult); });
                }

                if (!distinguisherFound)
                {
                    tenantResult.Distinguishers.Add(identifier);
                }

                return(tenantResult);
                // todo
            }
            finally
            {
                _semaphore.Release();
            }
        }