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; } }
public static async Task HandlerAsync(InvocationContext invocationContext, Uri server, CancellationToken cancellationToken) { var region = new Region( 0, 0, Console.WindowWidth, Console.WindowHeight, true); List <AvailableVersion> availableVersions = null; ISchemaClient schemaClient = new SchemaClient(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); } }