/// <summary> /// Initializes a new instance of the <see cref="CommittedExternalEvent"/> class. /// </summary> /// <param name="eventLogSequenceNumber">The event log sequence number of the Event.</param> /// <param name="occurred">The <see cref="DateTimeOffset"/> when the Event was committed to the Event Store.</param> /// <param name="eventSourceId">The <see cref="EventSourceId"/> of the Event.</param> /// <param name="executionContext">The <see cref="ExecutionContext"/> in which the Event was committed.</param> /// <param name="externalEventLogSequenceNumber">The event log sequence number of the Event in the event log of the external Microservice that committed the event.</param> /// <param name="received">The <see cref="DateTimeOffset"/> when the Event was received over the Event Horizon.</param> /// <param name="event">An instance of the Event that was committed to the Event Store.</param> public CommittedExternalEvent( EventLogSequenceNumber eventLogSequenceNumber, DateTimeOffset occurred, EventSourceId eventSourceId, ExecutionContext executionContext, EventLogSequenceNumber externalEventLogSequenceNumber, DateTimeOffset received, IEvent @event) : base(eventLogSequenceNumber, occurred, eventSourceId, executionContext, @event) { ExternalEventLogSequenceNumber = externalEventLogSequenceNumber; Received = received; }
/// <summary> /// Initializes a new instance of the <see cref="CommittedAggregateEvent"/> class. /// </summary> /// <param name="eventLogSequenceNumber">The event log sequence number of the Event.</param> /// <param name="occurred">The <see cref="DateTimeOffset" /> when the Event was committed to the Event Store.</param> /// <param name="eventSourceId">The <see cref="EventSourceId" /> of the Event.</param> /// <param name="aggregateRoot">The <see cref="Type"/> of the Aggregate Root that applied the Event to the Event Source.</param> /// <param name="aggregateRootVersion">The version of the <see cref="AggregateRoot"/> that applied the Event.</param> /// <param name="executionContext">The <see cref="ExecutionContext"/> in which the Event was committed.</param> /// <param name="event">An instance of the Event that was committed to the Event Store.</param> public CommittedAggregateEvent( EventLogSequenceNumber eventLogSequenceNumber, DateTimeOffset occurred, EventSourceId eventSourceId, Type aggregateRoot, AggregateRootVersion aggregateRootVersion, ExecutionContext executionContext, IEvent @event) : base(eventLogSequenceNumber, occurred, eventSourceId, executionContext, @event) { AggregateRoot = aggregateRoot; AggregateRootVersion = aggregateRootVersion; }
/// <summary> /// Initializes a new instance of the <see cref="EventContext"/> class. /// </summary> /// <param name="sequenceNumber">The <see cref="EventLogSequenceNumber">sequence number</see> that uniquely identifies the event in the event log which it was committed.</param> /// <param name="eventSourceId">The <see cref="EventSourceId"/> that the event was committed to.</param> /// <param name="occurred">The <see cref="DateTimeOffset"/> when the event was committed to the <see cref="IEventStore"/>.</param> /// <param name="executionContext">The <see cref="ExecutionContext"/> in which the event was committed to the <see cref="IEventStore"/>.</param> public EventContext( EventLogSequenceNumber sequenceNumber, EventSourceId eventSourceId, DateTimeOffset occurred, ExecutionContext executionContext) : this( sequenceNumber, eventSourceId, occurred, executionContext, new EventIdentifier(executionContext.Microservice, executionContext.Tenant, sequenceNumber)) { }
/// <summary> /// Initializes a new instance of the <see cref="EventContext"/> class. /// </summary> /// <param name="sequenceNumber">The <see cref="EventLogSequenceNumber">sequence number</see> that uniquely identifies the event in the event log which it was committed.</param> /// <param name="eventSourceId">The <see cref="EventSourceId"/> that the event was committed to.</param> /// <param name="occurred">The <see cref="DateTimeOffset"/> when the event was committed to the <see cref="IEventStore"/>.</param> /// <param name="executionContext">The <see cref="ExecutionContext"/> in which the event was committed to the <see cref="IEventStore"/>.</param> /// <param name="uniqueIdentifier">The <see cref="EventIdentifier"/> that uniquely identifies the event.</param> protected EventContext( EventLogSequenceNumber sequenceNumber, EventSourceId eventSourceId, DateTimeOffset occurred, ExecutionContext executionContext, EventIdentifier uniqueIdentifier) { SequenceNumber = sequenceNumber; EventSourceId = eventSourceId; Occurred = occurred; ExecutionContext = executionContext; UniqueIdentifier = uniqueIdentifier; }
/// <summary> /// Initializes a new instance of the <see cref="CommittedEvent"/> class. /// </summary> /// <param name="eventLogSequenceNumber">The event log sequence number of the Event.</param> /// <param name="occurred">The <see cref="DateTimeOffset" /> when the Event was committed to the Event Store.</param> /// <param name="eventSourceId">The <see cref="EventSourceId" /> of the Event.</param> /// <param name="executionContext">The <see cref="ExecutionContext"/> in which the Event was committed.</param> /// <param name="event">An instance of the Event that was committed to the Event Store.</param> public CommittedEvent( EventLogSequenceNumber eventLogSequenceNumber, DateTimeOffset occurred, EventSourceId eventSourceId, ExecutionContext executionContext, IEvent @event) { EventLogSequenceNumber = eventLogSequenceNumber; Occurred = occurred; ExecutionContext = executionContext; Event = @event; EventSource = eventSourceId; }
/// <summary> /// Initializes a new instance of the <see cref="ExternalEventContext"/> class. /// </summary> /// <param name="sequenceNumber">The <see cref="EventLogSequenceNumber">sequence number</see> that uniquely identifies the event in the event log which it was received.</param> /// <param name="eventSourceId">The <see cref="EventSourceId"/> that the event was committed to.</param> /// <param name="occurred">The <see cref="DateTimeOffset"/> when the event was committed to the <see cref="IEventStore"/>.</param> /// <param name="executionContext">The <see cref="ExecutionContext"/> in which the event was committed to the <see cref="IEventStore"/>.</param> /// <param name="externalEventLogSequenceNumber">The <see cref="EventLogSequenceNumber">sequence number</see> that uniquely identifies the event in the event log which it was committed (the external Microservice event log).</param> /// <param name="received">The <see cref="DateTimeOffset"/> when the Event was received over the Event Horizon.</param> public ExternalEventContext( EventLogSequenceNumber sequenceNumber, EventSourceId eventSourceId, DateTimeOffset occurred, ExecutionContext executionContext, EventLogSequenceNumber externalEventLogSequenceNumber, DateTimeOffset received) : base( sequenceNumber, eventSourceId, occurred, executionContext, new EventIdentifier(executionContext.Microservice, executionContext.Tenant, externalEventLogSequenceNumber)) { ExternalEventLogSequenceNumber = externalEventLogSequenceNumber; Received = received; }
/// <summary> /// Composes an event identifier <see cref="string"/> from its components. /// </summary> /// <param name="microservice">The <see cref="Microservice"/> that committed the event.</param> /// <param name="tenant">The <see cref="TenantId"/> that committed the event.</param> /// <param name="sequenceNumber">The <see cref="EventLogSequenceNumber"/> of the event that was committed.</param> /// <returns>An event identifier <see cref="string"/>.</returns> /// <remarks> /// The event identifier string is the Base64 encoding of the concatenated bytes of the microservice ++ tenant ++ event log sequence number (40 bytes total). /// When converting the values to bytes, they are in the order that they are transmitted over gRPC as defined by the contracts - i.e. little endian. /// </remarks> public static string Compose(Microservice microservice, TenantId tenant, EventLogSequenceNumber sequenceNumber) { var microserviceBytes = microservice.Value.ToByteArray(); var tenantBytes = tenant.Value.ToByteArray(); var sequenceNumberBytes = BitConverter.GetBytes(sequenceNumber.Value); if (!BitConverter.IsLittleEndian) { Array.Reverse(sequenceNumberBytes); } using var stream = new MemoryStream(40); stream.Write(microserviceBytes); stream.Write(tenantBytes); stream.Write(sequenceNumberBytes); return(Convert.ToBase64String(stream.ToArray())); }
/// <summary> /// Initializes a new instance of the <see cref="EventLogSequenceNumberIsOutOfOrder"/> class. /// </summary> /// <param name="sequenceNumber">The <see cref="EventLogSequenceNumber"/> the Event was committed to.</param> /// <param name="expectedSequenceNumber">Expected <see cref="EventLogSequenceNumber"/>.</param> public EventLogSequenceNumberIsOutOfOrder(EventLogSequenceNumber sequenceNumber, EventLogSequenceNumber expectedSequenceNumber) : base($"Event Log Sequence is out of order because Event Log Sequence Number '{sequenceNumber}' is not greater than '{expectedSequenceNumber}'.") { }
/// <summary> /// Tries to decompose an event identifier <see cref="string"/> to its components. /// </summary> /// <param name="eventIdentifier">The event identifier <see cref="string"/>.</param> /// <param name="microservice">When this method returns, the <see cref="Microservice"/> that committed the event.</param> /// <param name="tenant">When this method returns, the <see cref="TenantId"/> that committed the event.</param> /// <param name="sequenceNumber">When this method returns, the <see cref="EventLogSequenceNumber"/> of the event that was committed.</param> /// <returns><c>true</c> if the deomposition was successful; otherwise, <c>false</c>.</returns> public static bool TryDecompose(string eventIdentifier, out Microservice microservice, out TenantId tenant, out EventLogSequenceNumber sequenceNumber) { var decoded = new Span <byte>(new byte[40]); if (Convert.TryFromBase64String(eventIdentifier, decoded, out var read) && read == 40) { var microserviceBytes = decoded.Slice(0, 16); var tenantBytes = decoded.Slice(16, 16); var sequenceNumberBytes = decoded.Slice(32, 8); if (!BitConverter.IsLittleEndian) { sequenceNumberBytes.Reverse(); } microservice = new Guid(microserviceBytes); tenant = new Guid(tenantBytes); sequenceNumber = BitConverter.ToUInt64(sequenceNumberBytes); return(true); } microservice = null; tenant = null; sequenceNumber = 0; return(false); }
/// <summary> /// Initializes a new instance of the <see cref="EventIdentifier"/> class. /// </summary> /// <param name="microservice">The <see cref="Microservice"/> that committed the event.</param> /// <param name="tenant">The <see cref="TenantId"/> that committed the event.</param> /// <param name="sequenceNumber">The <see cref="EventLogSequenceNumber"/> of the event that was committed.</param> public EventIdentifier(Microservice microservice, TenantId tenant, EventLogSequenceNumber sequenceNumber) { Value = Compose(microservice, tenant, sequenceNumber); }
/// <summary> /// Decomposes the <see cref="EventIdentifier"/> to its components. /// </summary> /// <param name="microservice">When this method returns, the <see cref="Microservice"/> that committed the event.</param> /// <param name="tenant">When this method returns, the <see cref="TenantId"/> that committed the event.</param> /// <param name="sequenceNumber">When this method returns, the <see cref="EventLogSequenceNumber"/> of the event that was committed.</param> public void Decompose(out Microservice microservice, out TenantId tenant, out EventLogSequenceNumber sequenceNumber) { TryDecompose(Value, out microservice, out tenant, out sequenceNumber); }