MigrateAttachmentMetadata will move any attachment metadata defined in sync data to global sync xattr
(ctx context.Context, docID string, cas uint64, syncData *SyncData)
| 1083 | |
| 1084 | // MigrateAttachmentMetadata will move any attachment metadata defined in sync data to global sync xattr |
| 1085 | func (c *DatabaseCollectionWithUser) MigrateAttachmentMetadata(ctx context.Context, docID string, cas uint64, syncData *SyncData) error { |
| 1086 | xattrs, _, err := c.dataStore.GetXattrs(ctx, docID, []string{base.GlobalXattrName, base.VirtualXattrRevSeqNo}) |
| 1087 | if err != nil && !base.IsXattrNotFoundError(err) { |
| 1088 | return err |
| 1089 | } |
| 1090 | var globalData GlobalSyncData |
| 1091 | if xattrs[base.GlobalXattrName] != nil { |
| 1092 | // we have a global xattr to preserve |
| 1093 | err := base.JSONUnmarshal(xattrs[base.GlobalXattrName], &globalData) |
| 1094 | if err != nil { |
| 1095 | return base.RedactErrorf("Failed to Unmarshal global sync data when attempting to migrate sync data attachments to global xattr with id: %s. Error: %v", base.UD(docID), err) |
| 1096 | } |
| 1097 | } |
| 1098 | globalData.Attachments = mergeAttachments(syncData.AttachmentsPre4dot0, globalData.Attachments) |
| 1099 | syncData.AttachmentsPre4dot0 = nil // clear out the pre-4.0 attachments so we don't try to write them to the doc |
| 1100 | globalXattr, err := base.JSONMarshal(globalData) |
| 1101 | if err != nil { |
| 1102 | return base.RedactErrorf("Failed to Marshal global sync data when attempting to migrate sync data attachments to global xattr with id: %s. Error: %v", base.UD(docID), err) |
| 1103 | } |
| 1104 | rawSyncXattr, err := base.JSONMarshal(*syncData) |
| 1105 | if err != nil { |
| 1106 | return base.RedactErrorf("Failed to Marshal sync data when attempting to migrate sync data attachments to global xattr with id: %s. Error: %v", base.UD(docID), err) |
| 1107 | } |
| 1108 | revSeqNo, err := unmarshalRevSeqNo(xattrs[base.VirtualXattrRevSeqNo]) |
| 1109 | if err != nil { |
| 1110 | base.InfofCtx(ctx, base.KeyCRUD, "Could not determine revSeqNo found when attempting to migrate sync data attachments to global xattr for doc %q. Assuming 0. Error: %v", base.UD(docID), err) |
| 1111 | } |
| 1112 | |
| 1113 | metadataOnlyUpdate := &MetadataOnlyUpdate{ |
| 1114 | HexCAS: expandMacroCASValueString, // when non-empty, this is replaced with cas macro expansion |
| 1115 | PreviousHexCAS: syncData.Cas, |
| 1116 | PreviousRevSeqNo: revSeqNo, |
| 1117 | } |
| 1118 | rawMouXattr, err := base.JSONMarshal(metadataOnlyUpdate) |
| 1119 | if err != nil { |
| 1120 | return base.RedactErrorf("Failed to marshal _mou when attempting to migrate sync data attachments to global xattr with id: %s. Error: %v", base.UD(docID), err) |
| 1121 | } |
| 1122 | |
| 1123 | // build macro expansion for sync data. This will avoid the update to xattrs causing an extra import event (i.e. sync cas will be == to doc cas) |
| 1124 | opts := &sgbucket.MutateInOptions{} |
| 1125 | spec := append(macroExpandSpec(base.SyncXattrName), sgbucket.NewMacroExpansionSpec(XattrMouCasPath(), sgbucket.MacroCas)) |
| 1126 | opts.MacroExpansion = spec |
| 1127 | opts.PreserveExpiry = true // if doc has expiry, we should preserve this |
| 1128 | |
| 1129 | updatedXattr := map[string][]byte{ |
| 1130 | base.SyncXattrName: rawSyncXattr, |
| 1131 | base.GlobalXattrName: globalXattr, |
| 1132 | base.MouXattrName: rawMouXattr, |
| 1133 | } |
| 1134 | _, err = c.dataStore.UpdateXattrs(ctx, docID, 0, cas, updatedXattr, opts) |
| 1135 | return err |
| 1136 | } |
| 1137 | |
| 1138 | // Updates or creates a document. |
| 1139 | // The new body's BodyRev property must match the current revision's, if any. |