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);
        }
Exemple #2
0
        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);
            }
        }
Exemple #4
0
 public MetadataCleanedArgs(SyncContext context, DatabaseMetadatasCleaned databaseMetadatasCleaned, DbConnection connection = null, DbTransaction transaction = null)
     : base(context, connection, transaction)
 {
     this.DatabaseMetadatasCleaned = databaseMetadatasCleaned;
 }
Exemple #5
0
        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);
        }