Skip to content

Commit f355d8e

Browse files
committed
change writesOff to send the finalTs
1 parent c6e4db9 commit f355d8e

File tree

6 files changed

+78
-42
lines changed

6 files changed

+78
-42
lines changed

internal/verifier/change_stream.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,26 @@ func (verifier *Verifier) GetChangeStreamFilter() []bson.D {
126126
return []bson.D{stage}
127127
}
128128

129-
func (verifier *Verifier) readAndHandleOneChangeEventBatch(ctx context.Context, cs *mongo.ChangeStream) error {
129+
func (verifier *Verifier) readAndHandleOneChangeEventBatch(
130+
ctx context.Context,
131+
cs *mongo.ChangeStream,
132+
finalTs *primitive.Timestamp,
133+
) error {
130134
eventsRead := 0
131135
var changeEventBatch []ParsedEvent
132136

133137
for hasEventInBatch := true; hasEventInBatch; hasEventInBatch = cs.RemainingBatchLength() > 0 {
138+
// Once the change stream reaches the final timestamp we should stop reading.
139+
if finalTs != nil {
140+
csTimestamp, err := extractTimestampFromResumeToken(cs.ResumeToken())
141+
if err != nil {
142+
return errors.Wrap(err, "failed to extract timestamp from change stream's resume token")
143+
}
144+
if !csTimestamp.Before(*finalTs) {
145+
break
146+
}
147+
}
148+
134149
gotEvent := cs.TryNext(ctx)
135150

136151
if cs.Err() != nil {
@@ -184,7 +199,7 @@ func (verifier *Verifier) iterateChangeStream(ctx context.Context, cs *mongo.Cha
184199

185200
for {
186201
var err error
187-
var changeStreamEnded bool
202+
var gotFinalTimestamp bool
188203

189204
select {
190205

@@ -203,7 +218,7 @@ func (verifier *Verifier) iterateChangeStream(ctx context.Context, cs *mongo.Cha
203218
Interface("finalTimestamp", finalTs).
204219
Msg("Change stream thread received final timestamp. Finalizing change stream.")
205220

206-
changeStreamEnded = true
221+
gotFinalTimestamp = true
207222

208223
// Read all change events until the source reports no events.
209224
// (i.e., the `getMore` call returns empty)
@@ -224,15 +239,15 @@ func (verifier *Verifier) iterateChangeStream(ctx context.Context, cs *mongo.Cha
224239
break
225240
}
226241

227-
err = verifier.readAndHandleOneChangeEventBatch(ctx, cs)
242+
err = verifier.readAndHandleOneChangeEventBatch(ctx, cs, &finalTs)
228243

229244
if err != nil {
230245
break
231246
}
232247
}
233248

234249
default:
235-
err = verifier.readAndHandleOneChangeEventBatch(ctx, cs)
250+
err = verifier.readAndHandleOneChangeEventBatch(ctx, cs, nil)
236251

237252
if err == nil {
238253
err = persistResumeTokenIfNeeded()
@@ -246,12 +261,12 @@ func (verifier *Verifier) iterateChangeStream(ctx context.Context, cs *mongo.Cha
246261

247262
verifier.changeStreamErrChan <- err
248263

249-
if !changeStreamEnded {
264+
if !gotFinalTimestamp {
250265
break
251266
}
252267
}
253268

254-
if changeStreamEnded {
269+
if gotFinalTimestamp {
255270
verifier.mux.Lock()
256271
verifier.changeStreamRunning = false
257272
if verifier.lastChangeEventTime != nil {
@@ -260,7 +275,7 @@ func (verifier *Verifier) iterateChangeStream(ctx context.Context, cs *mongo.Cha
260275
verifier.mux.Unlock()
261276
// since we have started Recheck, we must signal that we have
262277
// finished the change stream changes so that Recheck can continue.
263-
verifier.changeStreamDoneChan <- struct{}{}
278+
close(verifier.changeStreamDoneChan)
264279
break
265280
}
266281
}

internal/verifier/check.go

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -43,34 +43,19 @@ func (verifier *Verifier) Check(ctx context.Context, filter map[string]any) {
4343
}
4444

4545
func (verifier *Verifier) waitForChangeStream(ctx context.Context) error {
46-
verifier.mux.RLock()
47-
csRunning := verifier.changeStreamRunning
48-
verifier.mux.RUnlock()
49-
if csRunning {
50-
verifier.logger.Debug().Msg("Changestream still running, signalling that writes are done and waiting for change stream to exit")
51-
52-
finalTs, err := GetNewClusterTime(
53-
ctx,
54-
verifier.logger,
55-
verifier.srcClient,
56-
)
57-
58-
if err != nil {
59-
return errors.Wrapf(err, "failed to fetch source's cluster time")
60-
}
61-
62-
verifier.changeStreamFinalTsChan <- finalTs
63-
select {
64-
case err := <-verifier.changeStreamErrChan:
65-
verifier.logger.Warn().Err(err).
66-
Msg("Received error from change stream.")
67-
return err
68-
case <-verifier.changeStreamDoneChan:
69-
verifier.logger.Debug().
70-
Msg("Received completion signal from change stream.")
71-
break
72-
}
46+
select {
47+
case <-ctx.Done():
48+
return ctx.Err()
49+
case err := <-verifier.changeStreamErrChan:
50+
verifier.logger.Warn().Err(err).
51+
Msg("Received error from change stream.")
52+
return err
53+
case <-verifier.changeStreamDoneChan:
54+
verifier.logger.Debug().
55+
Msg("Received completion signal from change stream.")
56+
break
7357
}
58+
7459
return nil
7560
}
7661

internal/verifier/migration_verifier.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ type Verifier struct {
127127
changeStreamErrChan chan error
128128
changeStreamDoneChan chan struct{}
129129
lastChangeEventTime *primitive.Timestamp
130+
writesOffTimestamp *primitive.Timestamp
130131

131132
readConcernSetting ReadConcernSetting
132133

@@ -226,13 +227,33 @@ func (verifier *Verifier) SetFailureDisplaySize(size int64) {
226227
verifier.failureDisplaySize = size
227228
}
228229

229-
func (verifier *Verifier) WritesOff(ctx context.Context) {
230+
func (verifier *Verifier) WritesOff(ctx context.Context) error {
230231
verifier.logger.Debug().
231232
Msg("WritesOff called.")
232233

233234
verifier.mux.Lock()
235+
defer verifier.mux.Unlock()
234236
verifier.writesOff = true
235-
verifier.mux.Unlock()
237+
238+
if verifier.writesOffTimestamp == nil {
239+
verifier.logger.Debug().Msg("Change stream still running. Signalling that writes are done.")
240+
241+
finalTs, err := GetNewClusterTime(
242+
ctx,
243+
verifier.logger,
244+
verifier.srcClient,
245+
)
246+
247+
if err != nil {
248+
return errors.Wrapf(err, "failed to fetch source's cluster time")
249+
}
250+
251+
verifier.writesOffTimestamp = &finalTs
252+
253+
verifier.changeStreamFinalTsChan <- finalTs
254+
}
255+
256+
return nil
236257
}
237258

238259
func (verifier *Verifier) WritesOn(ctx context.Context) {

internal/verifier/migration_verifier_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1390,8 +1390,19 @@ func (suite *IntegrationTestSuite) TestGenerationalRechecking() {
13901390
// because of the calls to WritesOff
13911391
status, err = verifier.GetVerificationStatus()
13921392
suite.Require().NoError(err)
1393+
13931394
// there should be a failure from the src insert
1394-
suite.Require().Equal(VerificationStatus{TotalTasks: 1, FailedTasks: 1}, *status)
1395+
suite.T().Logf("status: %+v", *status)
1396+
suite.Assert().Equal(VerificationStatus{TotalTasks: 1, FailedTasks: 1}, *status)
1397+
1398+
failedTasks, incompleteTasks, err := FetchFailedAndIncompleteTasks(
1399+
ctx,
1400+
verifier.verificationTaskCollection(),
1401+
verificationTaskVerifyDocuments,
1402+
verifier.generation,
1403+
)
1404+
suite.T().Logf("failed: %+v", failedTasks)
1405+
suite.T().Logf("incomplete: %+v", incompleteTasks)
13951406

13961407
checkContinueChan <- struct{}{}
13971408
require.NoError(suite.T(), errGroup.Wait())

internal/verifier/web_server.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const RequestInProgressErrorDescription = "Another request is currently in progr
2222
// MigrationVerifierAPI represents the interaction webserver with mongosync
2323
type MigrationVerifierAPI interface {
2424
Check(ctx context.Context, filter map[string]any)
25-
WritesOff(ctx context.Context)
25+
WritesOff(ctx context.Context) error
2626
WritesOn(ctx context.Context)
2727
GetProgress(ctx context.Context) (Progress, error)
2828
}
@@ -214,7 +214,11 @@ func (server *WebServer) writesOffEndpoint(c *gin.Context) {
214214
return
215215
}
216216

217-
server.Mapi.WritesOff(context.Background())
217+
err := server.Mapi.WritesOff(context.Background())
218+
if err != nil {
219+
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
220+
return
221+
}
218222
successResponse(c)
219223
}
220224

internal/verifier/web_server_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ func NewMockVerifier() *MockVerifier {
3030
func (verifier *MockVerifier) Check(ctx context.Context, filter map[string]any) {
3131
verifier.filter = filter
3232
}
33-
func (verifier *MockVerifier) WritesOff(ctx context.Context) {}
34-
func (verifier *MockVerifier) WritesOn(ctx context.Context) {}
33+
func (verifier *MockVerifier) WritesOff(ctx context.Context) error { return nil }
34+
func (verifier *MockVerifier) WritesOn(ctx context.Context) {}
3535
func (verifier *MockVerifier) GetProgress(ctx context.Context) (Progress, error) {
3636
return Progress{}, nil
3737
}

0 commit comments

Comments
 (0)