public async Task <IReadOnlyCollection <ICommittedDomainEvent> > CommitEventsAsync( IIdentity id, IReadOnlyCollection <SerializedEvent> serializedEvents, CancellationToken cancellationToken) { using (await _asyncLock.WaitAsync(cancellationToken).ConfigureAwait(false)) { var committedDomainEvents = new List <ICommittedDomainEvent>(); var aggregatePath = _filesEventLocator.GetEntityPath(id); if (!Directory.Exists(aggregatePath)) { Directory.CreateDirectory(aggregatePath); } foreach (var serializedEvent in serializedEvents) { var eventPath = _filesEventLocator.GetEventPath(id, serializedEvent.AggregateSequenceNumber); _globalSequenceNumber++; _eventLog[_globalSequenceNumber] = eventPath; var fileEventData = new FileEventData { AggregateId = id.Value, AggregateSequenceNumber = serializedEvent.AggregateSequenceNumber, Data = serializedEvent.SerializedData, Metadata = serializedEvent.SerializedMetadata, GlobalSequenceNumber = _globalSequenceNumber, }; var json = _jsonSerializer.Serialize(fileEventData, true); using (var streamWriter = CreateNewTextFile(eventPath, fileEventData)) { _log.Verbose("Writing file '{0}'", eventPath); await streamWriter.WriteAsync(json).ConfigureAwait(false); } committedDomainEvents.Add(fileEventData); } using (var streamWriter = File.CreateText(_logFilePath)) { _log.Verbose( "Writing global sequence number '{0}' to '{1}'", _globalSequenceNumber, _logFilePath); var json = _jsonSerializer.Serialize( new EventStoreLog { GlobalSequenceNumber = _globalSequenceNumber, Log = _eventLog }, true); await streamWriter.WriteAsync(json).ConfigureAwait(false); } return(committedDomainEvents); } }
public void UnsyncedWillThrow() { var fsm = new FileEventStateMachine(); Assert.Throws <ArgumentOutOfRangeException> (() => fsm.Set("a", 0, 0, false, FileState.Removed)); // Add a busted FileEventData var eventData = new FileEventData { Kind = EventDataKind.Changed, Args = new FileEventArgs(), }; Assert.Throws <ArgumentOutOfRangeException> (() => fsm.Set("a", 0, 0, false, FileState.Removed)); }
private StreamWriter CreateNewTextFile(string path, FileEventData fileEventData) { try { var stream = new FileStream(path, FileMode.CreateNew); return(new StreamWriter(stream)); } catch (IOException) { if (File.Exists(path)) { throw new OptimisticConcurrencyException( $"Event {fileEventData.AggregateSequenceNumber} already exists for entity with ID '{fileEventData.AggregateId}'"); } throw; } }
public void AddAndRemove() { var fsm = new FileEventStateMachine(); var eventData = new FileEventData { Kind = EventDataKind.Changed, Args = new FileEventArgs("a", false), }; fsm.Queue(eventData); fsm.Set("a", 0, 0, false, FileState.Removed); fsm.RemoveLastEventData("a"); Assert.IsFalse(fsm.TryGet("a", out var state)); fsm.RemoveLastEventData("a"); Assert.IsFalse(fsm.TryGet("a", out state)); }
public async Task<IReadOnlyCollection<ICommittedDomainEvent>> CommitEventsAsync(IIdentity id, IReadOnlyCollection<SerializedEvent> serializedEvents, CancellationToken cancellationToken) { using (await _asyncLock.WaitAsync(cancellationToken).ConfigureAwait(false)) { var committedDomainEvents = new List<ICommittedDomainEvent>(); var aggregatePath = _filesEventLocator.GetEntityPath(id); if (!Directory.Exists(aggregatePath)) { Directory.CreateDirectory(aggregatePath); } foreach (var serializedEvent in serializedEvents) { var eventPath = _filesEventLocator.GetEventPath(id, serializedEvent.AggregateSequenceNumber); _globalSequenceNumber++; _eventLog[_globalSequenceNumber] = eventPath; var fileEventData = new FileEventData { AggregateId = id.Value, AggregateSequenceNumber = serializedEvent.AggregateSequenceNumber, Data = serializedEvent.SerializedData, Metadata = serializedEvent.SerializedMetadata, GlobalSequenceNumber = _globalSequenceNumber, }; var json = _jsonSerializer.Serialize(fileEventData, true); if (File.Exists(eventPath)) { // TODO: This needs to be on file creation throw new OptimisticConcurrencyException(string.Format( "Event {0} already exists for entity with ID '{1}'", fileEventData.AggregateSequenceNumber, id)); } using (var streamWriter = File.CreateText(eventPath)) { _log.Verbose("Writing file '{0}'", eventPath); await streamWriter.WriteAsync(json).ConfigureAwait(false); } committedDomainEvents.Add(fileEventData); } using (var streamWriter = File.CreateText(_logFilePath)) { _log.Verbose( "Writing global sequence number '{0}' to '{1}'", _globalSequenceNumber, _logFilePath); var json = _jsonSerializer.Serialize( new EventStoreLog { GlobalSequenceNumber = _globalSequenceNumber, Log = _eventLog, }, true); await streamWriter.WriteAsync(json).ConfigureAwait(false); } return committedDomainEvents; } }
protected override async Task <IReadOnlyCollection <ICommittedDomainEvent> > CommitEventsAsync <TAggregate, TIdentity>( TIdentity id, IReadOnlyCollection <SerializedEvent> serializedEvents, CancellationToken cancellationToken) { using (await _asyncLock.WaitAsync(cancellationToken).ConfigureAwait(false)) { var aggregateType = typeof(TAggregate); var committedDomainEvents = new List <ICommittedDomainEvent>(); var aggregatePath = GetAggregatePath(aggregateType, id); if (!Directory.Exists(aggregatePath)) { Directory.CreateDirectory(aggregatePath); } foreach (var serializedEvent in serializedEvents) { var eventPath = GetEventPath(aggregateType, id, serializedEvent.AggregateSequenceNumber); _globalSequenceNumber++; _log[_globalSequenceNumber] = eventPath; var fileEventData = new FileEventData { AggregateId = id.Value, AggregateSequenceNumber = serializedEvent.AggregateSequenceNumber, Data = serializedEvent.SerializedData, Metadata = serializedEvent.SerializedMetadata, GlobalSequenceNumber = _globalSequenceNumber, }; var json = _jsonSerializer.Serialize(fileEventData, true); if (File.Exists(eventPath)) { // TODO: This needs to be on file creation throw new OptimisticConcurrencyException(string.Format( "Event {0} already exists for aggregate '{1}' with ID '{2}'", fileEventData.AggregateSequenceNumber, aggregateType.Name, id)); } using (var streamWriter = File.CreateText(eventPath)) { Log.Verbose("Writing file '{0}'", eventPath); await streamWriter.WriteAsync(json).ConfigureAwait(false); } committedDomainEvents.Add(fileEventData); } using (var streamWriter = File.CreateText(_logFilePath)) { Log.Verbose( "Writing global sequence number '{0}' to '{1}'", _globalSequenceNumber, _logFilePath); var json = _jsonSerializer.Serialize( new EventStoreLog { GlobalSequenceNumber = _globalSequenceNumber, Log = _log, }, true); await streamWriter.WriteAsync(json).ConfigureAwait(false); } return(committedDomainEvents); } }
public void Functionality() { var fsm = new FileEventStateMachine(); FilePath a = "a", b = "b", c = "c"; var eventData = new FileEventData { Kind = EventDataKind.Changed, Args = new FileEventArgs(new [] { a, b, c }, false), }; fsm.Queue(eventData); Assert.AreEqual(false, fsm.TryGet(a, out var state)); fsm.Set(a, 0, 0, false, FileState.Changed); fsm.Set(b, 0, 1, false, FileState.Changed); fsm.Set(c, 0, 2, false, FileState.Changed); Assert.AreEqual(true, fsm.TryGet(a, out state)); AssertState(state, FileState.Changed, 1, 0, 0); Assert.AreEqual(true, fsm.TryGet(b, out state)); AssertState(state, FileState.Changed, 1, 0, 1); Assert.AreEqual(true, fsm.TryGet(c, out state)); AssertState(state, FileState.Changed, 1, 0, 2); eventData = new FileEventData { Kind = EventDataKind.Removed, Args = new FileEventArgs(new [] { b, a, c }, false), }; fsm.Queue(eventData); fsm.Set(a, 1, 1, false, FileState.Removed); fsm.Set(b, 1, 0, false, FileState.Removed); fsm.Set(c, 1, 2, false, FileState.Removed); Assert.AreEqual(true, fsm.TryGet(a, out state)); AssertState(state, FileState.Removed, 2, 1, 1); Assert.AreEqual(true, fsm.TryGet(b, out state)); AssertState(state, FileState.Removed, 2, 1, 0); Assert.AreEqual(true, fsm.TryGet(c, out state)); AssertState(state, FileState.Removed, 2, 1, 2); fsm.RemoveLastEventData(c); Assert.AreEqual(true, fsm.TryGet(a, out state)); AssertState(state, FileState.Removed, 2, 1, 1); Assert.AreEqual(true, fsm.TryGet(b, out state)); AssertState(state, FileState.Removed, 2, 1, 0); Assert.AreEqual(true, fsm.TryGet(c, out state)); AssertState(state, FileState.Changed, 1, 0, 2); fsm.RemoveLastEventData(c); Assert.AreEqual(false, fsm.TryGet(c, out state)); Assert.IsNull(state); void AssertState(FileEventState s, FileState fs, int count, int eventIndex, int fileIndex) { Assert.AreEqual(fs, state.FinalState); Assert.AreEqual(count, state.Indices.Count); if (count == 0) { return; } Assert.AreEqual(eventIndex, state.Indices [count - 1].EventIndex); Assert.AreEqual(fileIndex, state.Indices [count - 1].FileIndex); } }