public async Task <string> CreateEvent(Event newEvent) { newEvent.Id = Guid.NewGuid().ToString(); var result = await _eventContainer.Value.CreateItemAsync(PersistedEvent.FromInstance(newEvent)); return(result.Resource.id); }
public static async Task <PersistedEvent> GetAsync(this NpgsqlConnection conn, long eventId, CancellationToken cancellationToken = default) { var query = $"{Select} {s_queryColumns} {From} {Table} where \"Id\" = @id"; await using var command = new NpgsqlCommand(query, conn); command.Parameters.AddWithValue("id", eventId); await using var reader = await command.ExecuteReaderAsync(cancellationToken); await reader.ReadAsync(cancellationToken); var timestamp = reader.GetFieldValue <Instant>(0); var aggregateId = reader.GetFieldValue <Guid>(1); var version = reader.GetFieldValue <int>(2); var eventType = reader.GetFieldValue <string>(3); var metadata = reader.GetFieldValue <byte[]>(4); var payload = reader.GetFieldValue <byte[]>(5); var result = new PersistedEvent() { AggregateId = aggregateId, EventType = eventType, Id = eventId, Metadata = metadata, Payload = payload, Timestamp = timestamp, Version = version }; return(result); }
private static void WriteItem(PersistedEvent item, BinaryWriter binaryWriter) { binaryWriter.Write(item.Id); binaryWriter.Write(item.Previous); binaryWriter.Write(item.StreamLength); binaryWriter.Write((int)item.State); item.Metadata.WriteTo(new BsonWriter(binaryWriter)); item.Data.WriteTo(new BsonWriter(binaryWriter)); }
public bool ShouldTakeSnapshot(PersistedEvent persistedEvent) { var now = _getNow(); if (_lastTaken.Add(_interval) <= now) { _lastTaken = now; return(true); } return(false); }
internal static Event ToEvent(this PersistedEvent instance) { Event result = new Event(); result.Id = instance.EventId.ToString(); result.EventKey = instance.EventKey; result.EventName = instance.EventName; result.EventTime = DateTime.SpecifyKind(instance.EventTime, DateTimeKind.Utc); result.IsProcessed = instance.IsProcessed; result.EventData = JsonConvert.DeserializeObject(instance.EventData, SerializerSettings); return(result); }
internal static PersistedEvent ToPersistable(this Event instance) { PersistedEvent result = new PersistedEvent(); result.EventId = new Guid(instance.Id); result.EventKey = instance.EventKey; result.EventName = instance.EventName; result.EventTime = DateTime.SpecifyKind(instance.EventTime, DateTimeKind.Utc); result.IsProcessed = instance.IsProcessed; result.EventData = JsonConvert.SerializeObject(instance.EventData, SerializerSettings); return(result); }
public Task <IEventPersistence.AppendEventResult> AppendEvent(IEventPersistence.Event @event) { var streamName = @event.StreamName; long actualStreamPosition = 0; if (!_streams.ContainsKey(streamName)) { _streams.Add(streamName, new List <IndexedStreamEvent>()); } else { actualStreamPosition = _streams[streamName].Last().StreamPosition; } var persistedEvent = new PersistedEvent(_globalPosition, actualStreamPosition, @event); _events.Add(persistedEvent); _streams[streamName].Add(new IndexedStreamEvent(streamName, actualStreamPosition, _globalPosition)); _globalPosition += 1; return(Task.FromResult(new IEventPersistence.AppendEventResult(actualStreamPosition))); }
public async Task <Event> GetEvent(string id) { var resp = await _eventContainer.Value.ReadItemAsync <PersistedEvent>(id, new PartitionKey(id)); return(PersistedEvent.ToInstance(resp.Resource)); }
public bool ShouldTakeSnapshot(PersistedEvent persistedEvent) { return(persistedEvent.Data.GetType() == _eventType); }
public bool ShouldTakeSnapshot(PersistedEvent persistedEvent) { return(persistedEvent.Index % _eventsPerSnapshot == 0); }
public static async IAsyncEnumerable <PersistedEvent> GetAsync(this NpgsqlConnection conn, IEventFilter eventFilter, [EnumeratorCancellation] CancellationToken cancellationToken = default) { var parameters = new List <(string, object)>(); var whereClauses = new List <string>(); if (eventFilter.AggregateId.HasValue) { var name = "a"; whereClauses.Add($"\"AggregateId\" = @{name}"); parameters.Add((name, eventFilter.AggregateId.Value)); } if (eventFilter.Checkpoint.HasValue) { var name = "b"; whereClauses.Add($"\"Id\" > @{name}"); parameters.Add((name, eventFilter.Checkpoint.Value)); } var eventTypes = eventFilter.EventTypes.ToArray(); if (eventTypes.Any()) { var stringBuilder = new StringBuilder("\"EventType\" in ("); var whereClauseParts = new string[eventTypes.Length]; for (var i = 0; i < eventTypes.Length; i++) { var eventType = eventTypes[i]; var name = "c" + i; parameters.Add((name, eventType)); whereClauseParts[i] = "@" + name; } var partsString = string.Join(", ", whereClauseParts); stringBuilder.Append(partsString); stringBuilder.Append(")"); whereClauses.Add(stringBuilder.ToString()); } var whereClause = whereClauses.Any() ? "WHERE " + string.Join(" AND ", whereClauses) : ""; const string Id = "\"Id\""; var query = $"{Select} {s_queryColumns}, {Id} {From} {Table} {whereClause} order by {Id}"; await using var command = new NpgsqlCommand(query, conn); foreach (var(parameterName, value) in parameters) { command.Parameters.AddWithValue(parameterName, value); } await using var reader = await command.ExecuteReaderAsync(cancellationToken); while (await reader.ReadAsync(cancellationToken)) { var timestamp = reader.GetFieldValue <Instant>(0); var aggregateId = reader.GetFieldValue <Guid>(1); var version = reader.GetFieldValue <int>(2); var eventType = reader.GetFieldValue <string>(3); var metadata = reader.GetFieldValue <byte[]>(4); var payload = reader.GetFieldValue <byte[]>(5); var eventId = reader.GetFieldValue <long>(6); var result = new PersistedEvent() { AggregateId = aggregateId, EventType = eventType, Id = eventId, Metadata = metadata, Payload = payload, Timestamp = timestamp, Version = version }; yield return(result); } }
public IEventPersistence.Event ToEvent(PersistedEvent persistedEvent) { return(new IEventPersistence.Event(StreamName, StreamPosition, persistedEvent.EventData, persistedEvent.EventMetadata)); }
private void WriteToDisk() { var tasksToNotify = new List <Action <Exception> >(); while (true) { if (cts.IsCancellationRequested) { FlushToDisk(tasksToNotify, closing: true); return; } WriteState item; if (hadWrites) { if ((DateTime.UtcNow - lastWrite) > options.MaxTimeToWaitForFlush) { // we have to flush to disk now, because we have writes and nothing else is forthcoming // or we have so many writes, that we need to flush to clear the buffers FlushToDisk(tasksToNotify); continue; } } if (itemsToWrite.TryDequeue(out item) == false) { if (hadWrites) { FlushToDisk(tasksToNotify); } else { if (deleteCount > (eventsCount / 4)) // we have > 25% wasted space { // we waited enough time to be pretty sure we are idle // and can run compaction without too much problems. if (hasItems.Wait(options.IdleTime, cts.Token) == false) { Compact(); continue; } } else { hasItems.Wait(cts.Token); } hasItems.Reset(); } continue; } StreamInformation info; idToPos.TryGetValue(item.Id, out info); var prevPos = info == null ? DoesNotExists : info.LastPosition; var currentPos = file.Position; var persistedEvent = new PersistedEvent { Id = item.Id, Data = item.Data, State = item.State, Previous = prevPos, Metadata = item.Metadata }; WriteItem(persistedEvent, binaryWriter); var action = CreateCompletionAction(tasksToNotify, item, currentPos); tasksToNotify.Add(action); hadWrites = true; } }