Пример #1
0
        public ApplyCommand(
            SqlServerDataStoreConfiguration sqlServerDataStoreConfiguration,
            BaseSchemaRunner baseSchemaRunner,
            ISchemaManagerDataStore schemaManagerDataStore,
            ISchemaClient schemaClient)
            : base(CommandNames.Apply, Resources.ApplyCommandDescription)
        {
            AddOption(CommandOptions.ConnectionStringOption());
            AddOption(CommandOptions.ServerOption());
            AddOption(CommandOptions.VersionOption());
            AddOption(CommandOptions.NextOption());
            AddOption(CommandOptions.LatestOption());
            AddOption(CommandOptions.ForceOption());

            Handler = CommandHandler.Create(
                (string connectionString, Uri server, MutuallyExclusiveType type, bool force, CancellationToken token)
                => HandlerAsync(connectionString, server, type, force, token));

            Argument.AddValidator(symbol => Validators.RequiredOptionValidator.Validate(symbol, CommandOptions.ConnectionStringOption(), Resources.ConnectionStringRequiredValidation));
            Argument.AddValidator(symbol => Validators.RequiredOptionValidator.Validate(symbol, CommandOptions.ServerOption(), Resources.ServerRequiredValidation));
            Argument.AddValidator(symbol => Validators.MutuallyExclusiveOptionValidator.Validate(symbol, new List <Option> {
                CommandOptions.VersionOption(), CommandOptions.NextOption(), CommandOptions.LatestOption()
            }, Resources.MutuallyExclusiveValidation));

            EnsureArg.IsNotNull(sqlServerDataStoreConfiguration);
            EnsureArg.IsNotNull(baseSchemaRunner);
            EnsureArg.IsNotNull(schemaManagerDataStore);
            EnsureArg.IsNotNull(schemaClient);

            _sqlServerDataStoreConfiguration = sqlServerDataStoreConfiguration;
            _baseSchemaRunner       = baseSchemaRunner;
            _schemaManagerDataStore = schemaManagerDataStore;
            _schemaClient           = schemaClient;
        }
Пример #2
0
        public BaseSchemaRunnerTests(ITestOutputHelper output)
            : base(output)
        {
            var sqlConnectionFactory = new DefaultSqlConnectionFactory(ConnectionStringProvider);

            _dataStore = new SchemaManagerDataStore(sqlConnectionFactory);

            _runner = new BaseSchemaRunner(sqlConnectionFactory, _dataStore, ConnectionStringProvider, NullLogger <BaseSchemaRunner> .Instance);
        }
Пример #3
0
        public CurrentCommand(
            BaseSchemaRunner baseSchemaRunner,
            SqlServerDataStoreConfiguration sqlServerDataStore,
            ISchemaClient schemaClient)
            : base(CommandNames.Current, Resources.CurrentCommandDescription)
        {
            AddOption(CommandOptions.ServerOption());
            AddOption(CommandOptions.ConnectionStringOption());

            Handler = CommandHandler.Create(
                (InvocationContext context, Uri server, string connectionString, CancellationToken token)
                => HandlerAsync(context, server, connectionString, token));

            Argument.AddValidator(symbol => Validators.RequiredOptionValidator.Validate(symbol, CommandOptions.ConnectionStringOption(), Resources.ConnectionStringRequiredValidation));
            Argument.AddValidator(symbol => Validators.RequiredOptionValidator.Validate(symbol, CommandOptions.ServerOption(), Resources.ServerRequiredValidation));

            EnsureArg.IsNotNull(baseSchemaRunner);
            EnsureArg.IsNotNull(sqlServerDataStore);
            EnsureArg.IsNotNull(schemaClient);

            _baseSchemaRunner   = baseSchemaRunner;
            _sqlServerDataStore = sqlServerDataStore;
            _schemaClient       = schemaClient;
        }
        public static 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;
            ISchemaClient         schemaClient    = new SchemaClient(server);

            try
            {
                // Base schema is required to run the schema migration tool.
                // This method also initializes the database if not initialized yet.
                await BaseSchemaRunner.EnsureBaseSchemaExistsAsync(connectionString, 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(connectionString, 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);
            }
        }
        public static async Task HandlerAsync(string connectionString, Uri server, MutuallyExclusiveType exclusiveType, bool force, CancellationToken cancellationToken = default)
        {
            ISchemaClient schemaClient = new SchemaClient(server);

            if (force && !EnsureForce())
            {
                return;
            }

            try
            {
                // Base schema is required to run the schema migration tool.
                // This method also initializes the database if not initialized yet.
                await BaseSchemaRunner.EnsureBaseSchemaExistsAsync(connectionString, 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(connectionString, cancellationToken);

                availableVersions = await schemaClient.GetAvailabilityAsync(cancellationToken);

                // 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;

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

                if (availableVersions.Count == 1)
                {
                    CommandUtils.PrintError(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));
                }

                if (!force)
                {
                    await ValidateVersionCompatibility(schemaClient, availableVersions.Last().Id, cancellationToken);
                }

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

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

                    return;
                }

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

                    Console.WriteLine(string.Format(Resources.SchemaMigrationStartedMessage, executingVersion));

                    if (!force)
                    {
                        attemptCount = 1;

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

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

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

                if (ex is SchemaManagerException || ex is InvalidOperationException)
                {
                    CommandUtils.PrintError(ex.Message);
                    return;
                }

                throw;
            }
        }