Esempio n. 1
0
        /// <summary>
        /// Internal load scope routine
        /// </summary>
        internal async Task <T> InternalGetScopeAsync <T>(SyncContext ctx, DbScopeType scopeType, string scopeName, DbScopeBuilder scopeBuilder, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) where T : class
        {
            if (typeof(T) != typeof(ScopeInfo) && typeof(T) != typeof(ServerScopeInfo))
            {
                throw new NotImplementedException($"Type {typeof(T).Name} is not implemented when trying to get a single instance");
            }

            var scopes = await InternalGetAllScopesAsync <T>(ctx, scopeType, scopeName, scopeBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            if (scopes == null || scopes.Count <= 0)
            {
                scopes = new List <T>();

                // create a new scope id for the current owner (could be server or client as well)
                T scope = scopeType switch
                {
                    DbScopeType.Client => new ScopeInfo {
                        Id = Guid.NewGuid(), Name = scopeName, IsNewScope = true, LastSync = null, LastServerSyncTimestamp = null, LastSyncTimestamp = null, Version = SyncVersion.Current.ToString()
                    } as T,
                    DbScopeType.Server => new ServerScopeInfo {
                        Name = scopeName, LastCleanupTimestamp = 0, Version = SyncVersion.Current.ToString()
                    } as T,
                    _ => throw new NotImplementedException($"Type {typeof(T).Name} is not implemented when trying to get a single instance")
                };

                scope = await this.InternalSaveScopeAsync(ctx, scopeType, scope, scopeBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

                scopes.Add(scope);
            }

            // get first scope
            var localScope = scopes.FirstOrDefault();

            if (typeof(T) == typeof(ScopeInfo))
            {
                //check if we have already a good last sync. if no, treat it as new
                scopes.ForEach(sc => (sc as ScopeInfo).IsNewScope = (sc as ScopeInfo).LastSync == null);

                var scopeInfo = localScope as ScopeInfo;

                if (scopeInfo?.Schema != null)
                {
                    scopeInfo.Schema.EnsureSchema();
                }

                var scopeLoadedArgs = new ScopeLoadedArgs <ScopeInfo>(ctx, scopeName, scopeType, scopeInfo, connection, transaction);
                await this.InterceptAsync(scopeLoadedArgs, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                var scopeInfo = localScope as ServerScopeInfo;

                if (scopeInfo?.Schema != null)
                {
                    scopeInfo.Schema.EnsureSchema();
                }

                var scopeLoadedArgs = new ScopeLoadedArgs <ServerScopeInfo>(ctx, scopeName, scopeType, scopeInfo, connection, transaction);
                await this.InterceptAsync(scopeLoadedArgs, cancellationToken).ConfigureAwait(false);
            }

            return(localScope);
        }
Esempio n. 2
0
        /// <summary>
        /// Get the local configuration, ensures the local scope is created
        /// </summary>
        /// <returns>current context, the local scope info created or get from the database and the configuration from the client if changed </returns>
        public async Task <ScopeInfo> GetClientScopeAsync(CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        {
            if (!this.StartTime.HasValue)
            {
                this.StartTime = DateTime.UtcNow;
            }

            // Get context or create a new one
            var       ctx        = this.GetContext();
            ScopeInfo localScope = null;

            using (var connection = this.Provider.CreateConnection())
            {
                try
                {
                    ctx.SyncStage = SyncStage.ScopeLoading;

                    // Open connection
                    await this.OpenConnectionAsync(connection, cancellationToken).ConfigureAwait(false);

                    using (var transaction = connection.BeginTransaction())
                    {
                        await this.InterceptAsync(new TransactionOpenedArgs(ctx, connection, transaction), cancellationToken).ConfigureAwait(false);

                        await this.InterceptAsync(new ScopeLoadingArgs(ctx, this.ScopeName, this.Options.ScopeInfoTableName, connection, transaction), cancellationToken).ConfigureAwait(false);

                        ctx = await this.Provider.EnsureClientScopeAsync(ctx, this.Options.ScopeInfoTableName, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

                        (ctx, localScope) = await this.Provider.GetClientScopeAsync(ctx, this.Options.ScopeInfoTableName, this.ScopeName, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

                        await this.InterceptAsync(new TransactionCommitArgs(ctx, connection, transaction), cancellationToken).ConfigureAwait(false);

                        transaction.Commit();
                    }

                    ctx.SyncStage = SyncStage.ScopeLoaded;

                    await this.CloseConnectionAsync(connection, cancellationToken).ConfigureAwait(false);

                    var scopeArgs = new ScopeLoadedArgs(ctx, localScope, connection);
                    await this.InterceptAsync(scopeArgs, cancellationToken).ConfigureAwait(false);

                    this.ReportProgress(ctx, progress, scopeArgs);
                }
                catch (Exception ex)
                {
                    RaiseError(ex);
                }
                finally
                {
                    if (connection != null && connection.State == ConnectionState.Open)
                    {
                        connection.Close();
                    }
                }

                this.logger.LogInformation(SyncEventsId.GetClientScope, localScope);

                return(localScope);
            }
        }