Exemplo n.º 1
0
        /// <summary>
        /// The auto setup middleware invoke.
        /// </summary>
        /// <param name="httpContext">
        /// The http context.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public async Task InvokeAsync(HttpContext httpContext)
        {
            if (_setupOptions != null && _shellSettings.State == TenantState.Uninitialized)
            {
                // Try to acquire a lock before starting installation, it guaranties an atomic setup in multi instances environment.
                (var locker, var locked) = await _distributedLock.TryAcquireAutoSetupLockAsync(_lockOptions);

                if (!locked)
                {
                    throw new TimeoutException($"Fails to acquire an auto setup lock for the tenant: {_setupOptions.ShellName}");
                }

                await using var acquiredLock = locker;

                if (_shellSettings.State == TenantState.Uninitialized)
                {
                    var pathBase = httpContext.Request.PathBase;
                    if (!pathBase.HasValue)
                    {
                        pathBase = "/";
                    }

                    // Check if the tenant was installed by another instance.
                    var settings = await _shellSettingsManager.LoadSettingsAsync(_shellSettings.Name);

                    if (settings.State != TenantState.Uninitialized)
                    {
                        await _shellHost.ReloadShellContextAsync(_shellSettings, eventSource : false);

                        httpContext.Response.Redirect(pathBase);

                        return;
                    }

                    var setupService = httpContext.RequestServices.GetRequiredService <ISetupService>();
                    if (await SetupTenantAsync(setupService, _setupOptions, _shellSettings))
                    {
                        if (_setupOptions.IsDefault)
                        {
                            // Create the rest of the shells for further on demand setup.
                            foreach (var setupOptions in _options.Tenants)
                            {
                                if (_setupOptions != setupOptions)
                                {
                                    await CreateTenantSettingsAsync(setupOptions);
                                }
                            }
                        }

                        httpContext.Response.Redirect(pathBase);

                        return;
                    }
                }
            }

            await _next.Invoke(httpContext);
        }