private async Task <object> InvokeAsync <TCommand>(TCommand command, Func <TCommand, Task <object> > handler, bool isUpdate) where TCommand : class, IAggregateCommand { Guard.NotNull(command, nameof(command)); if (command.ExpectedVersion != EtagVersion.Any && command.ExpectedVersion != Version) { throw new DomainObjectVersionException(Id.ToString(), GetType(), Version, command.ExpectedVersion); } if (isUpdate && Version < 0) { throw new DomainObjectNotFoundException(Id.ToString(), GetType()); } else if (!isUpdate && Version >= 0) { throw new DomainException("Object has already been created."); } var previousSnapshot = snapshot; try { var result = await handler(command); var events = uncomittedEvents.ToArray(); if (events.Length > 0) { snapshot.Version = NewVersion; await persistence.WriteEventsAsync(events); await persistence.WriteSnapshotAsync(snapshot); } if (result == null) { if (isUpdate) { result = new EntitySavedResult(Version); } else { result = EntityCreatedResult.Create(Id, Version); } } return(result); } catch { snapshot = previousSnapshot; throw; } finally { ClearUncommittedEvents(); } }
private async Task <T> InvokeSyncedAsync <T>(CommandContext context, Func <T, Task> handler, bool isUpdate) where T : class, IDomainObject { Guard.NotNull(context, nameof(context)); var domainCommand = GetCommand(context); var domainObjectId = domainCommand.AggregateId; using (await lockPool.LockAsync(Tuple.Create(typeof(T), domainObjectId))) { var domainObject = await stateFactory.GetSingleAsync <T>(domainObjectId); if (domainCommand.ExpectedVersion != EtagVersion.Any && domainCommand.ExpectedVersion != domainObject.Version) { throw new DomainObjectVersionException(domainObjectId.ToString(), typeof(T), domainObject.Version, domainCommand.ExpectedVersion); } await handler(domainObject); await domainObject.WriteAsync(); if (!context.IsCompleted) { if (isUpdate) { context.Complete(new EntitySavedResult(domainObject.Version)); } else { context.Complete(EntityCreatedResult.Create(domainObjectId, domainObject.Version)); } } return(domainObject); } }
private async Task <object?> InvokeAsync <TCommand>(TCommand command, Func <TCommand, Task <object?> > handler, Mode mode) where TCommand : class, IAggregateCommand { Guard.NotNull(command); Guard.NotNull(handler); if (command.ExpectedVersion > EtagVersion.Any && command.ExpectedVersion != Version) { throw new DomainObjectVersionException(id.ToString(), GetType(), Version, command.ExpectedVersion); } if (mode == Mode.Update && Version < 0) { TryDeactivateOnIdle(); throw new DomainObjectNotFoundException(id.ToString(), GetType()); } if (mode == Mode.Create && Version >= 0) { throw new DomainException("Object has already been created."); } var previousSnapshot = Snapshot; var previousVersion = Version; try { var result = await handler(command); var events = uncomittedEvents.ToArray(); await WriteAsync(events, previousVersion); if (result == null) { if (mode == Mode.Update || (mode == Mode.Upsert && Version == 0)) { result = new EntitySavedResult(Version); } else { result = EntityCreatedResult.Create(id, Version); } } return(result); } catch { RestorePreviousSnapshot(previousSnapshot, previousVersion); throw; } finally { ClearUncommittedEvents(); } }
private async Task <object?> InvokeAsync <TCommand>(TCommand command, Func <TCommand, Task <object?> > handler, bool isUpdate) where TCommand : class, IAggregateCommand { Guard.NotNull(command); Guard.NotNull(handler); if (isUpdate) { await EnsureLoadedAsync(); } if (command.ExpectedVersion > EtagVersion.Any && command.ExpectedVersion != Version) { throw new DomainObjectVersionException(id.ToString(), GetType(), Version, command.ExpectedVersion); } if (isUpdate == true && Version < 0) { throw new DomainObjectNotFoundException(id.ToString(), GetType()); } var previousSnapshot = Snapshot; var previousVersion = Version; try { var result = await handler(command); var events = uncomittedEvents.ToArray(); await WriteAsync(events, previousVersion); if (result == null) { if (isUpdate) { result = new EntitySavedResult(Version); } else { result = EntityCreatedResult.Create(id, Version); } } isLoaded = true; return(result); } catch { RestorePreviousSnapshot(previousSnapshot, previousVersion); throw; } finally { ClearUncommittedEvents(); } }
private async Task <object?> InvokeAsync <TCommand>(TCommand command, Func <TCommand, Task <object?> > handler, bool isUpdate) where TCommand : class, IAggregateCommand { Guard.NotNull(command, nameof(command)); Guard.NotNull(handler, nameof(handler)); if (isUpdate) { await EnsureLoadedAsync(); if (Version < 0) { throw new DomainObjectNotFoundException(uniqueId.ToString()); } if (Version != command.ExpectedVersion && command.ExpectedVersion > EtagVersion.Any) { throw new DomainObjectVersionException(uniqueId.ToString(), Version, command.ExpectedVersion); } if (IsDeleted()) { throw new DomainException("Object has already been deleted."); } if (!CanAccept(command)) { throw new DomainException("Invalid command."); } } else { command.ExpectedVersion = EtagVersion.Empty; if (Version != command.ExpectedVersion) { throw new DomainObjectConflictException(uniqueId.ToString()); } if (!CanAcceptCreation(command)) { throw new DomainException("Invalid command."); } } var previousSnapshot = Snapshot; var previousVersion = Version; try { var result = await handler(command); var events = uncomittedEvents.ToArray(); await WriteAsync(events, previousVersion); if (result == null) { if (isUpdate) { result = new EntitySavedResult(Version); } else { result = EntityCreatedResult.Create(uniqueId, Version); } } isLoaded = true; return(result); } catch (InconsistentStateException) when(!isUpdate) { RestorePreviousSnapshot(previousSnapshot, previousVersion); throw new DomainObjectConflictException(uniqueId.ToString()); } catch { RestorePreviousSnapshot(previousSnapshot, previousVersion); throw; } finally { ClearUncommittedEvents(); } }