Exemple #1
0
        private StreamSubscription SubscribeToStream(string streamName,
                                                     StreamRevision start,
                                                     Func <StreamSubscription, ResolvedEvent, CancellationToken, Task> eventAppeared,
                                                     EventStoreClientOperationOptions operationOptions,
                                                     bool resolveLinkTos = false,
                                                     Action <StreamSubscription, SubscriptionDroppedReason, Exception> subscriptionDropped = default,
                                                     UserCredentials userCredentials     = default,
                                                     CancellationToken cancellationToken = default)
        {
            operationOptions.TimeoutAfter = DeadLine.None;

            var subscription = new StreamSubscription(ReadInternal(new ReadReq {
                Options = new ReadReq.Types.Options {
                    ReadDirection = ReadReq.Types.Options.Types.ReadDirection.Forwards,
                    ResolveLinks  = resolveLinkTos,
                    Stream        = ReadReq.Types.Options.Types.StreamOptions.FromStreamNameAndRevision(streamName,
                                                                                                        start),
                    Subscription = new ReadReq.Types.Options.Types.SubscriptionOptions()
                }
            },
                                                                   operationOptions, userCredentials, cancellationToken), eventAppeared,
                                                      subscriptionDropped);

            return(subscription);
        }
        private Task <StreamSubscription> SubscribeToStreamAsync(string streamName,
                                                                 StreamRevision start,
                                                                 Func <StreamSubscription, ResolvedEvent, CancellationToken, Task> eventAppeared,
                                                                 EventStoreClientOperationOptions operationOptions,
                                                                 bool resolveLinkTos = false,
                                                                 Action <StreamSubscription, SubscriptionDroppedReason, Exception> subscriptionDropped = default,
                                                                 UserCredentials userCredentials     = default,
                                                                 CancellationToken cancellationToken = default)
        {
            operationOptions.TimeoutAfter = DeadLine.None;

            return(StreamSubscription.Confirm(ReadInternal(new ReadReq {
                Options = new ReadReq.Types.Options {
                    ReadDirection = ReadReq.Types.Options.Types.ReadDirection.Forwards,
                    ResolveLinks = resolveLinkTos,
                    Stream = start == StreamRevision.End
                                                                ? new ReadReq.Types.Options.Types.StreamOptions {
                        End = new Empty(),
                        StreamName = streamName
                    }
                                                                : new ReadReq.Types.Options.Types.StreamOptions {
                        Revision = start,
                        StreamName = streamName
                    },
                    Subscription = new ReadReq.Types.Options.Types.SubscriptionOptions()
                }
            },
                                                           operationOptions, userCredentials, cancellationToken), eventAppeared, subscriptionDropped, _log,
                                              cancellationToken: cancellationToken));
        }
 private Task <IWriteResult> SetStreamMetadataAsync(string streamName, StreamState expectedState,
                                                    StreamMetadata metadata, EventStoreClientOperationOptions operationOptions,
                                                    UserCredentials?userCredentials = null, CancellationToken cancellationToken = default)
 => SetStreamMetadataInternal(metadata, new AppendReq {
     Options = new AppendReq.Types.Options {
         StreamName = SystemStreams.MetastreamOf(streamName)
     }
 }.WithAnyStreamRevision(expectedState), operationOptions, userCredentials, cancellationToken);
