Beispiel #1
0
        private async Task HandlerAsync(InvocationContext invocationContext, Uri server, CancellationToken cancellationToken)
        {
            var region = new Region(
                0,
                0,
                Console.WindowWidth,
                Console.WindowHeight,
                true);

            List <AvailableVersion> availableVersions = null;

            _schemaClient.SetUri(server);

            try
            {
                availableVersions = await _schemaClient.GetAvailabilityAsync(cancellationToken);

                // To ensure that schema version null/0 is not printed
                if (availableVersions.First().Id == 0)
                {
                    availableVersions.RemoveAt(0);
                }
            }
            catch (SchemaManagerException ex)
            {
                CommandUtils.PrintError(ex.Message);
                return;
            }
            catch (HttpRequestException)
            {
                CommandUtils.PrintError(string.Format(Resources.RequestFailedMessage, server));
                return;
            }

            var tableView = new TableView <AvailableVersion>
            {
                Items = availableVersions,
            };

            tableView.AddColumn(
                cellValue: availableVersion => availableVersion.Id,
                header: new ContentView("Version"));

            tableView.AddColumn(
                cellValue: availableVersion => availableVersion.ScriptUri,
                header: new ContentView("Script"));

            tableView.AddColumn(
                cellValue: availableVersion => string.IsNullOrEmpty(availableVersion.DiffUri) ? "N/A" : availableVersion.DiffUri,
                header: new ContentView("Diff"));

            var consoleRenderer = new ConsoleRenderer(
                invocationContext.Console,
                mode: invocationContext.BindingContext.OutputMode(),
                resetAfterRender: true);

            using (var screen = new ScreenView(renderer: consoleRenderer))
            {
                screen.Child = tableView;
                screen.Render(region);
            }
        }
Beispiel #2
0
        /// <inheritdoc />
        public virtual async Task ApplySchema(string connectionString, Uri server, MutuallyExclusiveType exclusiveType, CancellationToken cancellationToken = default)
        {
            EnsureArg.IsNotNullOrEmpty(connectionString, nameof(connectionString));
            EnsureArg.IsNotNull(server, nameof(server));
            EnsureArg.IsNotNull(exclusiveType, nameof(exclusiveType));

            _schemaClient.SetUri(server);

            try
            {
                _sqlServerDataStoreConfiguration.ConnectionString = connectionString;

                // Base schema is required to run the schema migration tool.
                // This method also initializes the database if not initialized yet.
                await _baseSchemaRunner.EnsureBaseSchemaExistsAsync(cancellationToken);

                // If InstanceSchema table is just created(as part of baseSchema), it takes a while to insert a version record
                // since the Schema job polls and upserts at the specified interval in the service.
                await _baseSchemaRunner.EnsureInstanceSchemaRecordExistsAsync(cancellationToken);

                var availableVersions = (await GetAvailableSchema(server, cancellationToken)).ToList();

                // If the user hits apply command multiple times in a row, then the service schema job might not poll the updated available versions
                // so there are retries to give it a fair amount of time.
                int attemptCount = 1;

                availableVersions = await Policy.Handle<SchemaManagerException>()
                .WaitAndRetryAsync(
                    retryCount: RetryAttempts,
                    sleepDurationProvider: (retryCount) => RetrySleepDuration,
                    onRetry: (exception, retryCount) =>
                    {
                        _logger.LogError(exception, string.Format(Resources.RetryCurrentSchemaVersion, attemptCount++, RetryAttempts));
                    })
                .ExecuteAsync(token => FetchUpdatedAvailableVersionsAsync(token), cancellationToken);

                if (availableVersions.Count() == 1)
                {
                    _logger.LogError(Resources.AvailableVersionsDefaultErrorMessage);
                    return;
                }

                // Removes the current version since the first available version is always the current version which is already applied.
                availableVersions.RemoveAt(0);

                var targetVersion = exclusiveType.Next == true ? availableVersions.First().Id :
                                                                 exclusiveType.Latest == true ? availableVersions.Last().Id :
                                                                                                        exclusiveType.Version;

                availableVersions = availableVersions.Where(availableVersion => availableVersion.Id <= targetVersion)
                    .ToList();

                // Checking the specified version is not out of range of available versions
                if (availableVersions.Count < 1 || targetVersion < availableVersions.First().Id || targetVersion > availableVersions.Last().Id)
                {
                    throw new SchemaManagerException(string.Format(Resources.SpecifiedVersionNotAvailable, targetVersion));
                }

                await ValidateVersionCompatibility(availableVersions.Last().Id, cancellationToken);

                if (availableVersions.First().Id == 1)
                {
                    // Upgrade schema directly to the latest schema version
                    _logger.LogInformation(string.Format(Resources.SchemaMigrationStartedMessage, availableVersions.Last().Id));

                    string script = await GetScriptAsync(1, availableVersions.Last().ScriptUri, cancellationToken);
                    await UpgradeSchemaAsync(availableVersions.Last().Id, script, cancellationToken);
                    return;
                }

                foreach (AvailableVersion availableVersion in availableVersions)
                {
                    int executingVersion = availableVersion.Id;

                    _logger.LogInformation(string.Format(Resources.SchemaMigrationStartedMessage, executingVersion));

                    attemptCount = 1;

                    await Policy.Handle<SchemaManagerException>()
                        .WaitAndRetryAsync(
                            retryCount: RetryAttempts,
                            sleepDurationProvider: (retryCount) => RetrySleepDuration,
                            onRetry: (exception, retryCount) =>
                            {
                                _logger.LogError(exception, string.Format(Resources.RetryCurrentVersions, attemptCount++, RetryAttempts));
                            })
                        .ExecuteAsync(token => ValidateInstancesVersionAsync(executingVersion, token), cancellationToken);

                    string script = await GetScriptAsync(executingVersion, availableVersion.ScriptUri, cancellationToken, availableVersion.DiffUri);

                    await UpgradeSchemaAsync(executingVersion, script, cancellationToken);
                }
            }
            catch (Exception ex) when (ex is SchemaManagerException || ex is InvalidOperationException)
            {
                _logger.LogError(ex, ex.Message);
                return;
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, string.Format(Resources.RequestFailedMessage, server));
                return;
            }
            catch (Exception ex)
            {
                if (ex is SqlException || ex is ExecutionFailureException)
                {
                    _logger.LogError(ex, string.Format(Resources.QueryExecutionErrorMessage, ex.Message));
                    return;
                }

                throw;
            }
        }
