예제 #1
0
        private Func <CancellationToken, Task <string> > GetJsonData(PostgresqlStreamId streamId, int version)
        => async cancellationToken =>
        {
            using (var connection = await OpenConnection(cancellationToken))
                using (var transaction = connection.BeginTransaction())
                    using (var command = BuildFunctionCommand(
                               _schema.ReadJsonData,
                               transaction,
                               Parameters.StreamId(streamId),
                               Parameters.Version(version)))
                        using (var reader = await command
                                            .ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken)
                                            .NotOnCapturedContext())
                        {
                            if (!await reader.ReadAsync(cancellationToken).NotOnCapturedContext() || reader.IsDBNull(0))
                            {
                                return(null);
                            }

                            using (var textReader = reader.GetTextReader(0))
                            {
                                return(await textReader.ReadToEndAsync().NotOnCapturedContext());
                            }
                        }
        };
예제 #2
0
        private async Task DeleteStreamInternal(
            PostgresqlStreamId streamId,
            int expectedVersion,
            IDbTransaction transaction,
            CancellationToken cancellationToken)
        {
            using (var command = BuildFunctionCommand(
                       _schema.DeleteStream,
                       transaction,
                       Parameters.StreamId(streamId),
                       Parameters.ExpectedVersion(expectedVersion),
                       Parameters.CreatedUtc(_settings.GetUtcNow?.Invoke()),
                       Parameters.DeletionTrackingDisabled(_settings.DisableDeletionTracking),
                       _settings.DisableDeletionTracking ? Parameters.Empty() : Parameters.DeletedStreamId,
                       _settings.DisableDeletionTracking ? Parameters.Empty() : Parameters.DeletedStreamIdOriginal,
                       _settings.DisableDeletionTracking ? Parameters.Empty() : Parameters.DeletedStreamMessage(streamId)))
            {
                try
                {
                    await command.ExecuteNonQueryAsync(cancellationToken).NotOnCapturedContext();
                }
                catch (PostgresException ex) when(ex.IsWrongExpectedVersion())
                {
                    await transaction.RollbackAsync(cancellationToken).NotOnCapturedContext();

                    throw new WrongExpectedVersionException(
                              ErrorMessages.DeleteStreamFailedWrongExpectedVersion(streamId.IdOriginal, expectedVersion),
                              streamId.IdOriginal,
                              expectedVersion,
                              ex);
                }
            }
        }
예제 #3
0
        public StreamIdInfo(string idOriginal)
        {
            Ensure.That(idOriginal, nameof(idOriginal)).IsNotNullOrWhiteSpace();

            PostgresqlStreamId        = new PostgresqlStreamId(idOriginal);
            MetadataPosgresqlStreamId = new PostgresqlStreamId("$$" + idOriginal);
        }
        private Func <CancellationToken, Task <string> > GetJsonData(PostgresqlStreamId streamId, int version)
        => async cancellationToken =>
        {
            using (var connection = await OpenConnection(cancellationToken))
                using (var transaction = connection.BeginTransaction())
                    using (var command = BuildFunctionCommand(
                               _schema.ReadJsonData,
                               transaction,
                               Parameters.StreamId(streamId),
                               Parameters.Version(version)))
                    {
                        var jsonData = await command.ExecuteScalarAsync(cancellationToken).NotOnCapturedContext();

                        return(jsonData == DBNull.Value ? null : (string)jsonData);
                    }
        };
예제 #5
0
        private async Task <ReadStreamPage> ReadStreamInternal(
            PostgresqlStreamId streamId,
            int start,
            int count,
            ReadDirection direction,
            bool prefetch,
            ReadNextStreamPage readNext,
            NpgsqlTransaction transaction,
            CancellationToken cancellationToken)
        {
            // If the count is int.MaxValue, TSql will see it as a negative number.
            // Users shouldn't be using int.MaxValue in the first place anyway.
            count = count == int.MaxValue ? count - 1 : count;

            // To read backwards from end, need to use int MaxValue
            var streamVersion = start == StreamVersion.End ? int.MaxValue : start;

            var messages = new List <(StreamMessage message, int?maxAge)>();

            Func <List <StreamMessage>, int, int> getNextVersion;

            if (direction == ReadDirection.Forward)
            {
                getNextVersion = (events, lastVersion) =>
                {
                    if (events.Any())
                    {
                        return(events.Last().StreamVersion + 1);
                    }

                    return(lastVersion + 1);
                };
            }
            else
            {
                getNextVersion = (events, lastVersion) =>
                {
                    if (events.Any())
                    {
                        return(events.Last().StreamVersion - 1);
                    }

                    return(-1);
                };
            }

            var refcursorSql = new StringBuilder();

            using (var command = BuildFunctionCommand(
                       _schema.Read,
                       transaction,
                       Parameters.StreamId(streamId),
                       Parameters.Count(count + 1),
                       Parameters.Version(streamVersion),
                       Parameters.ReadDirection(direction),
                       Parameters.Prefetch(prefetch)))
                using (var reader = await command
                                    .ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken)
                                    .ConfigureAwait(false))
                {
                    while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                    {
                        refcursorSql.AppendLine(Schema.FetchAll(reader.GetString(0)));
                    }
                }

            using (var command = new NpgsqlCommand(refcursorSql.ToString(), transaction.Connection, transaction))
                using (var reader = await command
                                    .ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken)
                                    .ConfigureAwait(false))
                {
                    if (!reader.HasRows)
                    {
                        return(new ReadStreamPage(
                                   streamId.IdOriginal,
                                   PageReadStatus.StreamNotFound,
                                   start,
                                   -1,
                                   -1,
                                   -1,
                                   direction,
                                   true,
                                   readNext));
                    }

                    if (messages.Count == count)
                    {
                        messages.Add(default);