Exemple #4
0
 private Task <WriteResult> SetStreamMetadataAsync(string streamName, StreamRevision expectedRevision,
                                                   StreamMetadata metadata, EventStoreClientOperationOptions operationOptions,
                                                   UserCredentials userCredentials = default, CancellationToken cancellationToken = default)
 => SetStreamMetadataInternal(metadata, new AppendReq {
     Options = new AppendReq.Types.Options {
         StreamName = SystemStreams.MetastreamOf(streamName),
         Revision   = expectedRevision
     }
 }, operationOptions, userCredentials, cancellationToken);
 private IAsyncEnumerable <ResolvedEvent> ReadAllAsync(
     Direction direction,
     Position position,
     ulong maxCount,
     EventStoreClientOperationOptions operationOptions,
     bool resolveLinkTos                 = false,
     IEventFilter filter                 = null,
     UserCredentials userCredentials     = default,
     CancellationToken cancellationToken = default) => ReadInternal(new ReadReq {
        private async Task <DeleteResult> TombstoneInternal(TombstoneReq request,
                                                            EventStoreClientOperationOptions operationOptions, UserCredentials userCredentials,
                                                            CancellationToken cancellationToken)
        {
            var result = await _client.TombstoneAsync(request, RequestMetadata.Create(userCredentials),
                                                      deadline : DeadLine.After(operationOptions.TimeoutAfter), cancellationToken);

            return(new DeleteResult(new Position(result.Position.CommitPosition, result.Position.PreparePosition)));
        }
 private Task <IWriteResult> SetStreamMetadataInternal(StreamMetadata metadata,
                                                       AppendReq appendReq,
                                                       EventStoreClientOperationOptions operationOptions,
                                                       UserCredentials?userCredentials,
                                                       CancellationToken cancellationToken) =>
 AppendToStreamInternal(appendReq, new[] {
     new EventData(Uuid.NewUuid(), SystemEventTypes.StreamMetadata,
                   JsonSerializer.SerializeToUtf8Bytes(metadata, StreamMetadataJsonSerializerOptions)),
 }, operationOptions, userCredentials, cancellationToken);
Exemple #8
0
        private async Task <DeleteResult> DeleteInternal(DeleteReq request, EventStoreClientOperationOptions operationOptions,
                                                         UserCredentials?userCredentials,
                                                         CancellationToken cancellationToken)
        {
            _log.LogDebug("Deleting stream {streamName}.", request.Options.StreamName);
            var result = await _client.DeleteAsync(request, RequestMetadata.Create(userCredentials ?? Settings.DefaultCredentials),
                                                   deadline : DeadLine.After(operationOptions.TimeoutAfter), cancellationToken);

            return(new DeleteResult(new Position(result.Position.CommitPosition, result.Position.PreparePosition)));
        }
Exemple #9
0
 private Task <DeleteResult> SoftDeleteAsync(
     string streamName,
     AnyStreamRevision expectedRevision,
     EventStoreClientOperationOptions operationOptions,
     UserCredentials userCredentials     = default,
     CancellationToken cancellationToken = default) =>
 DeleteInternal(new DeleteReq {
     Options = new DeleteReq.Types.Options {
         StreamName = streamName
     }
 }.WithAnyStreamRevision(expectedRevision), operationOptions, userCredentials, cancellationToken);
 private Task <DeleteResult> TombstoneAsync(
     string streamName,
     StreamState expectedState,
     EventStoreClientOperationOptions operationOptions,
     UserCredentials?userCredentials     = null,
     CancellationToken cancellationToken = default) =>
 TombstoneInternal(new TombstoneReq {
     Options = new TombstoneReq.Types.Options {
         StreamIdentifier = streamName
     }
 }.WithAnyStreamRevision(expectedState), operationOptions, userCredentials, cancellationToken);
		private async Task<DeleteResult> DeleteInternal(DeleteReq request,
			EventStoreClientOperationOptions operationOptions,
			UserCredentials? userCredentials,
			CancellationToken cancellationToken) {
			_log.LogDebug("Deleting stream {streamName}.", request.Options.StreamIdentifier);
			var result = await new Streams.Streams.StreamsClient(
				await SelectCallInvoker(cancellationToken).ConfigureAwait(false)).DeleteAsync(request,
				EventStoreCallOptions.Create(Settings, operationOptions, userCredentials, cancellationToken));

			return new DeleteResult(new Position(result.Position.CommitPosition, result.Position.PreparePosition));
		}
        private async Task <DeleteResult> TombstoneInternal(TombstoneReq request,
                                                            EventStoreClientOperationOptions operationOptions, UserCredentials?userCredentials,
                                                            CancellationToken cancellationToken)
        {
            _log.LogDebug("Tombstoning stream {streamName}.", request.Options.StreamIdentifier);

            var result = await _client.TombstoneAsync(request,
                                                      EventStoreCallOptions.Create(Settings, operationOptions, userCredentials, cancellationToken));

            return(new DeleteResult(new Position(result.Position.CommitPosition, result.Position.PreparePosition)));
        }
Exemple #13
0
        private async Task <WriteResult> AppendToStreamInternal(
            AppendReq header,
            IEnumerable <EventData> eventData,
            EventStoreClientOperationOptions operationOptions,
            UserCredentials userCredentials,
            CancellationToken cancellationToken)
        {
            using var call = _client.Append(RequestMetadata.Create(userCredentials),
                                            deadline: DeadLine.After(operationOptions.TimeoutAfter), cancellationToken: cancellationToken);

            try {
                await call.RequestStream.WriteAsync(header).ConfigureAwait(false);

                foreach (var e in eventData)
                {
                    _log.LogTrace("Appending event to stream - {streamName}@{eventId} {eventType}.",
                                  header.Options.StreamName, e.EventId, e.Type);
                    await call.RequestStream.WriteAsync(new AppendReq {
                        ProposedMessage = new AppendReq.Types.ProposedMessage {
                            Id             = e.EventId.ToDto(),
                            Data           = ByteString.CopyFrom(e.Data.Span),
                            CustomMetadata = ByteString.CopyFrom(e.Metadata.Span),
                            Metadata       =
                            {
                                { Constants.Metadata.Type,        e.Type        },
                                { Constants.Metadata.ContentType, e.ContentType }
                            }
                        }
                    }).ConfigureAwait(false);
                }

                await call.RequestStream.CompleteAsync().ConfigureAwait(false);
            } catch (InvalidOperationException exc) {
                _log.LogTrace(exc, "Got InvalidOperationException when appending events to stream - {streamName}. This is perfectly normal if the connection was closed from the server-side.", header.Options.StreamName);
            } catch (RpcException exc) {
                _log.LogTrace(exc, "Got RpcException when appending events to stream - {streamName}. This is perfectly normal if the connection was closed from the server-side.", header.Options.StreamName);
            }

            var response = await call.ResponseAsync.ConfigureAwait(false);

            var writeResult = new WriteResult(
                response.CurrentRevisionOptionCase == AppendResp.CurrentRevisionOptionOneofCase.NoStream
                                        ? AnyStreamRevision.NoStream.ToInt64()
                                        : new StreamRevision(response.CurrentRevision).ToInt64(),
                response.PositionOptionCase == AppendResp.PositionOptionOneofCase.Position
                                        ? new Position(response.Position.CommitPosition, response.Position.PreparePosition)
                                        : default);

            _log.LogDebug("Append to stream succeeded - {streamName}@{logPosition}/{nextExpectedVersion}.",
                          header.Options.StreamName, writeResult.LogPosition, writeResult.NextExpectedVersion);

            return(writeResult);
        }
 private Task <WriteResult> AppendToStreamAsync(
     string streamName,
     AnyStreamRevision expectedRevision,
     IEnumerable <EventData> eventData,
     EventStoreClientOperationOptions operationOptions,
     UserCredentials userCredentials     = default,
     CancellationToken cancellationToken = default) =>
 AppendToStreamInternal(new AppendReq {
     Options = new AppendReq.Types.Options {
         StreamName = streamName
     }
 }.WithAnyStreamRevision(expectedRevision), eventData, operationOptions, userCredentials, cancellationToken);
 private Task <DeleteResult> TombstoneAsync(
     string streamName,
     StreamRevision expectedRevision,
     EventStoreClientOperationOptions operationOptions,
     UserCredentials?userCredentials     = null,
     CancellationToken cancellationToken = default) =>
 TombstoneInternal(new TombstoneReq {
     Options = new TombstoneReq.Types.Options {
         StreamName = streamName,
         Revision   = expectedRevision
     }
 }, operationOptions, userCredentials, cancellationToken);
        public void setting_options_on_clone_should_not_modify_original()
        {
            EventStoreClientOperationOptions options = new EventStoreClientOperationOptions {
                TimeoutAfter = TimeSpan.FromDays(5),
            };

            var clonedOptions = options.Clone();

            clonedOptions.TimeoutAfter = TimeSpan.FromSeconds(1);

            Assert.Equal(options.TimeoutAfter, TimeSpan.FromDays(5));
            Assert.Equal(clonedOptions.TimeoutAfter, TimeSpan.FromSeconds(1));
        }
        private Task <IWriteResult> AppendToStreamAsync(
            string streamName,
            StreamState expectedState,
            IEnumerable <EventData> eventData,
            EventStoreClientOperationOptions operationOptions,
            UserCredentials?userCredentials     = null,
            CancellationToken cancellationToken = default)
        {
            _log.LogDebug("Append to stream - {streamName}@{expectedRevision}.", streamName, expectedState);

            return(AppendToStreamInternal(new AppendReq {
                Options = new AppendReq.Types.Options {
                    StreamIdentifier = streamName
                }
            }.WithAnyStreamRevision(expectedState), eventData, operationOptions, userCredentials, cancellationToken));
        }
Exemple #18
0
 private async IAsyncEnumerable <ResolvedEvent> ReadAllAsync(
     Direction direction,
     Position position,
     long maxCount,
     EventStoreClientOperationOptions operationOptions,
     bool resolveLinkTos             = false,
     UserCredentials?userCredentials = null,
     [EnumeratorCancellation] CancellationToken cancellationToken = default)
 {
     await foreach (var(confirmation, _, resolvedEvent) in ReadInternal(new ReadReq {
         Options = new ReadReq.Types.Options {
             ReadDirection = direction switch {
                 Direction.Backwards => ReadReq.Types.Options.Types.ReadDirection.Backwards,
                 Direction.Forwards => ReadReq.Types.Options.Types.ReadDirection.Forwards,
                 _ => throw new InvalidOperationException()
             },
Exemple #19
0
        private Task <WriteResult> AppendToStreamAsync(
            string streamName,
            StreamRevision expectedRevision,
            IEnumerable <EventData> eventData,
            EventStoreClientOperationOptions operationOptions,
            UserCredentials userCredentials     = default,
            CancellationToken cancellationToken = default)
        {
            _log.LogDebug("Append to stream - {streamName}@{expectedRevision}.", streamName, expectedRevision);

            return(AppendToStreamInternal(new AppendReq {
                Options = new AppendReq.Types.Options {
                    StreamName = streamName,
                    Revision = expectedRevision
                }
            }, eventData, operationOptions, userCredentials, cancellationToken));
        }
        public static CallOptions Create(EventStoreClientSettings settings,
                                         EventStoreClientOperationOptions operationOptions, UserCredentials?userCredentials,
                                         CancellationToken cancellationToken) => new CallOptions(
            cancellationToken: cancellationToken,
            deadline: DeadlineAfter(operationOptions.TimeoutAfter),
            headers: new Metadata(),
            credentials: CallCredentials.FromInterceptor(async(context, metadata) => {
            var credentials = settings.DefaultCredentials ?? userCredentials;

            if (credentials == null)
            {
                return;
            }

            var authorizationHeader = await settings.OperationOptions
                                      .GetAuthenticationHeaderValue(credentials, CancellationToken.None)
                                      .ConfigureAwait(false);
            metadata.Add(Constants.Headers.Authorization, authorizationHeader);
        })
            );
        private async Task <WriteResult> AppendToStreamInternal(
            AppendReq header,
            IEnumerable <EventData> eventData,
            EventStoreClientOperationOptions operationOptions,
            UserCredentials userCredentials,
            CancellationToken cancellationToken)
        {
            using var call = _client.Append(RequestMetadata.Create(userCredentials),
                                            deadline: DeadLine.After(operationOptions.TimeoutAfter), cancellationToken: cancellationToken);

            await call.RequestStream.WriteAsync(header).ConfigureAwait(false);

            foreach (var e in eventData)
            {
                await call.RequestStream.WriteAsync(new AppendReq {
                    ProposedMessage = new AppendReq.Types.ProposedMessage {
                        Id             = e.EventId.ToStreamsDto(),
                        Data           = ByteString.CopyFrom(e.Data),
                        CustomMetadata = ByteString.CopyFrom(e.Metadata),
                        Metadata       =
                        {
                            { Constants.Metadata.Type,   e.Type                                 },
                            { Constants.Metadata.IsJson, e.IsJson.ToString().ToLowerInvariant() }
                        }
                    }
                }).ConfigureAwait(false);
            }

            await call.RequestStream.CompleteAsync().ConfigureAwait(false);

            var response = await call.ResponseAsync.ConfigureAwait(false);

            return(new WriteResult(
                       response.CurrentRevisionOptionCase == AppendResp.CurrentRevisionOptionOneofCase.NoStream
                                        ? AnyStreamRevision.NoStream.ToInt64()
                                        : new StreamRevision(response.CurrentRevision).ToInt64(),
                       response.PositionOptionCase == AppendResp.PositionOptionOneofCase.Position
                                        ? new Position(response.Position.CommitPosition, response.Position.PreparePosition)
                                        : default));
        }
        private async Task <StreamMetadataResult> GetStreamMetadataAsync(string streamName,
                                                                         EventStoreClientOperationOptions operationOptions, UserCredentials?userCredentials = null,
                                                                         CancellationToken cancellationToken = default)
        {
            ResolvedEvent metadata;

            _log.LogDebug("Read stream metadata for {streamName}.");

            try {
                metadata = await ReadStreamAsync(Direction.Backwards, SystemStreams.MetastreamOf(streamName), StreamPosition.End, 1, operationOptions, false, userCredentials, cancellationToken)
                           .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
            } catch (StreamNotFoundException) {
                _log.LogWarning("Stream metadata for {streamName} not found.");
                return(StreamMetadataResult.None(streamName));
            }

            return(metadata.Event == null
                                ? StreamMetadataResult.None(streamName)
                                : StreamMetadataResult.Create(streamName, metadata.OriginalEventNumber,
                                                              JsonSerializer.Deserialize <StreamMetadata>(metadata.Event.Data.Span,
                                                                                                          StreamMetadataJsonSerializerOptions)));
        }
        private Task <StreamSubscription> SubscribeToAllAsync(Position start,
                                                              Func <StreamSubscription, ResolvedEvent, CancellationToken, Task> eventAppeared,
                                                              EventStoreClientOperationOptions operationOptions,
                                                              bool resolveLinkTos = false,
                                                              Action <StreamSubscription, SubscriptionDroppedReason, Exception> subscriptionDropped = default,
                                                              SubscriptionFilterOptions filterOptions = null,
                                                              UserCredentials userCredentials         = default,
                                                              CancellationToken cancellationToken     = default)
        {
            operationOptions.TimeoutAfter = DeadLine.None;

            return(StreamSubscription.Confirm(ReadInternal(new ReadReq {
                Options = new ReadReq.Types.Options {
                    ReadDirection = ReadReq.Types.Options.Types.ReadDirection.Forwards,
                    ResolveLinks = resolveLinkTos,
                    All = ReadReq.Types.Options.Types.AllOptions.FromPosition(start),
                    Subscription = new ReadReq.Types.Options.Types.SubscriptionOptions(),
                    Filter = GetFilterOptions(filterOptions)
                }
            }, operationOptions, userCredentials, cancellationToken), eventAppeared, subscriptionDropped, _log,
                                              filterOptions?.CheckpointReached, cancellationToken));
        }
        private async Task <StreamMetadataResult> GetStreamMetadataAsync(string streamName,
                                                                         EventStoreClientOperationOptions operationOptions, UserCredentials userCredentials = default,
                                                                         CancellationToken cancellationToken = default)
        {
            ResolvedEvent metadata = default;

            try {
                metadata = await ReadStreamAsync(Direction.Backwards, SystemStreams.MetastreamOf(streamName), StreamRevision.End, 1,
                                                 operationOptions,
                                                 resolveLinkTos : false,
                                                 userCredentials : userCredentials,
                                                 cancellationToken : cancellationToken).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
            } catch (StreamNotFoundException) {
                return(StreamMetadataResult.None(streamName));
            }

            return(metadata.Event == null
                                ? StreamMetadataResult.None(streamName)
                                : StreamMetadataResult.Create(
                       streamName,
                       metadata.OriginalEventNumber,
                       JsonSerializer.Deserialize <StreamMetadata>(metadata.Event.Data, StreamMetadataJsonSerializerOptions)));
        }
Exemple #25
0
        private StreamSubscription SubscribeToAll(
            Func <StreamSubscription, ResolvedEvent, CancellationToken, Task> eventAppeared,
            EventStoreClientOperationOptions operationOptions,
            bool resolveLinkTos = false,
            Action <StreamSubscription, SubscriptionDroppedReason, Exception> subscriptionDropped = default,
            IEventFilter filter                 = null,
            UserCredentials userCredentials     = default,
            CancellationToken cancellationToken = default)
        {
            operationOptions.TimeoutAfter = DeadLine.None;

            var subscription = new StreamSubscription(ReadInternal(new ReadReq {
                Options = new ReadReq.Types.Options {
                    ReadDirection = ReadReq.Types.Options.Types.ReadDirection.Forwards,
                    ResolveLinks  = resolveLinkTos,
                    All           = ReadReq.Types.Options.Types.AllOptions.FromPosition(Position.Start),
                    Subscription  = new ReadReq.Types.Options.Types.SubscriptionOptions(),
                    Filter        = GetFilterOptions(filter)
                }
            }, operationOptions, userCredentials, cancellationToken), eventAppeared,
                                                      subscriptionDropped);

            return(subscription);
        }
		public static CallOptions Create(EventStoreClientSettings settings,
			EventStoreClientOperationOptions operationOptions, UserCredentials? userCredentials,
			CancellationToken cancellationToken) => new(
        private async Task <IWriteResult> AppendToStreamInternal(
            AppendReq header,
            IEnumerable <EventData> eventData,
            EventStoreClientOperationOptions operationOptions,
            UserCredentials?userCredentials,
            CancellationToken cancellationToken)
        {
            using var call = new Streams.Streams.StreamsClient(
                      await SelectCallInvoker(cancellationToken).ConfigureAwait(false)).Append(EventStoreCallOptions.Create(
                                                                                                   Settings, operationOptions, userCredentials, cancellationToken));

            IWriteResult writeResult;

            try {
                await call.RequestStream.WriteAsync(header).ConfigureAwait(false);

                foreach (var e in eventData)
                {
                    _log.LogTrace("Appending event to stream - {streamName}@{eventId} {eventType}.",
                                  header.Options.StreamIdentifier, e.EventId, e.Type);
                    await call.RequestStream.WriteAsync(new AppendReq {
                        ProposedMessage = new AppendReq.Types.ProposedMessage {
                            Id             = e.EventId.ToDto(),
                            Data           = ByteString.CopyFrom(e.Data.Span),
                            CustomMetadata = ByteString.CopyFrom(e.Metadata.Span),
                            Metadata       =
                            {
                                { Constants.Metadata.Type,        e.Type        },
                                { Constants.Metadata.ContentType, e.ContentType }
                            }
                        }
                    }).ConfigureAwait(false);
                }
            } finally {
                await call.RequestStream.CompleteAsync().ConfigureAwait(false);

                var response = await call.ResponseAsync.ConfigureAwait(false);

                if (response.Success != null)
                {
                    writeResult = new SuccessResult(response.Success.CurrentRevisionOptionCase ==
                                                    AppendResp.Types.Success.CurrentRevisionOptionOneofCase.NoStream
                                                        ? StreamRevision.None
                                                        : new StreamRevision(response.Success.CurrentRevision),
                                                    response.Success.PositionOptionCase == AppendResp.Types.Success.PositionOptionOneofCase.Position
                                                        ? new Position(response.Success.Position.CommitPosition,
                                                                       response.Success.Position.PreparePosition)
                                                        : default);
                    _log.LogDebug("Append to stream succeeded - {streamName}@{logPosition}/{nextExpectedVersion}.",
                                  header.Options.StreamIdentifier, writeResult.LogPosition, writeResult.NextExpectedStreamRevision);
                }
                else
                {
                    if (response.WrongExpectedVersion != null)
                    {
                        var actualStreamRevision = response.WrongExpectedVersion.CurrentRevisionOptionCase switch {
                            AppendResp.Types.WrongExpectedVersion.CurrentRevisionOptionOneofCase.CurrentNoStream =>
                            StreamRevision.None,
                            _ => new StreamRevision(response.WrongExpectedVersion.CurrentRevision)
                        };

                        _log.LogDebug(
                            "Append to stream failed with Wrong Expected Version - {streamName}/{expectedRevision}/{currentRevision}",
                            header.Options.StreamIdentifier, new StreamRevision(header.Options.Revision),
                            actualStreamRevision);

                        if (operationOptions.ThrowOnAppendFailure)
                        {
                            if (response.WrongExpectedVersion.ExpectedRevisionOptionCase == AppendResp.Types
                                .WrongExpectedVersion.ExpectedRevisionOptionOneofCase.ExpectedRevision)
                            {
                                throw new WrongExpectedVersionException(header.Options.StreamIdentifier,
                                                                        new StreamRevision(response.WrongExpectedVersion.ExpectedRevision),
                                                                        actualStreamRevision);
                            }

                            var expectedStreamState = response.WrongExpectedVersion.ExpectedRevisionOptionCase switch {
                                AppendResp.Types.WrongExpectedVersion.ExpectedRevisionOptionOneofCase.ExpectedAny =>
                                StreamState.Any,
                                AppendResp.Types.WrongExpectedVersion.ExpectedRevisionOptionOneofCase.ExpectedNoStream =>
                                StreamState.NoStream,
                                AppendResp.Types.WrongExpectedVersion.ExpectedRevisionOptionOneofCase.ExpectedStreamExists =>
                                StreamState.StreamExists,
                                _ => throw new InvalidOperationException()
                            };

                            throw new WrongExpectedVersionException(header.Options.StreamIdentifier,
                                                                    expectedStreamState, actualStreamRevision);
                        }

                        if (response.WrongExpectedVersion.ExpectedRevisionOptionCase == AppendResp.Types
                            .WrongExpectedVersion.ExpectedRevisionOptionOneofCase.ExpectedRevision)
                        {
                            writeResult = new WrongExpectedVersionResult(header.Options.StreamIdentifier,
                                                                         new StreamRevision(response.WrongExpectedVersion.ExpectedRevision),
                                                                         actualStreamRevision);
                        }
                        else
                        {
                            writeResult = new WrongExpectedVersionResult(header.Options.StreamIdentifier,
                                                                         StreamRevision.None,
                                                                         actualStreamRevision);
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("The operation completed with an unexpected result.");
                    }
                }
            }

            return(writeResult);
        }
    }
}