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);
        }
Esempio n. 2
0
        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;
            }
        }
Esempio n. 5
0
        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);
        }