internal virtual async Task <DatabaseMetadatasCleaned> InternalDeleteMetadatasAsync(SyncContext context, SyncSet schema, SyncSetup setup, long timestampLimit, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { await this.InterceptAsync(new MetadataCleaningArgs(context, this.Setup, timestampLimit, connection, transaction), cancellationToken).ConfigureAwait(false); DatabaseMetadatasCleaned databaseMetadatasCleaned = new DatabaseMetadatasCleaned { TimestampLimit = timestampLimit }; foreach (var syncTable in schema.Tables) { // Create sync adapter var syncAdapter = this.GetSyncAdapter(syncTable, setup); var command = await syncAdapter.GetCommandAsync(DbCommandType.DeleteMetadata, connection, transaction); // Set the special parameters for delete metadata DbSyncAdapter.SetParameterValue(command, "sync_row_timestamp", timestampLimit); var rowsCleanedCount = await command.ExecuteNonQueryAsync().ConfigureAwait(false); // Check if we have a return value instead var syncRowCountParam = DbSyncAdapter.GetParameter(command, "sync_row_count"); if (syncRowCountParam != null) { rowsCleanedCount = (int)syncRowCountParam.Value; } // Only add a new table metadata stats object, if we have, at least, purged 1 or more rows if (rowsCleanedCount > 0) { var tableMetadatasCleaned = new TableMetadatasCleaned(syncTable.TableName, syncTable.SchemaName) { RowsCleanedCount = rowsCleanedCount, TimestampLimit = timestampLimit }; databaseMetadatasCleaned.Tables.Add(tableMetadatasCleaned); } } await this.InterceptAsync(new MetadataCleanedArgs(context, databaseMetadatasCleaned, connection), cancellationToken).ConfigureAwait(false); return(databaseMetadatasCleaned); }
public virtual async Task <(SyncContext syncContext, DatabaseMetadatasCleaned databaseMetadatasCleaned)> DeleteMetadatasAsync(SyncContext context, SyncSet schema, SyncSetup setup, long timestampLimit, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { DatabaseMetadatasCleaned databaseMetadatasCleaned = new DatabaseMetadatasCleaned { TimestampLimit = timestampLimit }; foreach (var syncTable in schema.Tables) { // get table builder var tableBuilder = this.GetTableBuilder(syncTable, setup); var tableHelper = tableBuilder.CreateTableBuilder(connection, transaction); // check if table exists // If not, kindly continue, without exception if (await tableHelper.NeedToCreateTableAsync().ConfigureAwait(false)) { continue; } // Create sync adapter var syncAdapter = tableBuilder.CreateSyncAdapter(connection, transaction); // Delete metadatas var rowsCleanedCount = await syncAdapter.DeleteMetadatasAsync(timestampLimit).ConfigureAwait(false); // Only add a new table metadata stats object, if we have, at least, purged 1 or more rows if (rowsCleanedCount > 0) { var tableMetadatasCleaned = new TableMetadatasCleaned(syncTable.TableName, syncTable.SchemaName); tableMetadatasCleaned.RowsCleanedCount = rowsCleanedCount; tableMetadatasCleaned.TimestampLimit = timestampLimit; this.Orchestrator.logger.LogDebug(SyncEventsId.MetadataCleaning, tableMetadatasCleaned); databaseMetadatasCleaned.Tables.Add(tableMetadatasCleaned); } } this.Orchestrator.logger.LogDebug(SyncEventsId.MetadataCleaning, databaseMetadatasCleaned); return(context, databaseMetadatasCleaned); }
/// <summary> /// Delete metadatas items from tracking tables /// </summary> /// <param name="timeStampStart">Timestamp start. Used to limit the delete metadatas rows from now to this timestamp</param> /// <param name="cancellationToken">Cancellation token</param> /// <param name="progress">Progress args</param> public virtual async Task <DatabaseMetadatasCleaned> DeleteMetadatasAsync(long timeStampStart, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) { if (!this.StartTime.HasValue) { this.StartTime = DateTime.UtcNow; } DatabaseMetadatasCleaned databaseMetadatasCleaned = null; // Get context or create a new one var ctx = this.GetContext(); using (var connection = this.Provider.CreateConnection()) { try { this.logger.LogInformation(SyncEventsId.MetadataCleaning, new { connection.Database, TimeStampStart = timeStampStart }); ctx.SyncStage = SyncStage.MetadataCleaning; // Open connection await this.OpenConnectionAsync(connection, cancellationToken).ConfigureAwait(false); // Create a transaction using (var transaction = connection.BeginTransaction()) { await this.InterceptAsync(new TransactionOpenedArgs(ctx, connection, transaction), cancellationToken).ConfigureAwait(false); await this.InterceptAsync(new MetadataCleaningArgs(ctx, this.Setup, timeStampStart, connection, transaction), cancellationToken).ConfigureAwait(false); // Create a dummy schema to be able to call the DeprovisionAsync method on the provider // No need columns or primary keys to be able to deprovision a table SyncSet schema = new SyncSet(this.Setup); (ctx, databaseMetadatasCleaned) = await this.Provider.DeleteMetadatasAsync(ctx, schema, this.Setup, timeStampStart, connection, transaction, cancellationToken, progress).ConfigureAwait(false); await this.InterceptAsync(new TransactionCommitArgs(ctx, connection, transaction), cancellationToken).ConfigureAwait(false); transaction.Commit(); } ctx.SyncStage = SyncStage.MetadataCleaned; await this.CloseConnectionAsync(connection, cancellationToken).ConfigureAwait(false); var args = new MetadataCleanedArgs(ctx, databaseMetadatasCleaned, connection); await this.InterceptAsync(args, cancellationToken).ConfigureAwait(false); this.ReportProgress(ctx, progress, args); } catch (Exception ex) { RaiseError(ex); } finally { if (connection != null && connection.State != ConnectionState.Closed) { connection.Close(); } } return(databaseMetadatasCleaned); } }
public MetadataCleanedArgs(SyncContext context, DatabaseMetadatasCleaned databaseMetadatasCleaned, DbConnection connection = null, DbTransaction transaction = null) : base(context, connection, transaction) { this.DatabaseMetadatasCleaned = databaseMetadatasCleaned; }
InternalDeleteMetadatasAsync( IEnumerable <IScopeInfo> scopeInfos, SyncContext context, long timestampLimit, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { context.SyncStage = SyncStage.ChangesApplying; var databaseMetadatasCleaned = new DatabaseMetadatasCleaned { TimestampLimit = timestampLimit }; await this.InterceptAsync(new MetadataCleaningArgs(context, scopeInfos, timestampLimit, connection, transaction), progress, cancellationToken).ConfigureAwait(false); // contains all tables already processed var doneList = new List <SetupTable>(); foreach (var scopeInfo in scopeInfos) { if (scopeInfo.Setup?.Tables == null || scopeInfo.Setup.Tables.Count <= 0) { continue; } foreach (var setupTable in scopeInfo.Setup.Tables) { var isDone = doneList.Any(t => t.EqualsByName(setupTable)); if (isDone) { continue; } // create a fake syncTable // Don't need anything else than table name to make a delete metadata clean up var syncTable = new SyncTable(setupTable.TableName, setupTable.SchemaName); // Create sync adapter var syncAdapter = this.GetSyncAdapter(syncTable, scopeInfo); var(command, _) = await syncAdapter.GetCommandAsync(DbCommandType.DeleteMetadata, connection, transaction); if (command != null) { // Set the special parameters for delete metadata DbSyncAdapter.SetParameterValue(command, "sync_row_timestamp", timestampLimit); await this.InterceptAsync(new DbCommandArgs(context, command, connection, transaction), progress, cancellationToken).ConfigureAwait(false); var rowsCleanedCount = await command.ExecuteNonQueryAsync().ConfigureAwait(false); // Check if we have a return value instead var syncRowCountParam = DbSyncAdapter.GetParameter(command, "sync_row_count"); if (syncRowCountParam != null) { rowsCleanedCount = (int)syncRowCountParam.Value; } // Only add a new table metadata stats object, if we have, at least, purged 1 or more rows if (rowsCleanedCount > 0) { var tableMetadatasCleaned = new TableMetadatasCleaned(syncTable.TableName, syncTable.SchemaName) { RowsCleanedCount = rowsCleanedCount, TimestampLimit = timestampLimit }; databaseMetadatasCleaned.Tables.Add(tableMetadatasCleaned); } command.Dispose(); } doneList.Add(setupTable); } } await this.InterceptAsync(new MetadataCleanedArgs(context, databaseMetadatasCleaned, connection), progress, cancellationToken).ConfigureAwait(false); return(context, databaseMetadatasCleaned); }