diff --git a/base/redactable_string.go b/base/redactable_string.go
new file mode 100644
index 0000000000..1a9bc58542
--- /dev/null
+++ b/base/redactable_string.go
@@ -0,0 +1,17 @@
+// Copyright 2024-Present Couchbase, Inc.
+//
+// Use of this software is governed by the Business Source License included
+// in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
+// in that file, in accordance with the Business Source License, use of this
+// software will be governed by the Apache License, Version 2.0, included in
+// the file licenses/APL2.txt.
+
+package base
+
+import "fmt"
+
+// RedactSprintf is a wrapper around fmt.Sprintf that redacts any sensitive data.
+func RedactSprintf(format string, args ...any) string {
+ redactedArgs := redact(args)
+ return fmt.Sprintf(format, redactedArgs...)
+}
diff --git a/db/change_cache.go b/db/change_cache.go
index 19995d5ae7..bbeecdcbee 100644
--- a/db/change_cache.go
+++ b/db/change_cache.go
@@ -576,7 +576,6 @@ func (c *changeCache) releaseUnusedSequence(ctx context.Context, sequence uint64
} else {
changedChannels.Add(unusedSeq)
}
- c.channelCache.AddUnusedSequence(change)
if c.notifyChange != nil && len(changedChannels) > 0 {
c.notifyChange(ctx, changedChannels)
}
@@ -599,7 +598,6 @@ func (c *changeCache) releaseUnusedSequenceRange(ctx context.Context, fromSequen
}
changedChannels := c.processEntry(ctx, change)
allChangedChannels = allChangedChannels.Update(changedChannels)
- c.channelCache.AddUnusedSequence(change)
if c.notifyChange != nil {
c.notifyChange(ctx, allChangedChannels)
}
@@ -609,9 +607,6 @@ func (c *changeCache) releaseUnusedSequenceRange(ctx context.Context, fromSequen
// push unused range to either pending or skipped lists based on current state of the change cache
allChangedChannels = c.processUnusedRange(ctx, fromSequence, toSequence, allChangedChannels, timeReceived)
- // update high seq cached
- c.channelCache.AddUnusedSequence(&LogEntry{Sequence: toSequence})
-
if c.notifyChange != nil {
c.notifyChange(ctx, allChangedChannels)
}
@@ -804,8 +799,9 @@ func (c *changeCache) _addToCache(ctx context.Context, change *LogEntry) []chann
}
delete(c.receivedSeqs, change.Sequence)
- // If unused sequence or principal, we're done after updating sequence
+ // If unused sequence, notify the cache and return
if change.DocID == "" {
+ c.channelCache.AddUnusedSequence(change)
return nil
}
diff --git a/db/change_cache_test.go b/db/change_cache_test.go
index 2e500eba5f..0a6b245c2d 100644
--- a/db/change_cache_test.go
+++ b/db/change_cache_test.go
@@ -2350,7 +2350,7 @@ func TestReleasedSequenceRangeHandlingEverythingPending(t *testing.T) {
assert.Equal(c, int64(1), dbContext.DbStats.CacheStats.PendingSeqLen.Value())
assert.Equal(c, uint64(2), testChangeCache.nextSequence)
dbContext.UpdateCalculatedStats(ctx)
- assert.Equal(c, int64(25), dbContext.DbStats.CacheStats.HighSeqCached.Value())
+ assert.Equal(c, int64(1), dbContext.DbStats.CacheStats.HighSeqCached.Value())
}, time.Second*10, time.Millisecond*100)
}
@@ -2456,7 +2456,7 @@ func TestReleasedSequenceRangeHandlingEverythingPendingLowPendingCapacity(t *tes
defer testChangeCache.Stop(ctx)
require.NoError(t, err)
- // process unused sequence range
+ // process unused sequence range, will be sent to pending. Triggers seq 1 being sent to skipped
testChangeCache.releaseUnusedSequenceRange(ctx, 2, 25, time.Now())
require.EventuallyWithT(t, func(c *assert.CollectT) {
@@ -2567,7 +2567,7 @@ func TestReleasedSequenceRangeHandlingSingleSequence(t *testing.T) {
assert.Equal(c, int64(1), dbContext.DbStats.CacheStats.PendingSeqLen.Value())
assert.Equal(c, uint64(1), testChangeCache.nextSequence)
dbContext.UpdateCalculatedStats(ctx)
- assert.Equal(c, int64(2), dbContext.DbStats.CacheStats.HighSeqCached.Value())
+ assert.Equal(c, int64(0), dbContext.DbStats.CacheStats.HighSeqCached.Value())
}, time.Second*10, time.Millisecond*100)
// process change that should overload pending and push sequence 1 to skipped
diff --git a/db/channel_cache.go b/db/channel_cache.go
index d4ab42371d..716a996a92 100644
--- a/db/channel_cache.go
+++ b/db/channel_cache.go
@@ -188,7 +188,11 @@ func (c *channelCacheImpl) AddPrincipal(change *LogEntry) {
// Add unused Sequence notifies the cache of an unused sequence update. Updates the cache's high sequence
func (c *channelCacheImpl) AddUnusedSequence(change *LogEntry) {
- c.updateHighCacheSequence(change.Sequence)
+ if change.EndSequence > 0 {
+ c.updateHighCacheSequence(change.EndSequence)
+ } else {
+ c.updateHighCacheSequence(change.Sequence)
+ }
}
// Adds an entry to the appropriate channels' caches, returning the affected channels. lateSequence
diff --git a/docs/api/components/schemas.yaml b/docs/api/components/schemas.yaml
index de68c4c73b..adf0396cd5 100644
--- a/docs/api/components/schemas.yaml
+++ b/docs/api/components/schemas.yaml
@@ -1894,6 +1894,33 @@ Database:
description: The name of the role for which audit logging is disabled.
type: string
title: Database-config
+Disabled-users-and-roles:
+ type: object
+ properties:
+ disabled_users:
+ description: List of users for which audit logging is disabled.
+ type: array
+ items:
+ type: object
+ properties:
+ domain:
+ description: The domain of the user for which audit logging is disabled. Either cbs or sgw.
+ type: string
+ name:
+ description: The name of the user for which audit logging is disabled.
+ type: string
+ disabled_roles:
+ description: List of roles for which audit logging is disabled. Either cbs or sgw.
+ type: array
+ items:
+ type: object
+ properties:
+ domain:
+ description: The domain of the role for which audit logging is disabled.
+ type: string
+ name:
+ description: The name of the role for which audit logging is disabled.
+ type: string
Database-audit:
title: Simple
description: A map of audit events and whether they are enabled or not.
@@ -1986,7 +2013,6 @@ Database-audit-verbose:
name:
description: The name of the role for which audit logging is disabled.
type: string
-
AuditEventVerbose:
title: audit-event-verbose
description: Detailed information about an audit event.
diff --git a/manifest/3.1.xml b/manifest/3.1.xml
index fedaa0f327..21559591f3 100644
--- a/manifest/3.1.xml
+++ b/manifest/3.1.xml
@@ -18,13 +18,13 @@ licenses/APL2.txt.
-
+
-
+
diff --git a/manifest/3.1/3.1.10.1.xml b/manifest/3.1/3.1.10.1.xml
new file mode 100644
index 0000000000..dba19c2c93
--- /dev/null
+++ b/manifest/3.1/3.1.10.1.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/manifest/product-config.json b/manifest/product-config.json
index 3dbe784773..97082f6095 100644
--- a/manifest/product-config.json
+++ b/manifest/product-config.json
@@ -450,8 +450,8 @@
"start_build": 1
},
"manifest/3.1.xml": {
- "release": "3.1.10.1",
- "release_name": "Couchbase Sync Gateway 3.1.10.1",
+ "release": "3.1.11",
+ "release_name": "Couchbase Sync Gateway 3.1.11",
"production": true,
"interval": 120,
"go_version": "1.22.5",
@@ -478,6 +478,16 @@
"trigger_blackduck": true,
"start_build": 5
},
+ "manifest/3.1/3.1.10.1.xml": {
+ "do-build": false,
+ "release": "3.1.10.1",
+ "release_name": "Couchbase Sync Gateway 3.1.10.1",
+ "production": true,
+ "interval": 1440,
+ "go_version": "1.22.5",
+ "trigger_blackduck": true,
+ "start_build": 3
+ },
"manifest/3.1/3.1.8.xml": {
"do-build": false,
"release": "3.1.8",
diff --git a/rest/config_manager.go b/rest/config_manager.go
index dbb8be15d4..b50bff05b4 100644
--- a/rest/config_manager.go
+++ b/rest/config_manager.go
@@ -519,9 +519,10 @@ func (b *bootstrapContext) waitForConfigDelete(ctx context.Context, bucketName,
timeout = b.configRetryTimeout
}
+ dbConfigName := PersistentConfigKey(ctx, groupID, dbName)
retryWorker := func() (shouldRetry bool, err error, value interface{}) {
config := &DatabaseConfig{}
- cas, getErr := b.Connection.GetMetadataDocument(ctx, bucketName, PersistentConfigKey(ctx, groupID, dbName), config)
+ cas, getErr := b.Connection.GetMetadataDocument(ctx, bucketName, dbConfigName, config)
// Success case - delete has been completed
if base.IsDocNotFoundError(getErr) {
return false, nil, nil
@@ -541,7 +542,7 @@ func (b *bootstrapContext) waitForConfigDelete(ctx context.Context, bucketName,
// Kick off the retry loop
err, retryResult := base.RetryLoop(
ctx,
- "Wait for config version match",
+ base.RedactSprintf("Wait for %q to be deleted in %q", base.MD(dbConfigName), base.MD(bucketName)),
retryWorker,
base.CreateDoublingSleeperDurationFunc(50, timeout),
)