Beispiel #3
0
        private async Task HandlerAsync(InvocationContext invocationContext, Uri server, string connectionString, CancellationToken cancellationToken = default)
        {
            var region = new Region(
                0,
                0,
                Console.WindowWidth,
                Console.WindowHeight,
                true);
            List <CurrentVersion> currentVersions = null;

            _schemaClient.SetUri(server);

            try
            {
                _sqlServerDataStore.ConnectionString = connectionString;

                // Base schema is required to run the schema migration tool.
                // This method also initializes the database if not initialized yet.
                await _baseSchemaRunner.EnsureBaseSchemaExistsAsync(cancellationToken);

                // If InstanceSchema table is just created(as part of baseSchema), it takes a while to insert a version record
                // since the Schema job polls and upserts at the specified interval in the service.
                await _baseSchemaRunner.EnsureInstanceSchemaRecordExistsAsync(cancellationToken);

                currentVersions = await _schemaClient.GetCurrentVersionInformationAsync(cancellationToken);
            }
            catch (SchemaManagerException ex)
            {
                CommandUtils.PrintError(ex.Message);
                return;
            }
            catch (HttpRequestException)
            {
                CommandUtils.PrintError(string.Format(Resources.RequestFailedMessage, server));
                return;
            }

            var tableView = new TableView <CurrentVersion>
            {
                Items = currentVersions,
            };

            tableView.AddColumn(
                cellValue: currentVersion => currentVersion.Id,
                header: new ContentView("Version"));

            tableView.AddColumn(
                cellValue: currentVersion => currentVersion.Status,
                header: new ContentView("Status"));

            tableView.AddColumn(
                cellValue: currentVersion => string.Join(", ", currentVersion.Servers),
                header: new ContentView("Servers"));

            var consoleRenderer = new ConsoleRenderer(
                invocationContext.Console,
                mode: invocationContext.BindingContext.OutputMode(),
                resetAfterRender: true);

            using (var screen = new ScreenView(renderer: consoleRenderer))
            {
                screen.Child = tableView;
                screen.Render(region);
            }
        }