Skip to content

Commit c3a8424

Browse files
Updated readme. Stop balancer prior to index creation to avoid deadlocks.
1 parent b6b58c7 commit c3a8424

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

cmd/docStreamer/main.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,18 @@ func createAllDeferredIndexes(ctx context.Context, docdbURI, mongoURI string, st
519519
}
520520
defer targetClient.Disconnect(ctx)
521521

522+
logging.PrintStep("Stopping MongoDB Balancer to prevent index build deadlocks...", 0)
523+
indexer.StopBalancer(ctx, targetClient)
524+
525+
// Use defer to ENSURE the balancer is restarted when this function exits,
526+
// even if an error occurs or the context is cancelled.
527+
defer func() {
528+
logging.PrintStep("Restarting MongoDB Balancer...", 0)
529+
// We use context.Background() here because if the user cancelled the operation,
530+
// the original 'ctx' is dead, and the balancer restart command would fail.
531+
indexer.StartBalancer(context.Background(), targetClient)
532+
}()
533+
522534
collectionsToMigrate, err := discover.DiscoverCollections(ctx, discClient)
523535
if err != nil {
524536
return err
@@ -535,13 +547,19 @@ func createAllDeferredIndexes(ctx context.Context, docdbURI, mongoURI string, st
535547
statusMgr.SetIndexingProgress(true, "Preparing...", 0, totalColls, false)
536548

537549
for i, collInfo := range collsWithIndexes {
550+
if ctx.Err() != nil {
551+
logging.PrintWarning("Index creation aborted due to shutdown.", 0)
552+
return ctx.Err()
553+
}
554+
538555
statusMgr.SetIndexingProgress(true, collInfo.Namespace, i, totalColls, false)
539556
targetColl := targetClient.Database(collInfo.DB).Collection(collInfo.Coll)
540557

541558
logging.PrintStep(fmt.Sprintf("[%s] Checking %d source indexes...", collInfo.Namespace, len(collInfo.Indexes)), 0)
542559

543560
if err := indexer.FinalizeIndexes(ctx, targetColl, collInfo.Indexes, collInfo.Namespace, includeTTL); err != nil {
544561
logging.PrintError(fmt.Sprintf("[%s] Failed to finalize indexes: %v", collInfo.Namespace, err), 0)
562+
return err
545563
}
546564
}
547565

@@ -852,7 +870,7 @@ func runMigrationProcess(cmd *cobra.Command, args []string) {
852870
os.Exit(1)
853871
}
854872
logging.PrintPhase("FINALIZE", "Creating deferred indexes...")
855-
if err := createAllDeferredIndexes(context.Background(), docdbURI, mongoURI, statusManager, true); err != nil {
873+
if err := createAllDeferredIndexes(ctx, docdbURI, mongoURI, statusManager, true); err != nil {
856874
logging.PrintError(fmt.Sprintf("Index creation failed: %v", err), 0)
857875
os.Exit(1)
858876
}
@@ -932,6 +950,8 @@ func runMigrationProcess(cmd *cobra.Command, args []string) {
932950
w.Write([]byte(`{"status": "finalization started"}`))
933951

934952
logging.PrintPhase("FINALIZE", "Stopping CDC to begin finalization...")
953+
statusManager.SetState("finalizing", "Stopping CDC to begin finalization")
954+
statusManager.Persist(context.Background())
935955
triggerFinalize.Store(true) // Flip the switch to trigger finalization
936956
cancel() // Tell CDC to stop safely
937957
})
@@ -1121,6 +1141,8 @@ func runMigrationProcess(cmd *cobra.Command, args []string) {
11211141

11221142
if triggerFinalize.Load() {
11231143
logging.PrintPhase("FINALIZE", "CDC safely drained. Creating deferred indexes...")
1144+
statusManager.SetState("finalizing", "Creating deferred indexes")
1145+
statusManager.Persist(context.Background())
11241146
if err := createAllDeferredIndexes(context.Background(), docdbURI, mongoURI, statusManager, true); err != nil {
11251147
logging.PrintError(fmt.Sprintf("Index creation failed: %v", err), 0)
11261148
} else {

readme.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ Percona docStreamer also has an API that allows you to perform certain status an
833833

834834
### Logs
835835

836-
Percona docStreamer generates three separate logs, each of the logs location and name can be configured via [config.yaml](./config.yaml):
836+
Percona docStreamer generates separate logs, each of the logs location and name can be configured via [config.yaml](./config.yaml):
837837

838838
1. Application Log (`logs/docStreamer.log`): Tracks the overall application status and any errors encountered.
839839
2. Full Load Log (`logs/full_load.log`): Dedicated to the initial full synchronization process. This log, together with the status endpoint, helps you monitor the progress of the initial sync.
@@ -1291,4 +1291,9 @@ By default, docStreamer safely defers TTL index creation. The safest and recomme
12911291

12921292
When you run the `docStreamer finalize` command, docStreamer safely stops the CDC stream and **automatically builds your TTL indexes** (along with any other deferred indexes). Because the data stream is stopped, this ensures your target has an exact, 1:1 match of the source data before it begins autonomously managing document expiration.
12931293

1294-
*(Alternatively, you can choose to manually create TTL indexes on the destination cluster after the migration is fully complete.)*
1294+
*(Alternatively, you can choose to manually create TTL indexes on the destination cluster after the migration is fully complete.)*
1295+
1296+
1297+
# Disclaimer
1298+
1299+
This code is not supported by Percona. It has been provided as a community contribution and is not covered under any Percona services agreement.

0 commit comments

Comments
 (0)