public async Task OnCommandAsync(ICommand command, CommandContext context, CancellationToken cancellationToken) { var skip = !IsEnabled || context.OuterContext != null || // Should be top-level command command is IInvalidateCommand || // Second handler here will take care of it Computed.IsInvalidating(); if (skip) { await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false); return; } if (InvalidationInfoProvider.RequiresInvalidation(command)) { context.Items.Set(InvalidateCommand.New(command)); } await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false); var invalidate = context.Items.TryGet <IInvalidateCommand>(); if (invalidate != null) { await context.Commander.RunAsync(invalidate, true, default).ConfigureAwait(false); } }
public virtual void OnOperationCompleted(IOperation operation) { if (operation.AgentId == AgentInfo.Id.Value) { // Local operations are invalidated by InvalidationHandler return; } if (!(operation.Command is ICommand command)) { return; } if (!InvalidationInfoProvider.RequiresInvalidation(command)) { return; } if (Log.IsEnabled(LogLevel.Debug)) { Log.LogDebug("Invalidating operation: agent {0}, command {1}", operation.AgentId, command); } Commander.Start(InvalidateCommand.New(command, operation), true); }
public async Task OnCommandAsync(ICommand command, CommandContext context, CancellationToken cancellationToken) { var skip = context.OuterContext != null || // Should be top-level command command is IInvalidateCommand || // Second handler here will take care of it Computed.IsInvalidating(); if (skip) { await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false); return; } var tScope = typeof(IDbOperationScope <TDbContext>); if (context.Items[tScope] != null) // Safety check { throw Stl.Internal.Errors.InternalError($"'{tScope}' scope is already provided. Duplicate handler?"); } var logEnabled = LogLevel != LogLevel.None && Log.IsEnabled(LogLevel); await using var scope = Services.GetRequiredService <IDbOperationScope <TDbContext> >(); scope.Command = command; context.Items.Set(scope); if (logEnabled) { Log.Log(LogLevel, "+ Operation started: {0}", command); } IOperation?operation = null; try { await context.InvokeRemainingHandlersAsync(cancellationToken).ConfigureAwait(false); // Building IOperation.Items from CommandContext.Items foreach (var(key, value) in context.Items.Items) { if (value is IOperationItem) { scope.Items = scope.Items.Set(key, value); } } operation = await scope.CommitAsync(cancellationToken); if (logEnabled) { Log.Log(LogLevel, "- Operation succeeded: {0}", command); } } catch (OperationCanceledException) { throw; } catch (Exception e) { Log.LogError(e, "! Operation failed: {0}", command); try { await scope.RollbackAsync(); } catch { // Intended } throw; } if (operation != null) { if (InvalidationInfoProvider?.RequiresInvalidation(command) ?? false) { context.Items.Set(InvalidateCommand.New(command, operation)); } OperationCompletionNotifier?.NotifyCompleted(operation); } }