Skip to content

Commit 98db576

Browse files
authored
CBG-5434: Avoid calling ResyncManager.Resume for non distributed resync (#8333)
1 parent 95aa525 commit 98db576

3 files changed

Lines changed: 35 additions & 26 deletions

File tree

db/background_mgr.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@ func (b *BackgroundManager) callUpdateDatabaseState(ctx context.Context, running
162162
// errBackgroundManagerStatusNotRunning. Only supported for multi-node background managers.
163163
func (b *BackgroundManager) Resume(ctx context.Context) error {
164164
if b.mode() != backgroundManagerModeMultiNode {
165-
return fmt.Errorf("Resume is only supported for multi-node background managers (process %q)", b.name)
165+
err := fmt.Errorf("Resume is only supported for multi-node background managers (process %q)", b.name)
166+
base.WarnfCtx(ctx, "%v", err)
167+
return err
166168
}
167169

168170
docID := b.clusterAwareOptions.StatusDocID()

db/database.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,11 @@ func NewDatabaseContext(ctx context.Context, dbName string, bucket base.Bucket,
628628
dbContext.ResyncManager = NewResyncManagerDCP(dbContext, distributedResync)
629629
dbContext.AsyncIndexInitManager = NewAsyncIndexInitManager(metadataStore, dbContext.MetadataKeys)
630630

631-
dbContext.DBStateManager = NewDatabaseStateMgr(metadataStore, metaKeys.DatabaseStateKey(), dbContext.ResyncManager.Resume)
631+
var resumeResync resyncResumeFunc
632+
if distributedResync {
633+
resumeResync = dbContext.ResyncManager.Resume
634+
}
635+
dbContext.DBStateManager = NewDatabaseStateMgr(metadataStore, metaKeys.DatabaseStateKey(), resumeResync)
632636

633637
return dbContext, nil
634638
}

db/database_state.go

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,32 @@ import (
1717
"github.com/couchbase/sync_gateway/base"
1818
)
1919

20+
// resyncResumeFunc is a callback function to call to resume a resync process.
21+
type resyncResumeFunc func(ctx context.Context) error
22+
2023
type DatabaseState struct {
2124
ResyncRunning *bool `json:"resync,omitempty"`
2225
}
2326

2427
type DatabaseStateMgr struct {
25-
CAS uint64
26-
dbStateID string
27-
metadataStore base.DataStore
28-
pollingInterval time.Duration
29-
resumeResyncFunc func(ctx context.Context) error
30-
lock sync.Mutex
31-
terminator chan struct{}
32-
done chan struct{}
28+
CAS uint64
29+
dbStateID string
30+
metadataStore base.DataStore
31+
pollingInterval time.Duration
32+
resumeResync resyncResumeFunc
33+
lock sync.Mutex
34+
terminator chan struct{}
35+
done chan struct{}
3336
}
3437

35-
// NewDatabaseStateMgr creates a DatabaseStateMgr for the given database. resumeResyncFunc is called by the polling loop
36-
// when a state change is detected with ResyncRunning set to true; it should resume the resync process.
37-
func NewDatabaseStateMgr(metadataStore base.DataStore, dbStateID string, resumeResyncFunc func(ctx context.Context) error) *DatabaseStateMgr {
38+
// NewDatabaseStateMgr creates a DatabaseStateMgr for the given database. If resumeResync is non-nil, it will be invoked when DatabaseState.ResyncRunning is detected as changed on the bucket.
39+
func NewDatabaseStateMgr(metadataStore base.DataStore, dbStateID string, resumeResync resyncResumeFunc) *DatabaseStateMgr {
3840
return &DatabaseStateMgr{
39-
dbStateID: dbStateID,
40-
CAS: 0,
41-
metadataStore: metadataStore,
42-
pollingInterval: 10 * time.Second,
43-
resumeResyncFunc: resumeResyncFunc,
41+
dbStateID: dbStateID,
42+
CAS: 0,
43+
metadataStore: metadataStore,
44+
pollingInterval: 10 * time.Second,
45+
resumeResync: resumeResync,
4446
}
4547
}
4648

@@ -112,19 +114,20 @@ func (dbMgr *DatabaseStateMgr) StartPolling(ctx context.Context) {
112114
}()
113115
}
114116

115-
// poll checks whether the state document has been updated and, if ResyncRunning is true, invokes
116-
// resumeResyncFunc. The locally held CAS is only advanced after resumeResyncFunc succeeds (or when no handler
117-
// action is required), so a transient resumeResyncFunc error leaves the CAS stale and the next tick retries.
117+
// poll checks whether the state document has been updated and calls appropriate callback functions. If the callback
118+
// functions return any errors, do not update the CAS so the next time poll runs, the callback function will rerun.
118119
func (dbMgr *DatabaseStateMgr) poll(ctx context.Context) {
119120
newCAS, state, ok := dbMgr.isUpdated(ctx)
120121
if !ok {
121122
return
122123
}
123-
if state.ResyncRunning != nil && *state.ResyncRunning {
124-
err := dbMgr.resumeResyncFunc(ctx)
125-
if err != nil {
126-
base.WarnfCtx(ctx, "failed to resume resync from DatabaseStateMgr: %v, will try again.", err)
127-
return // leave CAS stale so next tick retries
124+
if dbMgr.resumeResync != nil {
125+
if state.ResyncRunning != nil && *state.ResyncRunning {
126+
err := dbMgr.resumeResync(ctx)
127+
if err != nil {
128+
base.WarnfCtx(ctx, "failed to resume resync from DatabaseStateMgr: %v, will try again.", err)
129+
return // leave CAS stale so next tick retries
130+
}
128131
}
129132
}
130133
dbMgr.lock.Lock()

0 commit comments

Comments
 (0)