Example #1
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 SqlCommand(_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 MsSqlChunk
                        {
                            Position    = reader.GetInt64(0),
                            PartitionId = reader.GetString(1),
                            Index       = reader.GetInt64(2),
                            Payload     = _options.Serializer.Deserialize(reader.GetString(3)),
                            OperationId = reader.GetString(4),
                            Deleted     = reader.GetBoolean(5)
                        };

                        return(chunk);
                    }
                }
            }
        }
Example #2
0
        private async Task PushToSubscriber(SqlCommand command, long start, ISubscription subscription, CancellationToken cancellationToken)
        {
            long position = 0;
            await subscription.OnStart(start).ConfigureAwait(false);

            using (var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
            {
                while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                {
                    position = reader.GetInt64(0);

                    var chunk = new MsSqlChunk
                    {
                        Position    = position,
                        PartitionId = reader.GetString(1),
                        Index       = reader.GetInt64(2),
                        Payload     = _options.Serializer.Deserialize(reader.GetString(3)),
                        OperationId = reader.GetString(4),
                        Deleted     = reader.GetBoolean(5)
                    };

                    if (!await subscription.OnNext(chunk).ConfigureAwait(false))
                    {
                        await subscription.Stopped(chunk.Position).ConfigureAwait(false);

                        return;
                    }
                }
            }

            await subscription.Completed(position).ConfigureAwait(false);
        }
Example #3
0
        private async Task PushToSubscriber(SqlCommand 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 MsSqlChunk
                        {
                            Position    = reader.GetInt64(0),
                            PartitionId = reader.GetString(1),
                            Index       = reader.GetInt64(2),
                            OperationId = reader.GetString(4),
                        };

                        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);
            }
        }
Example #4
0
        private async Task <MsSqlChunk> ReadSingleChunk(SqlCommand 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 MsSqlChunk
                {
                    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);
            }
        }
Example #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 MsSqlChunk()
            {
                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 SqlCommand(_options.GetPersistScript(), 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 (SqlException ex)
            {
                if (ex.Number == DUPLICATED_INDEX_EXCEPTION)
                {
                    if (ex.Message.Contains("_IDX"))
                    {
                        throw new DuplicateStreamIndexException(partitionId, index);
                    }

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

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

            return(chunk);
        }