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); } }
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); } }
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); }
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); } } } }
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); }