ResyncDocument will re-run the sync function on the document and write an updated version to the bucket. If the sync function doesn't change any channels or access grants, no write will be performed.
(ctx context.Context, docid, key string, regenerateSequences bool, unusedSequences []uint64)
| 1829 | // ResyncDocument will re-run the sync function on the document and write an updated version to the bucket. If |
| 1830 | // the sync function doesn't change any channels or access grants, no write will be performed. |
| 1831 | func (db *DatabaseCollectionWithUser) ResyncDocument(ctx context.Context, docid, key string, regenerateSequences bool, unusedSequences []uint64) (updatedHighSeq uint64, updatedUnusedSequences []uint64, err error) { |
| 1832 | var updatedDoc *Document |
| 1833 | var shouldUpdate bool |
| 1834 | var updatedExpiry *uint32 |
| 1835 | if db.UseXattrs() { |
| 1836 | writeUpdateFunc := func(currentValue []byte, currentXattrs map[string][]byte, cas uint64) (sgbucket.UpdatedDoc, error) { |
| 1837 | // There's no scenario where a doc should from non-deleted to deleted during UpdateAllDocChannels processing, |
| 1838 | // so deleteDoc is always returned as false. |
| 1839 | if currentValue == nil || len(currentValue) == 0 { |
| 1840 | return sgbucket.UpdatedDoc{}, base.ErrUpdateCancel |
| 1841 | } |
| 1842 | doc, err := db.unmarshalDocumentWithXattrs(ctx, docid, currentValue, currentXattrs, cas, DocUnmarshalAll) |
| 1843 | if err != nil { |
| 1844 | return sgbucket.UpdatedDoc{}, err |
| 1845 | } |
| 1846 | updatedDoc, shouldUpdate, updatedExpiry, updatedHighSeq, unusedSequences, err = db.getResyncedDocument(ctx, doc, regenerateSequences, unusedSequences) |
| 1847 | if err != nil { |
| 1848 | return sgbucket.UpdatedDoc{}, err |
| 1849 | } |
| 1850 | if !shouldUpdate { |
| 1851 | return sgbucket.UpdatedDoc{}, base.ErrUpdateCancel |
| 1852 | } |
| 1853 | base.TracefCtx(ctx, base.KeyAccess, "Saving updated channels and access grants of %q", base.UD(docid)) |
| 1854 | if updatedExpiry != nil { |
| 1855 | updatedDoc.UpdateExpiry(*updatedExpiry) |
| 1856 | } |
| 1857 | doc.SetCrc32cUserXattrHash() |
| 1858 | |
| 1859 | // Update MetadataOnlyUpdate based on previous Cas, MetadataOnlyUpdate |
| 1860 | if db.useMou() { |
| 1861 | doc.MetadataOnlyUpdate = computeMetadataOnlyUpdate(doc.Cas, doc.RevSeqNo, doc.MetadataOnlyUpdate) |
| 1862 | } |
| 1863 | |
| 1864 | _, rawSyncXattr, _, rawMouXattr, rawGlobalXattr, err := updatedDoc.MarshalWithXattrs() |
| 1865 | updatedDoc := sgbucket.UpdatedDoc{ |
| 1866 | Doc: nil, // Resync does not require document body update |
| 1867 | Xattrs: map[string][]byte{ |
| 1868 | base.SyncXattrName: rawSyncXattr, |
| 1869 | }, |
| 1870 | Expiry: updatedExpiry, |
| 1871 | } |
| 1872 | if db.useMou() { |
| 1873 | updatedDoc.Xattrs[base.MouXattrName] = rawMouXattr |
| 1874 | if doc.MetadataOnlyUpdate.HexCAS == expandMacroCASValueString { |
| 1875 | updatedDoc.Spec = append(updatedDoc.Spec, sgbucket.NewMacroExpansionSpec(XattrMouCasPath(), sgbucket.MacroCas)) |
| 1876 | } |
| 1877 | } |
| 1878 | if rawGlobalXattr != nil { |
| 1879 | updatedDoc.Xattrs[base.GlobalXattrName] = rawGlobalXattr |
| 1880 | } |
| 1881 | return updatedDoc, err |
| 1882 | } |
| 1883 | opts := &sgbucket.MutateInOptions{ |
| 1884 | MacroExpansion: macroExpandSpec(base.SyncXattrName), |
| 1885 | } |
| 1886 | _, err = db.dataStore.WriteUpdateWithXattrs(ctx, key, db.syncGlobalSyncMouRevSeqNoAndUserXattrKeys(), 0, nil, opts, writeUpdateFunc) |
| 1887 | } else { |
| 1888 | _, err = db.dataStore.Update(key, 0, func(currentValue []byte) ([]byte, *uint32, bool, error) { |