Beispiel #1
0
 public virtual void OnOperationCompleted(IOperation operation)
 {
     if (operation.AgentId == AgentInfo.Id.Value)
     {
         return; // Local completions are handled by LocalCompletionProducer
     }
     if (!(operation.Command is ICommand command))
     {
         return; // We can't complete non-commands
     }
     if (command is IServerSideCommand serverSideCommand)
     {
         serverSideCommand.MarkServerSide(); // Server-side commands should be marked as such
     }
     Task.Run(async() => {
         try {
             await Commander.CallAsync(Completion.New(operation), true).ConfigureAwait(false);
             var logEnabled = LogLevel != LogLevel.None && Log.IsEnabled(LogLevel);
             if (logEnabled)
             {
                 Log.Log(LogLevel,
                         "External operation completion succeeded. Agent: '{AgentId}', Command: {Command}",
                         operation.AgentId, command);
             }
         }
         catch (Exception e) {
             Log.LogError(e,
                          "External operation completion failed! Agent: '{AgentId}', Command: {Command}",
                          operation.AgentId, command);
         }
     });
 }
Beispiel #2
0
 public virtual Task OnOperationCompleted(IOperation operation)
 {
     if (!(operation.Command is ICommand command))
     {
         return(Task.CompletedTask); // We can't complete non-commands
     }
     return(Task.Run(async() => {
         var isLocal = operation.AgentId == AgentInfo.Id.Value;
         var operationType = isLocal ? "Local" : "External";
         try {
             if (command is IServerSideCommand serverSideCommand)
             {
                 serverSideCommand.MarkServerSide(); // Server-side commands should be marked as such
             }
             await Commander.Call(Completion.New(operation), true).ConfigureAwait(false);
             var logEnabled = LogLevel != LogLevel.None && Log.IsEnabled(LogLevel);
             if (logEnabled)
             {
                 Log.Log(LogLevel,
                         "{OperationType} operation completion succeeded. Agent: '{AgentId}', Command: {Command}",
                         operationType, operation.AgentId, command);
             }
         }
         catch (Exception e) {
             Log.LogError(e,
                          "{OperationType} operation completion failed! Agent: '{AgentId}', Command: {Command}",
                          operationType, operation.AgentId, command);
         }
     }));
 }
Beispiel #3
0
 public virtual Task OnOperationCompleted(IOperation operation)
 {
     if (operation.Command is not ICommand command)
     {
         return(Task.CompletedTask); // We can't complete non-commands
     }
     return(Task.Run(async() => {
         var isLocal = StringComparer.Ordinal.Equals(operation.AgentId, AgentInfo.Id.Value);
         var operationType = isLocal ? "Local" : "External";
         try {
             // if (command is IBackendCommand backendCommand)
             //     backendCommand.MarkValid();
             await Commander.Call(Completion.New(operation), true).ConfigureAwait(false);
             if (IsLoggingEnabled)
             {
                 Log.Log(LogLevel,
                         "{OperationType} operation completion succeeded. Agent: '{AgentId}', Command: {Command}",
                         operationType, operation.AgentId, command);
             }
         }
         catch (Exception e) {
             Log.LogError(e,
                          "{OperationType} operation completion failed! Agent: '{AgentId}', Command: {Command}",
                          operationType, operation.AgentId, command);
         }
     }));
 }
        public async Task OnCommandAsync(ICommand command, CommandContext context, CancellationToken cancellationToken)
        {
            var operationRequired =
                context.OuterContext == null && // Should be top-level command
                !(command is IMetaCommand) && // No operations for "second-order" commands
                !Computed.IsInvalidating();

            if (!operationRequired)
            {
                await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false);

                return;
            }

            var tScope = typeof(DbOperationScope <TDbContext>);

            if (context.Items[tScope] != null) // Safety check
            {
                throw Stl.Internal.Errors.InternalError($"'{tScope}' scope is already provided. Duplicate handler?");
            }

            await using var scope = Services.GetRequiredService <DbOperationScope <TDbContext> >();
            var operation = scope.Operation;

            operation.Command = command;
            context.Items.Set(scope);

            var logEnabled = LogLevel != LogLevel.None && Log.IsEnabled(LogLevel);

            try {
                await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false);

                await scope.CommitAsync(cancellationToken);
            }
            catch (OperationCanceledException) {
                throw;
            }
            catch (Exception e) {
                if (scope.IsUsed)
                {
                    Log.LogError(e, "Operation failed: {Command}", command);
                }
                try {
                    await scope.RollbackAsync();
                }
                catch {
                    // Intended
                }
                throw;
            }
            if (scope.IsUsed)
            {
                if (logEnabled)
                {
                    Log.Log(LogLevel, "Operation succeeded: {Command}", command);
                }
                var completion = Completion.New(operation);
                context.Items.Set(completion);
                OperationCompletionNotifier.NotifyCompleted(operation);
                try {
                    await context.Commander.CallAsync(completion, true, default).ConfigureAwait(false);
                }
                catch (Exception e) {
                    Log.LogError(e, "Local operation completion failed! Command: {Command}", command);
                    // No throw: the operation itself succeeded
                }
            }
        }
        public async Task OnCommandAsync(ICommand command, CommandContext context, CancellationToken cancellationToken)
        {
            var operationRequired =
                context.OuterContext == null && // Should be top-level command
                !(command is IMetaCommand) && // No operations for "second-order" commands
                !Computed.IsInvalidating();

            if (!operationRequired)
            {
                await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false);

                return;
            }

            await using var scope = Services.GetRequiredService <LocalOperationScope>();
            var operation = scope.Operation;

            operation.Command = command;
            context.Items.Set(scope);
            context.SetOperation(operation);

            var logEnabled = LogLevel != LogLevel.None && Log.IsEnabled(LogLevel);

            try {
                await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false);

                await scope.CommitAsync(cancellationToken);
            }
            catch (OperationCanceledException) {
                throw;
            }
            catch (Exception e) {
                if (scope.IsUsed)
                {
                    Log.LogError(e, "Operation failed: {Command}", command);
                }
                await scope.RollbackAsync();

                throw;
            }

            // Since this is the outermost scope handler, it's reasonable to run the
            // ICompletion command right from it for any other scope too.
            var completion = context.Items.TryGet <ICompletion>();

            if (completion == null)   // Also means scope.IsUsed == true
            {
                if (logEnabled)
                {
                    Log.Log(LogLevel, "Operation succeeded: {Command}", command);
                }
                completion = Completion.New(operation);
                OperationCompletionNotifier.NotifyCompleted(operation);
                try {
                    await context.Commander.CallAsync(completion, true, default).ConfigureAwait(false);
                }
                catch (Exception e) {
                    Log.LogError(e, "Local operation completion failed! Command: {Command}", command);
                    // No throw: the operation itself succeeded
                }
            }
        }