Exemplo n.º 1
0
        private async Task PushToSubscriber(
            SqliteCommand command,
            long start,
            ISubscription subscription,
            bool broadcastPosition,
            CancellationToken cancellationToken)
        {
            long indexOrPosition = 0;
            await subscription.OnStartAsync(start).ConfigureAwait(false);

            try
            {
                using (var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
                {
                    while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                    {
                        var chunk = new SqliteChunk
                        {
                            Position    = reader.GetInt64(0),
                            PartitionId = reader.GetString(1),
                            Index       = reader.GetInt64(2),
                            OperationId = reader.GetString(4),
                            Deleted     = reader.GetBoolean(5)
                        };

                        indexOrPosition = broadcastPosition ? chunk.Position : chunk.Index;

                        // to handle exceptions with correct position
                        chunk.Payload = _options.Serializer.Deserialize(reader.GetString(3));

                        if (!await subscription.OnNextAsync(chunk).ConfigureAwait(false))
                        {
                            await subscription.StoppedAsync(chunk.Position).ConfigureAwait(false);

                            return;
                        }
                    }
                }

                await subscription.CompletedAsync(indexOrPosition).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                await subscription.OnErrorAsync(indexOrPosition, e).ConfigureAwait(false);
            }
        }
Exemplo n.º 2
0
        private async Task <IChunk> ReadSingleChunk(SqliteCommand command, CancellationToken cancellationToken)
        {
            using (var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
            {
                if (!reader.HasRows)
                {
                    return(null);
                }

                await reader.ReadAsync(cancellationToken).ConfigureAwait(false);

                var chunk = new SqliteChunk()
                {
                    Position    = reader.GetInt64(0),
                    PartitionId = reader.GetString(1),
                    Index       = reader.GetInt64(2),
                    OperationId = reader.GetString(4),
                    Payload     = _options.Serializer.Deserialize(reader.GetString(3)),
                };
                return(chunk);
            }
        }
Exemplo n.º 3
0
        private async Task <IList <SqliteChunk> > Load(SqliteCommand command, CancellationToken cancellationToken)
        {
            var list = new List <SqliteChunk>();

            using (var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
            {
                while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                {
                    var chunk = new SqliteChunk
                    {
                        Position    = reader.GetInt64(0),
                        PartitionId = reader.GetString(1),
                        Index       = reader.GetInt64(2),
                        OperationId = reader.GetString(4),
                        Payload     = _options.Serializer.Deserialize(reader.GetString(3))
                    };

                    list.Add(chunk);
                }
            }

            return(list);
        }
Exemplo n.º 4
0
        public async Task <IChunk> ReadSingleBackwardAsync(string partitionId, long fromUpperIndexInclusive,
                                                           CancellationToken cancellationToken)
        {
            using (var connection = Connect())
            {
                await connection.OpenAsync(cancellationToken).ConfigureAwait(false);

                using (var command = new SqliteCommand(_options.GetLastChunkScript(), connection))
                {
                    command.Parameters.AddWithValue("@PartitionId", partitionId);
                    command.Parameters.AddWithValue("@toUpperIndexInclusive", fromUpperIndexInclusive);

                    using (var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
                    {
                        if (!reader.HasRows)
                        {
                            return(null);
                        }

                        await reader.ReadAsync(cancellationToken).ConfigureAwait(false);

                        var chunk = new SqliteChunk
                        {
                            Position    = reader.GetInt64(0),
                            PartitionId = reader.GetString(1),
                            Index       = reader.GetInt64(2),
                            OperationId = reader.GetString(4),
                            Deleted     = reader.GetBoolean(5)
                        };

                        chunk.Payload = _options.Serializer.Deserialize(reader.GetString(3));

                        return(chunk);
                    }
                }
            }
        }
Exemplo n.º 5
0
        public async Task <IChunk> AppendAsync(
            string partitionId,
            long index,
            object payload,
            string operationId,
            CancellationToken cancellationToken)
        {
            if (index == -1)
            {
                index = Interlocked.Increment(ref USE_SEQUENCE_INSTEAD);
            }

            var chunk = new SqliteChunk()
            {
                PartitionId = partitionId,
                Index       = index,
                Payload     = payload,
                OperationId = operationId ?? Guid.NewGuid().ToString()
            };

            string textPayload = _options.Serializer.Serialize(payload);

            try
            {
                using (var connection = Connect())
                {
                    await connection.OpenAsync(cancellationToken).ConfigureAwait(false);

                    using (var command =
                               new SqliteCommand(_options.GetPersistScript(_options.StreamsTableName), connection))
                    {
                        command.Parameters.AddWithValue("@PartitionId", partitionId);
                        command.Parameters.AddWithValue("@Index", index);
                        command.Parameters.AddWithValue("@OperationId", chunk.OperationId);
                        command.Parameters.AddWithValue("@Payload", textPayload);

                        chunk.Position =
                            (long)await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
                    }
                }
            }
            catch (SqliteException ex)
            {
                if (ex.SqliteErrorCode == DUPLICATED_INDEX_EXCEPTION)
                {
                    if (ex.Message.Contains(".PartitionId") && ex.Message.Contains(".Index"))
                    {
                        throw new DuplicateStreamIndexException(partitionId, index);
                    }

                    if (ex.Message.Contains(".PartitionId") && ex.Message.Contains(".OperationId"))
                    {
                        _logger.LogInformation(
                            $"Skipped duplicated chunk on '{partitionId}' by operation id '{operationId}'");
                        return(null);
                    }
                }

                Console.WriteLine(_options.Serializer.Serialize(ex));

                _logger.LogError(ex.Message);
                throw;
            }

            return(chunk);
        }