Skip to content

Commit ab8fb03

Browse files
feat: supported Commit() & ReadAsync() in TopicReader (#265)
1 parent 943f8a0 commit ab8fb03

File tree

10 files changed

+525
-373
lines changed

10 files changed

+525
-373
lines changed

src/Ydb.Sdk/src/Services/Topic/Exceptions.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,13 @@ public class ReaderException : Exception
1919
{
2020
public ReaderException(string message) : base(message)
2121
{
22-
Status = new Status(StatusCode.Unspecified);
2322
}
2423

2524
public ReaderException(string message, Status status) : base(message + ": " + status)
2625
{
27-
Status = status;
2826
}
2927

30-
public ReaderException(string message, Driver.TransportException e) : base(message, e)
28+
public ReaderException(string message, Exception inner) : base(message, inner)
3129
{
32-
Status = e.Status;
3330
}
34-
35-
public Status Status { get; }
3631
}

src/Ydb.Sdk/src/Services/Topic/IReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ public interface IReader<TValue> : IDisposable
66
{
77
public ValueTask<Message<TValue>> ReadAsync(CancellationToken cancellationToken = default);
88

9-
public ValueTask<BatchMessage<TValue>> ReadBatchAsync(CancellationToken cancellationToken = default);
9+
public ValueTask<BatchMessages<TValue>> ReadBatchAsync(CancellationToken cancellationToken = default);
1010
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using System.Collections.Immutable;
2+
using System.Diagnostics.CodeAnalysis;
3+
using Ydb.Topic;
4+
5+
namespace Ydb.Sdk.Services.Topic.Reader;
6+
7+
internal class InternalBatchMessages<TValue>
8+
{
9+
private readonly StreamReadMessage.Types.ReadResponse.Types.Batch _batch;
10+
private readonly PartitionSession _partitionSession;
11+
private readonly IDeserializer<TValue> _deserializer;
12+
private readonly ReaderSession<TValue> _readerSession;
13+
private readonly long _approximatelyBatchSize;
14+
15+
private int _startMessageDataIndex;
16+
17+
private int OriginalMessageCount => _batch.MessageData.Count;
18+
private bool IsActive => _startMessageDataIndex < OriginalMessageCount && _readerSession.IsActive;
19+
20+
public InternalBatchMessages(
21+
StreamReadMessage.Types.ReadResponse.Types.Batch batch,
22+
PartitionSession partitionsSession,
23+
ReaderSession<TValue> readerSession,
24+
long approximatelyBatchSize,
25+
IDeserializer<TValue> deserializer)
26+
{
27+
_batch = batch;
28+
_partitionSession = partitionsSession;
29+
_readerSession = readerSession;
30+
_deserializer = deserializer;
31+
_approximatelyBatchSize = approximatelyBatchSize;
32+
}
33+
34+
internal bool TryDequeueMessage([MaybeNullWhen(false)] out Message<TValue> message)
35+
{
36+
if (!IsActive)
37+
{
38+
message = default;
39+
return false;
40+
}
41+
42+
var index = _startMessageDataIndex++;
43+
var approximatelyMessageBytesSize = Utils
44+
.CalculateApproximatelyBytesSize(_approximatelyBatchSize, OriginalMessageCount, index);
45+
var messageData = _batch.MessageData[index];
46+
47+
TValue value;
48+
try
49+
{
50+
value = _deserializer.Deserialize(messageData.Data.ToByteArray());
51+
}
52+
catch (Exception e)
53+
{
54+
throw new ReaderException("Error when deserializing message data", e);
55+
}
56+
57+
_readerSession.TryReadRequestBytes(approximatelyMessageBytesSize);
58+
var nextCommitedOffset = messageData.Offset + 1;
59+
60+
message = new Message<TValue>(
61+
data: value,
62+
topic: _partitionSession.TopicPath,
63+
partitionId: _partitionSession.PartitionId,
64+
partitionSessionId: _partitionSession.PartitionSessionId,
65+
producerId: _batch.ProducerId,
66+
createdAt: messageData.CreatedAt.ToDateTime(),
67+
metadata: messageData.MetadataItems.Select(item => new Metadata(item.Key, item.Value.ToByteArray()))
68+
.ToImmutableArray(),
69+
offsetsRange: new OffsetsRange
70+
{ Start = _partitionSession.PrevEndOffsetMessage, End = nextCommitedOffset },
71+
readerSession: _readerSession
72+
);
73+
_partitionSession.PrevEndOffsetMessage = nextCommitedOffset;
74+
75+
return true;
76+
}
77+
78+
internal bool TryPublicBatch([MaybeNullWhen(false)] out BatchMessages<TValue> batchMessages)
79+
{
80+
if (!IsActive)
81+
{
82+
batchMessages = default;
83+
return false;
84+
}
85+
86+
var nextCommitedOffset = _batch.MessageData.Last().Offset + 1;
87+
var offsetsRangeBatch = new OffsetsRange
88+
{ Start = _partitionSession.PrevEndOffsetMessage, End = nextCommitedOffset };
89+
_partitionSession.PrevEndOffsetMessage = nextCommitedOffset;
90+
91+
var messages = new List<Message<TValue>>();
92+
while (TryDequeueMessage(out var message))
93+
{
94+
messages.Add(message);
95+
}
96+
97+
batchMessages = new BatchMessages<TValue>(
98+
batch: messages,
99+
readerSession: _readerSession,
100+
offsetsRange: offsetsRangeBatch,
101+
partitionSessionId: _partitionSession.PartitionSessionId
102+
);
103+
104+
return true;
105+
}
106+
}
107+
108+
internal record CommitSending(
109+
OffsetsRange OffsetsRange,
110+
TaskCompletionSource TcsCommit
111+
);

src/Ydb.Sdk/src/Services/Topic/Reader/InternalMessage.cs

Lines changed: 0 additions & 91 deletions
This file was deleted.

src/Ydb.Sdk/src/Services/Topic/Reader/Message.cs

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ namespace Ydb.Sdk.Services.Topic.Reader;
55

66
public class Message<TValue>
77
{
8+
private readonly long _partitionSessionId;
89
private readonly OffsetsRange _offsetsRange;
9-
private readonly ReaderSession _readerSession;
10-
private readonly long _approximatelyBytesSize;
10+
private readonly ReaderSession<TValue> _readerSession;
1111

1212
internal Message(
1313
TValue data,
1414
string topic,
1515
long partitionId,
16+
long partitionSessionId,
1617
string producerId,
1718
DateTime createdAt,
1819
ImmutableArray<Metadata> metadata,
1920
OffsetsRange offsetsRange,
20-
ReaderSession readerSession,
21-
long approximatelyBytesSize)
21+
ReaderSession<TValue> readerSession)
2222
{
2323
Data = data;
2424
Topic = topic;
@@ -27,9 +27,9 @@ internal Message(
2727
CreatedAt = createdAt;
2828
Metadata = metadata;
2929

30+
_partitionSessionId = partitionSessionId;
3031
_offsetsRange = offsetsRange;
3132
_readerSession = readerSession;
32-
_approximatelyBytesSize = approximatelyBytesSize;
3333
}
3434

3535
public TValue Data { get; }
@@ -45,56 +45,38 @@ internal Message(
4545

4646
public DateTime CreatedAt { get; }
4747

48-
public ImmutableArray<Metadata> Metadata { get; }
49-
50-
internal long Start => _offsetsRange.Start;
51-
internal long End => _offsetsRange.End;
48+
public IReadOnlyCollection<Metadata> Metadata { get; }
5249

5350
public Task CommitAsync()
5451
{
55-
return _readerSession.CommitOffsetRange(_offsetsRange, PartitionId, _approximatelyBytesSize);
52+
return _readerSession.CommitOffsetRange(_offsetsRange, _partitionSessionId);
5653
}
5754
}
5855

59-
public class BatchMessage<TValue>
56+
public class BatchMessages<TValue>
6057
{
61-
private readonly ReaderSession _readerSession;
62-
private readonly long _approximatelyBatchSize;
58+
private readonly ReaderSession<TValue> _readerSession;
59+
private readonly OffsetsRange _offsetsRange;
60+
private readonly long _partitionSessionId;
6361

64-
public ImmutableArray<Message<TValue>> Batch { get; }
62+
public IReadOnlyCollection<Message<TValue>> Batch { get; }
6563

66-
internal BatchMessage(
67-
ImmutableArray<Message<TValue>> batch,
68-
ReaderSession readerSession,
69-
long approximatelyBatchSize)
64+
internal BatchMessages(
65+
IReadOnlyCollection<Message<TValue>> batch,
66+
ReaderSession<TValue> readerSession,
67+
OffsetsRange offsetsRange,
68+
long partitionSessionId)
7069
{
7170
Batch = batch;
7271
_readerSession = readerSession;
73-
_approximatelyBatchSize = approximatelyBatchSize;
72+
_offsetsRange = offsetsRange;
73+
_partitionSessionId = partitionSessionId;
7474
}
7575

7676
public Task CommitBatchAsync()
7777
{
78-
if (Batch.Length == 0)
79-
{
80-
return Task.CompletedTask;
81-
}
82-
83-
var offsetsRange = new OffsetsRange { Start = Batch.First().Start, End = Batch.Last().End };
84-
85-
return _readerSession.CommitOffsetRange(offsetsRange, Batch.First().PartitionId, _approximatelyBatchSize);
78+
return Batch.Count == 0
79+
? Task.CompletedTask
80+
: _readerSession.CommitOffsetRange(_offsetsRange, _partitionSessionId);
8681
}
8782
}
88-
89-
public class TopicPartitionOffset
90-
{
91-
public TopicPartitionOffset(long offset, long partitionId)
92-
{
93-
Offset = offset;
94-
PartitionId = partitionId;
95-
}
96-
97-
public long Offset { get; }
98-
99-
public long PartitionId { get; }
100-
}

0 commit comments

Comments
 (0)