public void Prepare_InsertsEvents( [Frozen] Mock <IBatchOperation> operationMock, [Frozen] string streamName, [Frozen] EventStreamHeader header, JournaledEvent[] events, AppendOperation operation) { operation.Prepare(events); var version = header.Version; foreach (var journaledEvent in events) { var e = journaledEvent; version = version.Increment(); VerifyInsertOperation( operationMock: operationMock, partitionKey: streamName, rowKey: version.ToString(), verifyColumns: columns => columns["EventId"].Equals(e.EventId) && columns["EventType"].Equals(e.EventTypeName)); } }
private EntityCreatedEvent EventStreamRoundTripEvent(EntityCreatedEvent evt) { EventStreamHeader header = new EventStreamHeader(new VectorClock(), new Infrastructure.VectorClock(), Guid.NewGuid(), Guid.NewGuid()); MemoryStream stream = new MemoryStream(); using (EventStreamWriter writer = new EventStreamWriter(stream, header, false)) { writer.WriteEvent(evt); } stream.Seek(0, SeekOrigin.Begin); using (stream) using (EventStreamReader reader = new EventStreamReader(stream)) { while (reader.Read()) { if (reader.ItemType == ItemType.Event) { return((EntityCreatedEvent)reader.CurrentEvent); } } } throw new InvalidOperationException("The event could not be round tripped"); }
public InitialCursorState(EventStreamHeader streamHeader, StreamVersion fromVersion, FetchEvents fetch) : base(streamHeader) { Require.NotNull(fetch, "fetch"); m_version = fromVersion; m_fetch = fetch; }
private EventStreamCursor(EventStreamHeader streamHeader, StreamVersion fromVersion, FetchEvents fetch) { Require.NotNull(fetch, "fetch"); m_state = new InitialCursorState(streamHeader, fromVersion, fetch); m_slice = EventStreamSlice.Empty; m_cursorStreamVersion = fromVersion; }
public void TwoEqualsHeader_AreSame(EventStreamHeader header) { var header1 = header; var header2 = new EventStreamHeader(header1.ETag, header1.Version); Assert.Equal(header1, header2); Assert.True(header1 == header2); }
public void TwoHeadersWithDifferentETagValue_AreNotSame(string etag1, string etag2, StreamVersion version) { var header1 = new EventStreamHeader(etag1, version); var header2 = new EventStreamHeader(etag2, version); Assert.NotEqual(header1, header2); Assert.False(header1 == header2); }
public void TwoHeadersWithDifferentVersionValue_AreNotSame(string etag, StreamVersion version1, StreamVersion version2) { var header1 = new EventStreamHeader(etag, version1); var header2 = new EventStreamHeader(etag, version2); Assert.NotEqual(header1, header2); Assert.False(header1 == header2); }
public FetchingCursorState( EventStreamHeader streamHeader, StreamVersion sliceSteamVersion, FetchEvents fetch) : base(streamHeader) { Require.NotNull(fetch, "fetch"); m_sliceSteamVersion = sliceSteamVersion; m_fetch = fetch; }
public async Task AppendEvents_AppendEventsToJournal( [Frozen] EventStreamHeader header, [Frozen] Mock<IEventJournal> journalMock, EventStreamWriter writer, JournaledEvent[] events) { await writer.AppendEventsAsync(events); journalMock.Verify(journal => journal.AppendEventsAsync( writer.StreamName, header, It.Is<IReadOnlyCollection<JournaledEvent>>(e => e.Count == events.Length))); }
private async Task <EventStreamHeader> AppendEventsAsync( string streamName, EventStreamHeader header, int batchSize = EVENTS_COUNT, int batchNumber = BATCH_NUMBER) { var batches = PrepareBatch(batchSize, batchNumber); var currentPosition = header; while (batches.Any()) { currentPosition = await Journal.AppendEventsAsync(streamName, currentPosition, batches.Dequeue()); } return(currentPosition); }
public async Task StreamPosition_AfterWriteAsyncCall_UpdatedStreamVersionValue( [Frozen] Mock<IEventJournal> journalMock, EventStreamHeader header, EventStreamWriter writer, JournaledEvent[] events) { journalMock .Setup(self => self.AppendEventsAsync( It.IsAny<string>(), It.IsAny<EventStreamHeader>(), It.IsAny<IReadOnlyCollection<JournaledEvent>>())) .Returns(header.YieldTask()); await writer.AppendEventsAsync(events); Assert.Equal(header.Version, writer.StreamVersion); }
public void Prepare_ForUnknownHeader_InsertsHeaderRow( [Frozen] Mock <IBatchOperation> operationMock, [Frozen] string streamName, [Frozen] EventStreamHeader header, JournaledEvent[] events, AppendOperation operation) { var targetVersion = (int)header.Version.Increment(events.Count()); operation.Prepare(events); VerifyInsertOperation( operationMock, streamName, "HEAD", name => name.Equals("Version"), value => value.Equals(targetVersion)); }
public async Task AppendEvents_DeletesPendingNotification( [Frozen] Mock<IEventJournal> journalMock, [Frozen] Mock<IPendingNotifications> pendingNotificationMock, [Frozen] EventStreamHeader header, EventStreamWriter writer, JournaledEvent[] events) { journalMock .Setup(self => self.AppendEventsAsync( It.IsAny<string>(), It.IsAny<EventStreamHeader>(), It.IsAny<IReadOnlyCollection<JournaledEvent>>())) .Returns(header.YieldTask()); await writer.AppendEventsAsync(events); pendingNotificationMock.Verify(notifications => notifications.DeleteAsync( writer.StreamName, header.Version)); }
public EventStreamWriter( string streamName, IEventStoreConnectionState connectionState, EventStreamHeader endOfStream, IEventJournal journal, IEventMutationPipeline mutationPipeline, INotificationHub notificationHub, IPendingNotifications pendingNotification) : base(streamName, connectionState) { Require.NotEmpty(streamName, "streamName"); Require.NotNull(journal, "journal"); Require.NotNull(mutationPipeline, "mutationPipeline"); Require.NotNull(notificationHub, "notificationHub"); Require.NotNull(pendingNotification, "pendingNotification"); m_endOfStream = endOfStream; m_journal = journal; m_mutationPipeline = mutationPipeline; m_notificationHub = notificationHub; m_pendingNotification = pendingNotification; }
public async Task <FetchEventsResult> FetchStreamEvents(string stream, EventStreamHeader header, StreamVersion fromVersion, int sliceSize) { // fromVersion already in slice var isFetchingCompleted = false; var nextSliceVersion = fromVersion.Increment(sliceSize - 1); if (nextSliceVersion >= header.Version) { nextSliceVersion = header.Version; isFetchingCompleted = true; } const string queryTemplate = "((PartitionKey eq '{0}') and (RowKey eq 'HEAD')) or " + "((PartitionKey eq '{0}') and (RowKey ge '{1}' and RowKey le '{2}'))"; var query = m_table.PrepareEntityFilterRangeQuery( queryTemplate.FormatString( stream, fromVersion.ToString(), nextSliceVersion.ToString())); var queryResult = await query.ExecuteAsync(); var events = new SortedList <StreamVersion, JournaledEvent>(sliceSize); foreach (var properties in queryResult) { var rowKey = (string)properties[KnownProperties.RowKey]; if (!rowKey.EqualsCi("HEAD")) { events.Add(StreamVersion.Parse((string)properties[KnownProperties.RowKey]), JournaledEvent.Create(properties)); } } return(new FetchEventsResult(isFetchingCompleted, events)); }
public void PublishEvents(IEnumerable <ModelEvent> events) { UpdateEventCache(); var eventsToPublish = events.Where(e => !_publishedEvents.Contains(e.EventID)).OrderBy(e => e.EventVector).ToList(); if (eventsToPublish.Count == 0) { return; } var streamId = Guid.NewGuid(); EventStreamHeader header = new EventStreamHeader(eventsToPublish[0].EventVector, eventsToPublish.Last().EventVector, _deviceId, streamId); string filePath = Path.Combine(_deviceDirectory, streamId.ToString() + ".eventstream"); using (Stream file = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write)) using (EventStreamWriter writer = new EventStreamWriter(file, header, true)) { writer.WriteEvents(eventsToPublish); } FileEventStream stream = new FileEventStream(filePath); _cachedEventStreams.Add(filePath, stream); var streamEventIDs = eventsToPublish.Select(e => e.EventID).ToList(); foreach (var eventId in streamEventIDs) { if (!_publishedEvents.Add(eventId)) { throw new InvalidOperationException("This eventID already exists!"); } } _eventsInStreams.Add(filePath, streamEventIDs); }
public async Task AppendEventsAsync(IReadOnlyCollection <JournaledEvent> events) { Require.NotNull(events, "events"); ConnectionState.EnsureConnectionIsActive(); if (events.Count == 0) { return; } var fromVersion = m_endOfStream.Version; var mutatedEvents = new List <JournaledEvent>(events.Count); mutatedEvents.AddRange(events.Select(journaledEvent => m_mutationPipeline.Mutate(journaledEvent))); await m_pendingNotification.AddAsync(StreamName, fromVersion, mutatedEvents.Count); m_endOfStream = await m_journal.AppendEventsAsync(StreamName, m_endOfStream, mutatedEvents); await m_notificationHub.NotifyAsync(new EventStreamUpdated(StreamName, fromVersion, m_endOfStream.Version)); await m_pendingNotification.DeleteAsync(StreamName, fromVersion); }
public void TestPositiveEncode() { foreach (var entry in _positiveDecodedTestCases) { byte[] payload = null; var headersList = new List <IEventStreamHeader>(); //read the data to encode, then add it to payload and headers list. var decodedDoc = entry.Value; var jsonStr = Encoding.UTF8.GetString(decodedDoc); var data = JsonMapper.ToObject(jsonStr); if (data[PayloadField] != null) { var base64Payload = (String)data[PayloadField]; payload = Convert.FromBase64String(base64Payload); } if (data[HeaderField] != null) { var headersCollection = data[HeaderField]; foreach (var header in headersCollection.OfType <JsonData>()) { var headerName = (string)header[HeaderNameField]; var headerValue = new EventStreamHeader(headerName); var type = (EventStreamHeaderType)(int)header[HeaderTypeField]; switch (type) { case EventStreamHeaderType.String: var strVal = Encoding.UTF8.GetString(Convert.FromBase64String((string)header[HeaderValueField])); headerValue.SetString(strVal); break; case EventStreamHeaderType.UUID: var uuidVal = Convert.FromBase64String((string)header[HeaderValueField]); headerValue.SetUUID(new Guid(uuidVal)); break; case EventStreamHeaderType.ByteBuf: var byteBuf = Convert.FromBase64String((string)header[HeaderValueField]); headerValue.SetByteBuf(byteBuf); break; case EventStreamHeaderType.BoolFalse: case EventStreamHeaderType.BoolTrue: var boolVal = (bool)header[HeaderValueField]; headerValue.SetBool(boolVal); break; case EventStreamHeaderType.Byte: var byteVal = (byte)(int)header[HeaderValueField]; headerValue.SetByte(byteVal); break; case EventStreamHeaderType.Int16: var int16Val = (short)header[HeaderValueField]; headerValue.SetInt16(int16Val); break; case EventStreamHeaderType.Int32: var int32Val = (int)header[HeaderValueField]; headerValue.SetInt32(int32Val); break; case EventStreamHeaderType.Int64: var intVal = (long)header[HeaderValueField]; headerValue.SetInt64(intVal); break; case EventStreamHeaderType.Timestamp: var dateVal = (long)header[HeaderValueField]; /* we only do this in this spot because we're setting it from the unix epoch directly. * normal API usage, you can use DateTime as a first class citizen. */ headerValue.SetTimestamp(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(dateVal)); break; default: break; } headersList.Add(headerValue); } } //create the message, and serialize it, it should equal the original encoded data. var message = new EventStreamMessage(headersList, payload); CollectionAssert.Equals(_positiveEncodedTestCases[entry.Key], message.ToByteArray()); } }
public void IsNewStream_ForNotUnknownHeader_ReturnsFalse(EventStreamHeader header) { Assert.False(EventStreamHeader.IsNewStream(header)); }
public void IsNewStream_ForUnknownHeader_ReturnsTrue() { Assert.True(EventStreamHeader.IsNewStream(EventStreamHeader.Unknown)); }
public async Task MoveToEndOfStreamAsync() { ConnectionState.EnsureConnectionIsActive(); m_endOfStream = await m_journal.ReadStreamHeaderAsync(StreamName); }
public AppendOperation CreateAppendOperation(string streamName, EventStreamHeader header) { return(new AppendOperation(m_table, streamName, header)); }
public void TwoNotEqualsHeader_AreNotSame(EventStreamHeader header1, EventStreamHeader header2) { Assert.NotEqual(header1, header2); Assert.False(header1 == header2); }
public static IEventStreamCursor CreateEmptyCursor(EventStreamHeader streamHeader, StreamVersion fromVersion) { return(new EventStreamCursor(streamHeader, fromVersion)); }
public static IEventStreamCursor CreateActiveCursor(EventStreamHeader streamHeader, StreamVersion fromVersion, FetchEvents fetch) { return(new EventStreamCursor(streamHeader, fromVersion, fetch)); }
private EventStreamCursor(EventStreamHeader streamHeader, StreamVersion fromVersion) { m_state = new EndOfStreamCursorState(streamHeader); m_slice = EventStreamSlice.Empty; m_cursorStreamVersion = fromVersion; }
protected CursorState(EventStreamHeader streamHeader) { StreamHeader = streamHeader; }
public MemoryEventStream(Func <IEnumerable <ModelEvent> > intializeEventIterator, EventStreamHeader header) { _intializeEventIterator = intializeEventIterator; _header = header; }
public EndOfStreamCursorState(EventStreamHeader streamHeader) : base(streamHeader) { }
public void StreamPosition_ReturnsStreamVersionValue([Frozen] EventStreamHeader header, EventStreamWriter writer) { Assert.Equal(header.Version, writer.StreamVersion); }