public ActionResult Create(AirlineModel model) { EnsureIncrementInitialized(); // Begin change tracking _db.BeginChangeTracking(); if (!ModelState.IsValid) { return(View(model)); } var airline = new Airline() { Id = (int)_bucket.Increment(IncrementDocument).Value, Name = model.Name, Callsign = model.Callsign }; // Add the document and save the changes _db.Save(airline); _db.SubmitChanges(); // Collect mutation state for queries on the next page view TempData["AirlineMutationState"] = _db.MutationState; return(RedirectToAction("Index")); }
private string AppendKeyIncrement(string key) { const string counterKey = "customer::counter"; IOperationResult <ulong> result = _bucket.Increment(counterKey, 1, 1); return(string.Format(key + "-{0}", result.Value)); }
static void Increment(IBucket bucket, string key) { var result = bucket.Increment(key); if (result.Success) { Console.WriteLine(result.Value); } }
public void When_Integer_Is_Incremented_By_Default_Value_Increases_By_One() { const string key = "When_Integer_Is_Incremented_Value_Increases_By_One"; _bucket.Remove(key); var result = _bucket.Increment(key); Assert.IsTrue(result.Success); Assert.AreEqual(1, result.Value); result = _bucket.Increment(key); Assert.IsTrue(result.Success); Assert.AreEqual(2, result.Value); }
public void SetUp() { _cluster = new Cluster(new ClientConfiguration { Servers = new List <Uri> { new Uri("http://10.142.180.102:8091/") } }); _cluster.Authenticate("Administrator", "password"); _bucket = _cluster.OpenBucket(); if (_bucket.Exists("a")) { var a = _bucket.Remove("a"); Assert.IsTrue(a.Success); } if (_bucket.Exists("b")) { var b = _bucket.Remove("b"); Assert.IsTrue(b.Success); } if (_bucket.Exists("c")) { var c = _bucket.Remove("c"); Assert.IsTrue(c.Success); } if (!_bucket.Exists("counter")) { var counter = _bucket.Increment("counter"); Assert.IsTrue(counter.Success); } var insertC = _bucket.Insert("c", new { }); Assert.AreEqual(ResponseStatus.Success, insertC.Status); }
public void PrepareTest() { var a = _bucket.Get <dynamic>("a"); var b = _bucket.Get <dynamic>("b"); var c = _bucket.Exists("c"); Assert.AreEqual(ResponseStatus.KeyNotFound, a.Status); Assert.AreEqual(ResponseStatus.KeyNotFound, b.Status); Assert.IsTrue(c); a = _bucket.Insert("a", new { }); Assert.IsTrue(a.Success); var increment = _bucket.Increment("counter"); Assert.IsTrue(increment.Success); var aMeta = _bucket.MutateIn <dynamic>("a"). Insert("tx", new { ts = increment.Value, md = new[] { b.Id }, value = new { name = "jeff" } }, SubdocPathFlags.Xattr); var execute = aMeta.Execute(); Assert.IsTrue(execute.Success); a = _bucket.Get <dynamic>("a"); Assert.AreEqual("", a.Value); b = _bucket.Insert("b", new { }); Assert.IsTrue(b.Success); var bMeta = _bucket.MutateIn <dynamic>("b"). Insert("tx", new { ts = increment.Value, md = new[] { a.Id }, value = new { name = "mike" } }, SubdocPathFlags.Xattr); execute = bMeta.Execute(); Assert.IsTrue(execute.Success); b = _bucket.Get <dynamic>("b"); Assert.AreEqual("", b.Value); dynamic aTx = _bucket.LookupIn <dynamic>("a").Get("tx", SubdocPathFlags.Xattr).Execute().Content("tx"); dynamic bTx = _bucket.LookupIn <dynamic>("b").Get("tx", SubdocPathFlags.Xattr).Execute().Content("tx"); //ts Assert.AreEqual(increment.Value, aTx.ts.Value); Assert.AreEqual(increment.Value, bTx.ts.Value); //md Assert.AreEqual(a.Id, bTx.md[0].Value); Assert.AreEqual(b.Id, aTx.md[0].Value); //value Assert.AreEqual("jeff", aTx.value.name.Value); Assert.AreEqual("mike", bTx.value.name.Value); }
public void Perform(IOperationResult <Barn> source, IOperationResult <Barn> destination, int amountToTransfer) { // this is how you create incremental document keys in Couchbase // you could use GUID or some other way to generate keys, it's not critical which you use var transactionDocumentNumber = _bucket.Increment("transaction::counter"); var transactionDocumentKey = $"transaction::{transactionDocumentNumber.Value}"; // create transation document // this is the record of a transaction, contains details of the transaction // used to keep track of transaction, and can also help debug/diagnose // tag::createtransactiondocument[] var transaction = _bucket.Upsert(new Document <TransactionRecord> { Id = transactionDocumentKey, Content = new TransactionRecord { SourceId = source.Id, Source = source.Value, DestinationId = destination.Id, Destination = destination.Value, Amount = amountToTransfer, State = TransactionStates.Initial } }); // end::createtransactiondocument[] Console.WriteLine($"Created transaction record: {transaction.Id}"); Console.ReadLine(); try { // #1 switch the transaction to pending - the transaction is now in progress // and a rollback attempt will see "pending" status and know how to proceed // tag::pending[] var transCas = UpdateWithCas <TransactionRecord>(transaction.Id, x => x.State = TransactionStates.Pending, transaction.Document.Cas); // end::pending[] Console.WriteLine($"Switch transaction to {TransactionStates.Pending}"); Console.ReadLine(); // #2 apply the change to both documents - this method is only able to transfer an amount of chickens // but it could be made more generic for your use case(s) // #2a update source MINUS amount // tag::updatesource[] var sourceCas = UpdateWithCas <Barn>(source.Id, x => { x.Chickens -= amountToTransfer; x.Transaction = transaction.Id; }); // end::updatesource[] Console.WriteLine($"Subtract {amountToTransfer} from {source.Value.Name} (and mark transaction {transaction.Id})"); Console.ReadLine(); // simulate an error that occurs smack in the middle of the transaction // triggering a rollback in the "catch" if (_simulateErrorDuringPending) { throw new Exception("Something went wrong while transaction was pending."); } // #2b update destination PLUS amount // tag::updatedestination[] var destCas = UpdateWithCas <Barn>(destination.Id, x => { x.Chickens += amountToTransfer; x.Transaction = transaction.Id; }); // end::updatedestination[] Console.WriteLine($"Add {amountToTransfer} to {destination.Value.Name} (and mark transaction {transaction.Id})"); Console.ReadLine(); // #3 switch transaction to committed // the transaction is now complete, and needs to be cleaned up // tag::committed[] transCas = UpdateWithCas <TransactionRecord>(transaction.Id, x => x.State = TransactionStates.Committed, transCas); // end::committed[] Console.WriteLine($"Switch transaction to {TransactionStates.Committed}"); Console.ReadLine(); // simulate an error during the committed/cleanup phase // triggering a rollback in the "catch" if (_simulateErrorsAfterCommitted) { throw new Exception("Something went wrong after transaction was committed."); } // #4 remove transactions from document // each document was marked as being part of a transaction // that needs to be cleaned up // tag::removetransactionmarkers[] UpdateWithCas <Barn>(source.Id, x => { x.Transaction = null; }, sourceCas); UpdateWithCas <Barn>(destination.Id, x => { x.Transaction = null; }, destCas); // end::removetransactionmarkers[] Console.WriteLine("Remove transactions from barns."); Console.ReadLine(); // #5 switch transaction to done // cleanup in complete, so switch transaction to 'done' // transactions in 'done' status could hypothetically be deleted on a regular basis // but you may want to keep them around for a while just in case // tag::done[] UpdateWithCas <TransactionRecord>(transaction.Id, x => x.State = TransactionStates.Done, transCas); // end::done[] Console.WriteLine($"Switch transaction to {TransactionStates.Done}"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine($"ROLLING BACK: {ex.Message}"); Rollback(source, destination, amountToTransfer, transaction, ex); throw; } }
/// <summary> /// /// </summary> /// <param name="key"></param> /// <param name="defaultValue"></param> /// <param name="delta"></param> /// <returns></returns> public ulong Increment(string key, ulong defaultValue, ulong delta) { return(_bucket.Increment(key, delta, defaultValue).Value); }