public async Task Can_perform_mutate_in_with_array() { var collection = await _fixture.GetDefaultCollection().ConfigureAwait(false); await collection.UpsertAsync(DocumentKey, new { foo = "bar", bar = "foo" }).ConfigureAwait(false); var result = await collection.MutateInAsync(DocumentKey, new[] { MutateInSpec.Upsert("name", "mike"), MutateInSpec.Replace("bar", "bar") }).ConfigureAwait(false); using var getResult = await collection.GetAsync(DocumentKey, options => options.Transcoder(new LegacyTranscoder())).ConfigureAwait(false); var content = getResult.ContentAs <string>(); var expected = new { foo = "bar", bar = "bar", name = "mike" }; Assert.Equal(JsonConvert.SerializeObject(expected), content); }
public async Task Can_perform_mutate_in_with_array() { var collection = await _fixture.GetDefaultCollection(); await collection.Upsert(DocumentKey, new { foo = "bar", bar = "foo" }); await collection.MutateIn(DocumentKey, new[] { MutateInSpec.Upsert("name", "mike"), MutateInSpec.Replace("bar", "bar") }); var getResult = await collection.Get(DocumentKey); var content = getResult.ContentAs <string>(); var expected = new { foo = "bar", bar = "bar", name = "mike" }; Assert.Equal(JsonConvert.SerializeObject(expected), content); }
public async Task <(ulong updatedCas, MutationToken mutationToken)> MutateStagedRemove(TransactionGetResult doc, IAtrRepository atr) { // For ExtAllKvCombinations, the Java implementation was updated to write "txn" as one JSON blob instead of multiple MutateInSpecs. // Remove is the one where it had to be updated, given that we need to remove the staged data only if it exists. var txn = new TransactionXattrs() { Operation = new StagedOperation() { Type = "remove" }, Id = new CompositeId() { Transactionid = _overallContext.TransactionId, AttemptId = _attemptId }, AtrRef = new AtrRef() { Id = atr.AtrId, ScopeName = atr.ScopeName, BucketName = atr.BucketName, CollectionName = atr.CollectionName }, RestoreMetadata = doc.DocumentMetadata }; var txnAsJObject = Newtonsoft.Json.Linq.JObject.FromObject(txn, _metadataSerializer); var specs = new MutateInSpec[] { MutateInSpec.Upsert(TransactionFields.TransactionInterfacePrefixOnly, txnAsJObject, isXattr: true), MutateInSpec.Upsert(TransactionFields.Crc32, MutationMacro.ValueCRC32c, createPath: true, isXattr: true), }; var opts = GetMutateInOptions(StoreSemantics.Replace).Cas(doc.Cas).CreateAsDeleted(true); var updatedDoc = await doc.Collection.MutateInAsync(doc.Id, specs, opts).CAF(); return(updatedDoc.Cas, updatedDoc.MutationToken); }
public async Task UpdateClientRecord(string clientUuid, TimeSpan cleanupWindow, int numAtrs, IReadOnlyList <string> expiredClientIds) { var prefix = ClientRecordEntry.PathForEntry(clientUuid); var opts = new MutateInOptions().Timeout(_keyValueTimeout).Serializer(DefaultSerializer); var specs = new List <MutateInSpec> { MutateInSpec.Upsert(ClientRecordEntry.PathForHeartbeat(clientUuid), MutationMacro.Cas, createPath: true), MutateInSpec.Upsert(ClientRecordEntry.PathForExpires(clientUuid), (int)cleanupWindow.TotalMilliseconds + ExpiresSafetyMarginMillis, isXattr: true), MutateInSpec.Upsert(ClientRecordEntry.PathForNumAtrs(clientUuid), numAtrs, isXattr: true), MutateInSpec.SetDoc(new byte?[] { null }), // ExtBinaryMetadata }; var remainingSpecLimit = 16 - specs.Count; foreach (var clientId in expiredClientIds.Take(remainingSpecLimit)) { var spec = MutateInSpec.Remove($"{ClientRecordsIndex.FIELD_CLIENTS_FULL}.{clientId}", isXattr: true); specs.Add(spec); } try { var mutateInReuslt = await Collection.MutateInAsync(ClientRecordsIndex.CLIENT_RECORD_DOC_ID, specs, opts).CAF(); } catch (Core.Exceptions.KeyValue.XattrException ex) { throw; } }
private List <MutateInSpec> CreateMutationSpecs(IAtrRepository atr, string opType, object content, DocumentMetadata?dm = null) { object userSerializedContent = content; if (!(_userDataSerializer is Core.IO.Serializers.DefaultSerializer)) { byte[] bytes = _userDataSerializer.Serialize(content); userSerializedContent = DefaultSerializer.Deserialize <object>(bytes) !; } var specs = new List <MutateInSpec> { MutateInSpec.Upsert(TransactionFields.TransactionId, _overallContext.TransactionId, createPath: true, isXattr: true), MutateInSpec.Upsert(TransactionFields.AttemptId, _attemptId, createPath: true, isXattr: true), MutateInSpec.Upsert(TransactionFields.AtrId, atr.AtrId, createPath: true, isXattr: true), MutateInSpec.Upsert(TransactionFields.AtrScopeName, atr.ScopeName, createPath: true, isXattr: true), MutateInSpec.Upsert(TransactionFields.AtrBucketName, atr.BucketName, createPath: true, isXattr: true), MutateInSpec.Upsert(TransactionFields.AtrCollName, atr.CollectionName, createPath: true, isXattr: true), MutateInSpec.Upsert(TransactionFields.Type, opType, createPath: true, isXattr: true), MutateInSpec.Upsert(TransactionFields.Crc32, MutationMacro.ValueCRC32c, createPath: true, isXattr: true), }; switch (opType) { case "remove": specs.Add(MutateInSpec.Upsert(TransactionFields.StagedData, new { }, isXattr: true)); specs.Add(MutateInSpec.Remove(TransactionFields.StagedData, isXattr: true)); break; case "replace": case "insert": specs.Add(MutateInSpec.Upsert(TransactionFields.StagedData, userSerializedContent, createPath: true, isXattr: true)); break; } if (dm != null) { if (dm.Cas != null) { specs.Add(MutateInSpec.Upsert(TransactionFields.PreTxnCas, dm.Cas, createPath: true, isXattr: true)); } if (dm.RevId != null) { specs.Add(MutateInSpec.Upsert(TransactionFields.PreTxnRevid, dm.RevId, createPath: true, isXattr: true)); } if (dm.ExpTime != null) { specs.Add(MutateInSpec.Upsert(TransactionFields.PreTxnExptime, dm.ExpTime, createPath: true, isXattr: true)); } } return(specs); }
public async Task ClearTransactionMetadata(ICouchbaseCollection collection, string docId, ulong cas, bool isDeleted) { var opts = GetMutateInOptions(StoreSemantics.Replace).Cas(cas); if (isDeleted) { opts.AccessDeleted(true); } var specs = new MutateInSpec[] { MutateInSpec.Upsert(TransactionFields.TransactionInterfacePrefixOnly, (string?)null, isXattr: true), MutateInSpec.Remove(TransactionFields.TransactionInterfacePrefixOnly, isXattr: true) }; _ = await collection.MutateInAsync(docId, specs, opts).CAF(); }
public async Task MutateAtrAborted(IEnumerable <StagedMutation> stagedMutations) { using var logScope = _logger.BeginMethodScope(); (var inserts, var replaces, var removes) = SplitMutationsForStaging(stagedMutations); var specs = new MutateInSpec[] { MutateInSpec.Upsert(_prefixedAtrFieldStatus, AttemptStates.ABORTED.ToString(), isXattr: true), MutateInSpec.Upsert(_prefixedAtrFieldTimestampRollbackStart, MutationMacro.Cas, isXattr: true), MutateInSpec.Upsert(_prefixedAtrFieldDocsInserted, inserts, isXattr: true), MutateInSpec.Upsert(_prefixedAtrFieldDocsReplaced, replaces, isXattr: true), MutateInSpec.Upsert(_prefixedAtrFieldDocsRemoved, removes, isXattr: true), }; var mutateResult = await Collection.MutateInAsync(AtrId, specs, GetMutateOpts(StoreSemantics.Replace)).CAF(); _logger.LogDebug("Updated to ABORTED ATR {atr}/{atrRoot} (cas = {cas})", AtrId, _atrRoot, mutateResult.Cas); }