public async Task Should_insert_and_retrieve_parallel() { var expectedEvents = 10 * 1000; var consumer = new MyEventConsumer(expectedEvents); var consumerGrain = new MyEventConsumerGrain(_ => consumer, grainState, _.EventStore, eventDataFormatter, log); await consumerGrain.ActivateAsync(consumer.Name); await consumerGrain.ActivateAsync(); Parallel.For(0, 20, x => { for (var i = 0; i < 500; i++) { var commitId = Guid.NewGuid(); var data = eventDataFormatter.ToEventData(Envelope.Create <IEvent>(new MyEvent()), commitId); _.EventStore.AppendAsync(commitId, commitId.ToString(), new[] { data }).Wait(); } }); await AssertConsumerAsync(expectedEvents, consumer); }
private async Task HandleEventAsync(IBackupReader reader, IEnumerable <IBackupHandler> handlers, string stream, Envelope <IEvent> @event) { if (@event.Payload is AppCreated appCreated) { if (!string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) { appCreated.Name = CurrentJob.NewAppName; CurrentJob.AppId = NamedId.Of(appCreated.AppId.Id, CurrentJob.NewAppName); } else { CurrentJob.AppId = appCreated.AppId; } await CreateContextAsync(reader); } if (@event.Payload is SquidexEvent squidexEvent && squidexEvent.Actor != null) { if (restoreContext.UserMapping.TryMap(squidexEvent.Actor, out var newUser)) { squidexEvent.Actor = newUser; } } if (@event.Payload is AppEvent appEvent) { appEvent.AppId = CurrentJob.AppId; } foreach (var handler in handlers) { if (!await handler.RestoreEventAsync(@event, restoreContext)) { return; } } var eventData = eventDataFormatter.ToEventData(@event, @event.Headers.CommitId()); var eventCommit = new List <EventData> { eventData }; await eventStore.AppendAsync(Guid.NewGuid(), stream, eventCommit); Log($"Read {reader.ReadEvents} events and {reader.ReadAttachments} attachments.", true); }
private async Task ReadEventsAsync(BackupReader reader) { await reader.ReadEventsAsync(streamNameResolver, async (storedEvent) => { var @event = eventDataFormatter.Parse(storedEvent.Data); if (@event.Payload is SquidexEvent squidexEvent) { squidexEvent.Actor = actor; } if (@event.Payload is AppCreated appCreated) { CurrentJob.AppId = appCreated.AppId.Id; if (!string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) { appCreated.Name = CurrentJob.NewAppName; } } if (@event.Payload is AppEvent appEvent && !string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) { appEvent.AppId = new NamedId <Guid>(appEvent.AppId.Id, CurrentJob.NewAppName); } foreach (var handler in handlers) { await handler.RestoreEventAsync(@event, CurrentJob.AppId, reader, actor); } var eventData = eventDataFormatter.ToEventData(@event, @event.Headers.CommitId()); var eventCommit = new List <EventData> { eventData }; await eventStore.AppendAsync(Guid.NewGuid(), storedEvent.StreamName, eventCommit); Log($"Read {reader.ReadEvents} events and {reader.ReadAttachments} attachments.", true); }); Log("Reading events completed."); }
private async Task <object> Upsert <TCommand>(TCommand command, Func <TCommand, object> handler) where TCommand : CommentsCommand { Guard.NotNull(command); Guard.NotNull(handler); if (command.ExpectedVersion > EtagVersion.Any && command.ExpectedVersion != Version) { throw new DomainObjectVersionException(Key, GetType(), Version, command.ExpectedVersion); } var prevVersion = version; try { var result = handler(command); if (uncommittedEvents.Count > 0) { var commitId = Guid.NewGuid(); var eventData = uncommittedEvents.Select(x => eventDataFormatter.ToEventData(x, commitId)).ToList(); await eventStore.AppendAsync(commitId, streamName, prevVersion, eventData); } events.AddRange(uncommittedEvents); return(result); } catch { version = prevVersion; throw; } finally { uncommittedEvents.Clear(); } }
private async Task HandleEventAsync(BackupReader reader, string stream, Envelope <IEvent> @event) { if (@event.Payload is SquidexEvent squidexEvent) { squidexEvent.Actor = actor; } if (@event.Payload is AppCreated appCreated) { CurrentJob.AppId = appCreated.AppId.Id; if (!string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) { appCreated.Name = CurrentJob.NewAppName; } } if (@event.Payload is AppEvent appEvent && !string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) { appEvent.AppId = new NamedId <Guid>(appEvent.AppId.Id, CurrentJob.NewAppName); } foreach (var handler in handlers) { if (!await handler.RestoreEventAsync(@event, CurrentJob.AppId, reader, actor)) { return; } } var eventData = eventDataFormatter.ToEventData(@event, @event.Headers.CommitId()); var eventCommit = new List <EventData> { eventData }; await eventStore.AppendAsync(Guid.NewGuid(), stream, eventCommit); Log($"Read {reader.ReadEvents} events and {reader.ReadAttachments} attachments.", true); }
private EventData[] GetEventData(Envelope <IEvent>[] events, Guid commitId) { return(events.Map(x => eventDataFormatter.ToEventData(x, commitId, true))); }
public async Task Should_write_and_read_events_to_backup(BackupVersion version) { var randomGenerator = new Random(); var randomDomainIds = new List <DomainId>(); for (var i = 0; i < 100; i++) { randomDomainIds.Add(DomainId.NewGuid()); } DomainId RandomDomainId() { return(randomDomainIds[randomGenerator.Next(randomDomainIds.Count)]); } var sourceEvents = new List <(string Stream, Envelope <MyEvent> Event)>(); for (var i = 0; i < 200; i++) { var @event = new MyEvent(); var envelope = Envelope.Create(@event); envelope.Headers.Add("Id", JsonValue.Create(@event.Id)); envelope.Headers.Add("Index", JsonValue.Create(i)); sourceEvents.Add(($"My-{RandomDomainId()}", envelope)); } await TestReaderWriterAsync(version, async writer => { foreach (var(stream, envelope) in sourceEvents) { var eventData = formatter.ToEventData(envelope, Guid.NewGuid(), true); var eventStored = new StoredEvent(stream, "1", 2, eventData); var index = int.Parse(envelope.Headers["Index"].ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture); if (index % 17 == 0) { await WriteGuidAsync(writer, index.ToString(CultureInfo.InvariantCulture), envelope.Payload.Id); } else if (index % 37 == 0) { await WriteJsonGuidAsync(writer, index.ToString(CultureInfo.InvariantCulture), envelope.Payload.Id); } writer.WriteEvent(eventStored); } }, async reader => { var targetEvents = new List <(string Stream, Envelope <IEvent> Event)>(); await foreach (var @event in reader.ReadEventsAsync(streamNameResolver, formatter)) { var index = int.Parse(@event.Event.Headers["Index"].ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture); var id = Guid.Parse(@event.Event.Headers["Id"].ToString()); if (index % 17 == 0) { var guid = await ReadGuidAsync(reader, index.ToString(CultureInfo.InvariantCulture)); Assert.Equal(id, guid); } else if (index % 37 == 0) { var guid = await ReadJsonGuidAsync(reader, index.ToString(CultureInfo.InvariantCulture)); Assert.Equal(id, guid); } targetEvents.Add(@event); } for (var i = 0; i < targetEvents.Count; i++) { var targetEvent = targetEvents[i].Event.To <MyEvent>(); var targetStream = targetEvents[i].Stream; var sourceEvent = sourceEvents[i].Event.To <MyEvent>(); var sourceStream = sourceEvents[i].Stream; Assert.Equal(sourceEvent.Payload.Id, targetEvent.Payload.Id); Assert.Equal(sourceStream, targetStream); } }); }
public async Task Should_write_and_read_events_to_backup(BackupVersion version) { var stream = new MemoryStream(); var random = new Random(); var randomGuids = new List <Guid>(); for (var i = 0; i < 100; i++) { randomGuids.Add(Guid.NewGuid()); } Guid RandomGuid() { return(randomGuids[random.Next(randomGuids.Count)]); } var sourceEvents = new List <(string Stream, Envelope <IEvent> Event)>(); for (var i = 0; i < 200; i++) { var @event = new MyEvent { GuidNamed = NamedId.Of(RandomGuid(), $"name{i}"), GuidRaw = RandomGuid(), Values = new Dictionary <Guid, string> { [RandomGuid()] = "Key" } }; var envelope = Envelope.Create <IEvent>(@event); envelope.Headers.Add(RandomGuid().ToString(), i); envelope.Headers.Add("Id", RandomGuid().ToString()); envelope.Headers.Add("Index", i); sourceEvents.Add(($"My-{RandomGuid()}", envelope)); } using (var writer = new BackupWriter(serializer, stream, true, version)) { foreach (var(_, envelope) in sourceEvents) { var eventData = formatter.ToEventData(envelope, Guid.NewGuid(), true); var eventStored = new StoredEvent("S", "1", 2, eventData); var index = int.Parse(envelope.Headers["Index"].ToString()); if (index % 17 == 0) { await writer.WriteBlobAsync(index.ToString(), innerStream => { innerStream.WriteByte((byte)index); return(TaskHelper.Done); }); } else if (index % 37 == 0) { await writer.WriteJsonAsync(index.ToString(), $"JSON_{index}"); } writer.WriteEvent(eventStored); } } stream.Position = 0; var targetEvents = new List <(string Stream, Envelope <IEvent> Event)>(); using (var reader = new BackupReader(serializer, stream)) { await reader.ReadEventsAsync(streamNameResolver, formatter, async @event => { var index = int.Parse(@event.Event.Headers["Index"].ToString()); if (index % 17 == 0) { await reader.ReadBlobAsync(index.ToString(), innerStream => { var byteRead = innerStream.ReadByte(); Assert.Equal((byte)index, byteRead); return(TaskHelper.Done); }); } else if (index % 37 == 0) { var json = await reader.ReadJsonAttachmentAsync <string>(index.ToString()); Assert.Equal($"JSON_{index}", json); } targetEvents.Add(@event); }); void CompareGuid(Guid source, Guid target) { Assert.Equal(source, reader.OldGuid(target)); Assert.NotEqual(source, target); } for (var i = 0; i < targetEvents.Count; i++) { var target = targetEvents[i].Event.To <MyEvent>(); var source = sourceEvents[i].Event.To <MyEvent>(); CompareGuid(source.Payload.Values.First().Key, target.Payload.Values.First().Key); CompareGuid(source.Payload.GuidRaw, target.Payload.GuidRaw); CompareGuid(source.Payload.GuidNamed.Id, target.Payload.GuidNamed.Id); CompareGuid(source.Headers.GetGuid("Id"), target.Headers.GetGuid("Id")); Assert.Equal(Guid.Empty, target.Payload.GuidEmpty); } } }
private async Task HandleEventAsync(IBackupReader reader, IEnumerable <IBackupHandler> handlers, string stream, Envelope <IEvent> @event) { if (@event.Payload is AppCreated appCreated) { var previousAppId = appCreated.AppId.Id; if (!string.IsNullOrWhiteSpace(CurrentJob.NewAppName)) { appCreated.Name = CurrentJob.NewAppName; CurrentJob.AppId = NamedId.Of(DomainId.NewGuid(), CurrentJob.NewAppName); } else { CurrentJob.AppId = NamedId.Of(DomainId.NewGuid(), appCreated.Name); } await CreateContextAsync(reader, previousAppId); } stream = stream.Replace( restoreContext.PreviousAppId.ToString(), restoreContext.AppId.ToString()); if (@event.Payload is SquidexEvent squidexEvent && squidexEvent.Actor != null) { if (restoreContext.UserMapping.TryMap(squidexEvent.Actor, out var newUser)) { squidexEvent.Actor = newUser; } } if (@event.Payload is AppEvent appEvent) { appEvent.AppId = CurrentJob.AppId; } if (@event.Headers.TryGet(CommonHeaders.AggregateId, out var aggregateId) && aggregateId is JsonString s) { var id = s.Value.Replace( restoreContext.PreviousAppId.ToString(), restoreContext.AppId.ToString()); var domainId = DomainId.Create(id); @event.SetAggregateId(domainId); } foreach (var handler in handlers) { if (!await handler.RestoreEventAsync(@event, restoreContext)) { return; } } var eventData = eventDataFormatter.ToEventData(@event, @event.Headers.CommitId()); var eventCommit = new List <EventData> { eventData }; await eventStore.AppendAsync(Guid.NewGuid(), stream, eventCommit); Log($"Read {reader.ReadEvents} events and {reader.ReadAttachments} attachments.", true); }
private EventData[] GetEventData(Envelope <IEvent>[] events, Guid commitId) { return(@events.Select(x => eventDataFormatter.ToEventData(x, commitId, true)).ToArray()); }