From 97e6e104b5eef4d36499754a28d595ff6a5dc372 Mon Sep 17 00:00:00 2001 From: Ben Brooks Date: Thu, 2 Nov 2023 13:27:35 +0000 Subject: [PATCH] Move currentRevChannels logic down into SyncData type --- db/document.go | 48 ++++++++++++++++++++++++++++----------- db/revision_cache_test.go | 8 ++++++- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/db/document.go b/db/document.go index 161ff851e4..89b626d320 100644 --- a/db/document.go +++ b/db/document.go @@ -94,6 +94,41 @@ type SyncData struct { addedRevisionBodies []string // revIDs of non-winning revision bodies that have been added (and so require persistence) removedRevisionBodyKeys map[string]string // keys of non-winning revisions that have been removed (and so may require deletion), indexed by revID + + currentRevChannels base.Set // A base.Set of the current revision's channels (determined by SyncData.Channels at UnmarshalJSON time) +} + +func (sd *SyncData) UnmarshalJSON(b []byte) error { + + // type alias avoids UnmarshalJSON stack overflow (forces fallback to standard JSON unmarshal instead of this one) + type stdSyncData SyncData + var tmp stdSyncData + + err := base.JSONUnmarshal(b, &tmp) + if err != nil { + return err + } + + *sd = SyncData(tmp) + + // determine current revision's channels and store in-memory (avoids Channels iteration at access-check time) + sd.currentRevChannels = sd.getCurrentChannels() + + return nil +} + +// determine set of current channels based on removal entries. +func (sd *SyncData) getCurrentChannels() base.Set { + if len(sd.Channels) > 0 { + ch := base.SetOf() + for channelName, channelRemoval := range sd.Channels { + if channelRemoval == nil || channelRemoval.Seq == 0 { + ch.Add(channelName) + } + } + return ch + } + return nil } func (sd *SyncData) HashRedact(salt string) SyncData { @@ -180,8 +215,6 @@ type Document struct { RevID string DocAttachments AttachmentsMeta inlineSyncData bool - - currentRevChannels base.Set // A base.Set of the current revision's channels (determined by SyncData.Channels at UnmarshalJSON time) } type historyOnlySyncData struct { @@ -1075,17 +1108,6 @@ func (doc *Document) UnmarshalJSON(data []byte) error { doc.SyncData = *syncData.SyncData } - // determine current revision's channels and store in-memory (avoids doc.Channels iteration at access-check time) - if len(doc.Channels) > 0 { - ch := base.SetOf() - for channelName, channelRemoval := range doc.Channels { - if channelRemoval == nil || channelRemoval.Seq == 0 { - ch.Add(channelName) - } - } - doc.currentRevChannels = ch - } - // Unmarshal the rest of the doc body as map[string]interface{} if err := doc._body.Unmarshal(data); err != nil { return pkgerrors.WithStack(base.RedactErrorf("Failed to UnmarshalJSON() doc with id: %s. Error: %v", base.UD(doc.ID), err)) diff --git a/db/revision_cache_test.go b/db/revision_cache_test.go index 3bae02b261..9a6d38d56c 100644 --- a/db/revision_cache_test.go +++ b/db/revision_cache_test.go @@ -19,6 +19,7 @@ import ( "testing" "github.com/couchbase/sync_gateway/base" + "github.com/couchbase/sync_gateway/channels" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -47,9 +48,14 @@ func (t *testBackingStore) GetDocument(ctx context.Context, docid string, unmars doc.CurrentRev = "1-abc" doc.History = RevTree{ doc.CurrentRev: { - Channels: base.SetOf("*"), + ID: doc.CurrentRev, }, } + doc.Channels = channels.ChannelMap{ + "*": &channels.ChannelRemoval{RevID: doc.CurrentRev}, + } + // currentRevChannels usually populated on JSON unmarshal + doc.currentRevChannels = doc.getCurrentRevChannels() return doc, nil }