Skip to content

Commit 3df23e2

Browse files
authored
Merge pull request #1707 from ydb-platform/topic-split-merge
Topic split merge
2 parents 68da27d + 5d74b11 commit 3df23e2

File tree

20 files changed

+795
-50
lines changed

20 files changed

+795
-50
lines changed

Diff for: CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Supported topic split merge server feature for topic reader (no api changed)
2+
13
## v3.104.7
24
* Added public type alias `ydb.Params` to `internal/params.Parameters` for external usage
35

Diff for: internal/grpcwrapper/rawtopic/client.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ func (c *Client) DropTopic(
8888
return res, err
8989
}
9090

91-
func (c *Client) StreamRead(ctxStreamLifeTime context.Context) (rawtopicreader.StreamReader, error) {
91+
func (c *Client) StreamRead(
92+
ctxStreamLifeTime context.Context,
93+
readerID int64,
94+
tracer *trace.Topic,
95+
) (rawtopicreader.StreamReader, error) {
9296
protoResp, err := c.service.StreamRead(ctxStreamLifeTime)
9397
if err != nil {
9498
return rawtopicreader.StreamReader{}, xerrors.WithStackTrace(
@@ -98,7 +102,11 @@ func (c *Client) StreamRead(ctxStreamLifeTime context.Context) (rawtopicreader.S
98102
)
99103
}
100104

101-
return rawtopicreader.StreamReader{Stream: protoResp}, nil
105+
return rawtopicreader.StreamReader{
106+
Stream: protoResp,
107+
ReaderID: readerID,
108+
Tracer: tracer,
109+
}, nil
102110
}
103111

104112
func (c *Client) StreamWrite(

Diff for: internal/grpcwrapper/rawtopic/controlplane_types.go

+86-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ import (
1010
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
1111
)
1212

13-
var errUnexpectedNilPartitioningSettings = xerrors.Wrap(errors.New("ydb: unexpected nil partitioning settings"))
13+
var (
14+
errUnexpectedNilPartitioningSettings = xerrors.Wrap(errors.New("ydb: unexpected nil partitioning settings"))
15+
errUnexpecredNilAutoPartitioningSettings = xerrors.Wrap(errors.New("ydb: unexpected nil auto-partitioning settings"))
16+
errUnexpectedNilAutoPartitionWriteSpeed = xerrors.Wrap(errors.New("ydb: unexpected nil auto-partition write speed"))
17+
)
1418

1519
type Consumer struct {
1620
Name string
@@ -47,8 +51,10 @@ const (
4751
)
4852

4953
type PartitioningSettings struct {
50-
MinActivePartitions int64
51-
PartitionCountLimit int64
54+
MinActivePartitions int64
55+
MaxActivePartitions int64
56+
PartitionCountLimit int64
57+
AutoPartitioningSettings AutoPartitioningSettings
5258
}
5359

5460
func (s *PartitioningSettings) FromProto(proto *Ydb_Topic.PartitioningSettings) error {
@@ -57,26 +63,101 @@ func (s *PartitioningSettings) FromProto(proto *Ydb_Topic.PartitioningSettings)
5763
}
5864

5965
s.MinActivePartitions = proto.GetMinActivePartitions()
66+
s.MaxActivePartitions = proto.GetMaxActivePartitions()
6067
s.PartitionCountLimit = proto.GetPartitionCountLimit() //nolint:staticcheck
6168

6269
return nil
6370
}
6471

6572
func (s *PartitioningSettings) ToProto() *Ydb_Topic.PartitioningSettings {
6673
return &Ydb_Topic.PartitioningSettings{
67-
MinActivePartitions: s.MinActivePartitions,
68-
PartitionCountLimit: s.PartitionCountLimit,
74+
MinActivePartitions: s.MinActivePartitions,
75+
MaxActivePartitions: s.MaxActivePartitions,
76+
PartitionCountLimit: s.PartitionCountLimit,
77+
AutoPartitioningSettings: s.AutoPartitioningSettings.ToProto(),
6978
}
7079
}
7180

81+
type AutoPartitioningSettings struct {
82+
AutoPartitioningStrategy AutoPartitioningStrategy
83+
AutoPartitioningWriteSpeedStrategy AutoPartitioningWriteSpeedStrategy
84+
}
85+
86+
func (s *AutoPartitioningSettings) ToProto() *Ydb_Topic.AutoPartitioningSettings {
87+
if s == nil {
88+
return nil
89+
}
90+
91+
return &Ydb_Topic.AutoPartitioningSettings{
92+
Strategy: s.AutoPartitioningStrategy.ToProto(),
93+
PartitionWriteSpeed: s.AutoPartitioningWriteSpeedStrategy.ToProto(),
94+
}
95+
}
96+
97+
func (s *AutoPartitioningSettings) FromProto(proto *Ydb_Topic.AutoPartitioningSettings) error {
98+
if proto == nil {
99+
return xerrors.WithStackTrace(errUnexpecredNilAutoPartitioningSettings)
100+
}
101+
s.AutoPartitioningStrategy = AutoPartitioningStrategy(proto.GetStrategy())
102+
103+
if proto.GetPartitionWriteSpeed() != nil {
104+
if err := s.AutoPartitioningWriteSpeedStrategy.FromProto(proto.GetPartitionWriteSpeed()); err != nil {
105+
return err
106+
}
107+
}
108+
109+
return nil
110+
}
111+
112+
type AutoPartitioningStrategy int32
113+
114+
const (
115+
AutoPartitioningStrategyUnspecified = AutoPartitioningStrategy(Ydb_Topic.AutoPartitioningStrategy_AUTO_PARTITIONING_STRATEGY_UNSPECIFIED) //nolint:lll
116+
AutoPartitioningStrategyDisabled = AutoPartitioningStrategy(Ydb_Topic.AutoPartitioningStrategy_AUTO_PARTITIONING_STRATEGY_DISABLED) //nolint:lll
117+
AutoPartitioningStrategyScaleUpAndDown = AutoPartitioningStrategy(Ydb_Topic.AutoPartitioningStrategy_AUTO_PARTITIONING_STRATEGY_SCALE_UP_AND_DOWN) //nolint:lll
118+
AutoPartitioningStrategyPaused = AutoPartitioningStrategy(Ydb_Topic.AutoPartitioningStrategy_AUTO_PARTITIONING_STRATEGY_PAUSED) //nolint:lll
119+
)
120+
121+
func (s AutoPartitioningStrategy) ToProto() Ydb_Topic.AutoPartitioningStrategy {
122+
return Ydb_Topic.AutoPartitioningStrategy(s)
123+
}
124+
125+
type AutoPartitioningWriteSpeedStrategy struct {
126+
StabilizationWindow rawoptional.Duration
127+
UpUtilizationPercent int32
128+
DownUtilizationPercent int32
129+
}
130+
131+
func (s *AutoPartitioningWriteSpeedStrategy) ToProto() *Ydb_Topic.AutoPartitioningWriteSpeedStrategy {
132+
return &Ydb_Topic.AutoPartitioningWriteSpeedStrategy{
133+
StabilizationWindow: s.StabilizationWindow.ToProto(),
134+
UpUtilizationPercent: s.UpUtilizationPercent,
135+
DownUtilizationPercent: s.DownUtilizationPercent,
136+
}
137+
}
138+
139+
func (s *AutoPartitioningWriteSpeedStrategy) FromProto(speed *Ydb_Topic.AutoPartitioningWriteSpeedStrategy) error {
140+
if speed == nil {
141+
return xerrors.WithStackTrace(errUnexpectedNilAutoPartitionWriteSpeed)
142+
}
143+
144+
s.StabilizationWindow.MustFromProto(speed.GetStabilizationWindow())
145+
s.UpUtilizationPercent = speed.GetUpUtilizationPercent()
146+
s.DownUtilizationPercent = speed.GetDownUtilizationPercent()
147+
148+
return nil
149+
}
150+
72151
type AlterPartitioningSettings struct {
73152
SetMinActivePartitions rawoptional.Int64
153+
SetMaxActivePartitions rawoptional.Int64
74154
SetPartitionCountLimit rawoptional.Int64
75155
}
76156

77157
func (s *AlterPartitioningSettings) ToProto() *Ydb_Topic.AlterPartitioningSettings {
78158
return &Ydb_Topic.AlterPartitioningSettings{
79159
SetMinActivePartitions: s.SetMinActivePartitions.ToProto(),
160+
SetMaxActivePartitions: s.SetMaxActivePartitions.ToProto(),
80161
SetPartitionCountLimit: s.SetPartitionCountLimit.ToProto(),
81162
}
82163
}

Diff for: internal/grpcwrapper/rawtopic/rawtopicreader/messages.go

+27-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var (
2020
errUnexpectedProtoNilStartPartitionSessionRequest = xerrors.Wrap(errors.New("ydb: unexpected proto nil start partition session request")) //nolint:lll
2121
errUnexpectedNilPartitionSession = xerrors.Wrap(errors.New("ydb: unexpected proto nil partition session in start partition session request")) //nolint:lll
2222
errUnexpectedGrpcNilStopPartitionSessionRequest = xerrors.Wrap(errors.New("ydb: unexpected grpc nil stop partition session request")) //nolint:lll
23+
errUnexpectedGrpcNilEndPartitionSession = xerrors.Wrap(errors.New("ydb: unexpected grpc nil end partition session")) //nolint:lll
2324
)
2425

2526
type PartitionSessionID int64
@@ -92,12 +93,14 @@ type InitRequest struct {
9293

9394
TopicsReadSettings []TopicReadSettings
9495

95-
Consumer string
96+
Consumer string
97+
AutoPartitioningSupport bool
9698
}
9799

98100
func (r *InitRequest) toProto() *Ydb_Topic.StreamReadMessage_InitRequest {
99101
p := &Ydb_Topic.StreamReadMessage_InitRequest{
100-
Consumer: r.Consumer,
102+
Consumer: r.Consumer,
103+
AutoPartitioningSupport: r.AutoPartitioningSupport,
101104
}
102105

103106
p.TopicsReadSettings = make([]*Ydb_Topic.StreamReadMessage_InitRequest_TopicReadSettings, len(r.TopicsReadSettings))
@@ -477,3 +480,25 @@ func (r *StopPartitionSessionResponse) toProto() *Ydb_Topic.StreamReadMessage_St
477480
PartitionSessionId: r.PartitionSessionID.ToInt64(),
478481
}
479482
}
483+
484+
type EndPartitionSession struct {
485+
serverMessageImpl
486+
487+
rawtopiccommon.ServerMessageMetadata
488+
489+
PartitionSessionID PartitionSessionID
490+
AdjacentPartitionIDs []int64
491+
ChildPartitionIDs []int64
492+
}
493+
494+
func (r *EndPartitionSession) fromProto(proto *Ydb_Topic.StreamReadMessage_EndPartitionSession) error {
495+
if proto == nil {
496+
return xerrors.WithStackTrace(errUnexpectedGrpcNilEndPartitionSession)
497+
}
498+
499+
r.PartitionSessionID.FromInt64(proto.GetPartitionSessionId())
500+
r.AdjacentPartitionIDs = proto.GetAdjacentPartitionIds()
501+
r.ChildPartitionIDs = proto.GetChildPartitionIds()
502+
503+
return nil
504+
}

Diff for: internal/grpcwrapper/rawtopic/rawtopicreader/rawtopicreader.go

+64-22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/ydb-platform/ydb-go-sdk/v3/internal/grpcwrapper/rawtopic/rawtopiccommon"
1212
"github.com/ydb-platform/ydb-go-sdk/v3/internal/grpcwrapper/rawydb"
1313
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
14+
"github.com/ydb-platform/ydb-go-sdk/v3/trace"
1415
)
1516

1617
var ErrUnexpectedMessageType = errors.New("unexpected message type")
@@ -22,16 +23,36 @@ type GrpcStream interface {
2223
}
2324

2425
type StreamReader struct {
25-
Stream GrpcStream
26+
Stream GrpcStream
27+
ReaderID int64
28+
29+
Tracer *trace.Topic
30+
sessionID string
31+
sentMessageCount int
32+
receiveMessageCount int
2633
}
2734

2835
func (s StreamReader) CloseSend() error {
2936
return s.Stream.CloseSend()
3037
}
3138

3239
//nolint:funlen
33-
func (s StreamReader) Recv() (ServerMessage, error) {
40+
func (s StreamReader) Recv() (_ ServerMessage, resErr error) {
3441
grpcMess, err := s.Stream.Recv()
42+
43+
defer func() {
44+
s.receiveMessageCount++
45+
46+
trace.TopicOnReaderReceiveGRPCMessage(
47+
s.Tracer,
48+
s.ReaderID,
49+
s.sessionID,
50+
s.receiveMessageCount,
51+
grpcMess,
52+
resErr,
53+
)
54+
}()
55+
3556
if xerrors.Is(err, io.EOF) {
3657
return nil, err
3758
}
@@ -53,6 +74,8 @@ func (s StreamReader) Recv() (ServerMessage, error) {
5374

5475
switch m := grpcMess.GetServerMessage().(type) {
5576
case *Ydb_Topic.StreamReadMessage_FromServer_InitResponse:
77+
s.sessionID = m.InitResponse.GetSessionId()
78+
5679
resp := &InitResponse{}
5780
resp.ServerMessageMetadata = meta
5881
resp.fromProto(m.InitResponse)
@@ -82,6 +105,16 @@ func (s StreamReader) Recv() (ServerMessage, error) {
82105
}
83106

84107
return req, nil
108+
109+
case *Ydb_Topic.StreamReadMessage_FromServer_EndPartitionSession:
110+
req := &EndPartitionSession{}
111+
req.ServerMessageMetadata = meta
112+
if err = req.fromProto(m.EndPartitionSession); err != nil {
113+
return nil, err
114+
}
115+
116+
return req, nil
117+
85118
case *Ydb_Topic.StreamReadMessage_FromServer_CommitOffsetResponse:
86119
resp := &CommitOffsetResponse{}
87120
resp.ServerMessageMetadata = meta
@@ -113,66 +146,75 @@ func (s StreamReader) Recv() (ServerMessage, error) {
113146
}
114147
}
115148

116-
func (s StreamReader) Send(msg ClientMessage) (err error) {
149+
//nolint:funlen
150+
func (s StreamReader) Send(msg ClientMessage) (resErr error) {
117151
defer func() {
118-
err = xerrors.Transport(err)
152+
resErr = xerrors.Transport(resErr)
119153
}()
154+
155+
var grpcMess *Ydb_Topic.StreamReadMessage_FromClient
120156
switch m := msg.(type) {
121157
case *InitRequest:
122-
grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{
158+
grpcMess = &Ydb_Topic.StreamReadMessage_FromClient{
123159
ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_InitRequest{InitRequest: m.toProto()},
124160
}
125161

126-
return s.Stream.Send(grpcMess)
127162
case *ReadRequest:
128-
grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{
163+
grpcMess = &Ydb_Topic.StreamReadMessage_FromClient{
129164
ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_ReadRequest{ReadRequest: m.toProto()},
130165
}
131-
132-
return s.Stream.Send(grpcMess)
133166
case *StartPartitionSessionResponse:
134-
grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{
167+
grpcMess = &Ydb_Topic.StreamReadMessage_FromClient{
135168
ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_StartPartitionSessionResponse{
136169
StartPartitionSessionResponse: m.toProto(),
137170
},
138171
}
139-
140-
return s.Stream.Send(grpcMess)
141172
case *StopPartitionSessionResponse:
142-
grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{
173+
grpcMess = &Ydb_Topic.StreamReadMessage_FromClient{
143174
ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_StopPartitionSessionResponse{
144175
StopPartitionSessionResponse: m.toProto(),
145176
},
146177
}
147178

148-
return s.Stream.Send(grpcMess)
149179
case *CommitOffsetRequest:
150-
grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{
180+
grpcMess = &Ydb_Topic.StreamReadMessage_FromClient{
151181
ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_CommitOffsetRequest{
152182
CommitOffsetRequest: m.toProto(),
153183
},
154184
}
155185

156-
return s.Stream.Send(grpcMess)
157186
case *PartitionSessionStatusRequest:
158-
grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{
187+
grpcMess = &Ydb_Topic.StreamReadMessage_FromClient{
159188
ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_PartitionSessionStatusRequest{
160189
PartitionSessionStatusRequest: m.toProto(),
161190
},
162191
}
163192

164-
return s.Stream.Send(grpcMess)
165193
case *UpdateTokenRequest:
166-
grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{
194+
grpcMess = &Ydb_Topic.StreamReadMessage_FromClient{
167195
ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_UpdateTokenRequest{
168196
UpdateTokenRequest: m.ToProto(),
169197
},
170198
}
199+
}
171200

172-
return s.Stream.Send(grpcMess)
173-
default:
174-
return xerrors.WithStackTrace(fmt.Errorf("ydb: send unexpected message type: %v", reflect.TypeOf(msg)))
201+
if grpcMess == nil {
202+
resErr = xerrors.WithStackTrace(fmt.Errorf("ydb: send unexpected message type: %v", reflect.TypeOf(msg)))
203+
} else {
204+
resErr = s.Stream.Send(grpcMess)
175205
}
206+
207+
s.sentMessageCount++
208+
trace.TopicOnReaderSentGRPCMessage(
209+
s.Tracer,
210+
s.ReaderID,
211+
s.sessionID,
212+
s.sentMessageCount,
213+
grpcMess,
214+
resErr,
215+
)
216+
217+
return resErr
176218
}
177219

178220
type ClientMessage interface {

Diff for: internal/topic/topicclientinternal/client.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,14 @@ func (c *Client) StartReader(
300300
readSelectors topicoptions.ReadSelectors,
301301
opts ...topicoptions.ReaderOption,
302302
) (*topicreader.Reader, error) {
303-
var connector topicreaderinternal.TopicSteamReaderConnect = func(ctx context.Context) (
303+
var connector topicreaderinternal.TopicSteamReaderConnect = func(
304+
ctx context.Context,
305+
readerID int64,
306+
tracer *trace.Topic,
307+
) (
304308
topicreadercommon.RawTopicReaderStream, error,
305309
) {
306-
return c.rawClient.StreamRead(ctx)
310+
return c.rawClient.StreamRead(ctx, readerID, tracer)
307311
}
308312

309313
defaultOpts := []topicoptions.ReaderOption{

0 commit comments

Comments
 (0)