Beispiel #1
0
        public void ReleaseResource(IDocumentStore store, string resourceName, long index)
        {
            CompareExchangeResult <SharedResource> deleteResult
                = store.Operations.Send(new DeleteCompareExchangeValueOperation <SharedResource>(resourceName, index));

            // We have 2 options here:
            // deleteResult.Successful is true - we managed to release resource
            // deleteResult.Successful is false - someone else took the look due to timeout
        }
Beispiel #2
0
        public async Task Sample()
        {
            using (var store = new DocumentStore())
            {
                #region email
                string email = "*****@*****.**";

                User user = new User
                {
                    Email = email
                };

                using (IDocumentSession session = store.OpenSession())
                {
                    session.Store(user);
                    // At this point, the user document has an Id assigned

                    // Try to reserve a new user email
                    // Note: This operation takes place outside of the session transaction,
                    //       It is a cluster-wide reservation
                    CompareExchangeResult <string> cmpXchgResult
                        = store.Operations.Send(
                              new PutCompareExchangeValueOperation <string>("emails/" + email, user.Id, 0));

                    if (cmpXchgResult.Successful == false)
                    {
                        throw new Exception("Email is already in use");
                    }

                    // At this point we managed to reserve/save the user email -
                    // The document can be saved in SaveChanges
                    session.SaveChanges();
                }
                #endregion

                #region query_cmpxchg
                using (IDocumentSession session = store.OpenSession())
                {
                    var query = from u in session.Query <User>()
                                where u.Email == RavenQuery.CmpXchg <string>("emails/[email protected]")
                                select u;

                    var q = session.Advanced
                            .DocumentQuery <User>()
                            .WhereEquals("Email", CmpXchg.Value("emails/[email protected]"));
                }
                #endregion
            }
        }
        public IActionResult Run(RunParams runParams)
        {
            string cmpXchgKey   = runParams.CmpXchgKey ?? "*****@*****.**";
            string cmpXchgValue = runParams.CmpXchgValue ?? "employee/1-A";

            string result = null;

            #region Demo
            #region Step_1
            var putCmpXchgOperation =
                new PutCompareExchangeValueOperation <string>(cmpXchgKey, cmpXchgValue, 0);

            CompareExchangeResult <string> putCmpXchgResult =
                DocumentStoreHolder.Store.Operations.Send(putCmpXchgOperation);
            #endregion

            #region Step_2
            var success    = putCmpXchgResult.Successful;
            var putValue   = putCmpXchgResult.Value;
            var putVersion = putCmpXchgResult.Index;

            if (success == false)
            {
                result = "Key already exists";
            }
            #endregion

            #region Step_3
            var getCmpXchgOperation =
                new GetCompareExchangeValueOperation <string>(cmpXchgKey);

            CompareExchangeValue <string> getCmpXchgResult =
                DocumentStoreHolder.Store.Operations.Send(getCmpXchgOperation);
            #endregion

            #region Step_4
            var key                 = getCmpXchgResult.Key;
            var currentValue        = getCmpXchgResult.Value;
            var currentValueVersion = getCmpXchgResult.Index;
            var currentMetadata     = getCmpXchgResult.Metadata;
            #endregion
            #endregion

            result = result ?? $"Created a new Compare-Exchange Key: {key}, Value: {currentValue}, Value Version: {currentValueVersion}";
            return(Ok(result));
        }
Beispiel #4
0
        public async Task SubscriptionsWorksWithCompareExchange()
        {
            using (var store = GetDocumentStore())
            {
                string userId;
                string cmpxValueOriginal;
                using (var session = store.OpenSession())
                {
                    User user = new User
                    {
                        Name = "foobar"
                    };
                    session.Store(user);
                    userId = session.Advanced.GetDocumentId(user);
                    // Try to reserve a new user email
                    // Note: This operation takes place outside of the session transaction,
                    //       It is a cluster-wide reservation
                    cmpxValueOriginal = "His name is " + user.Name;
                    CompareExchangeResult <string> cmpXchgResult
                        = store.Operations.Send(
                              new PutCompareExchangeValueOperation <string>(user.Id, cmpxValueOriginal, 0));
                    session.SaveChanges();
                }
                var subsId = store.Subscriptions.Create <User>(new Raven.Client.Documents.Subscriptions.SubscriptionCreationOptions <User>()
                {
                    Projection = x => new
                    {
                        Foo = RavenQuery.CmpXchg <string>(userId),
                        x.AddressId
                    }
                });

                string cmpxValue  = string.Empty;
                var    subsWorker = store.Subscriptions.GetSubscriptionWorker(new Raven.Client.Documents.Subscriptions.SubscriptionWorkerOptions(subsId)
                {
                    CloseWhenNoDocsLeft = true
                });
                await Assert.ThrowsAsync <SubscriptionClosedException>(async() =>
                                                                       await subsWorker.Run(x =>
                {
                    cmpxValue = x.Items[0].RawResult["Foo"].ToString();
                }));

                Assert.Equal(cmpxValue, cmpxValueOriginal);
            }
        }
Beispiel #5
0
        public long LockResource(IDocumentStore store, string resourceName, TimeSpan duration)
        {
            while (true)
            {
                DateTime now = DateTime.UtcNow;

                SharedResource resource = new SharedResource
                {
                    ReservedUntil = now.Add(duration)
                };

                CompareExchangeResult <SharedResource> saveResult = store.Operations.Send(
                    new PutCompareExchangeValueOperation <SharedResource>(resourceName, resource, 0));

                if (saveResult.Successful)
                {
                    // resourceName wasn't present - we managed to reserve
                    return(saveResult.Index);
                }

                // At this point, Put operation failed - someone else owns the lock or lock time expired
                if (saveResult.Value.ReservedUntil < now)
                {
                    // Time expired - Update the existing key with the new value
                    CompareExchangeResult <SharedResource> takeLockWithTimeoutResult = store.Operations.Send(
                        new PutCompareExchangeValueOperation <SharedResource>(resourceName, resource, saveResult.Index));

                    if (takeLockWithTimeoutResult.Successful)
                    {
                        return(takeLockWithTimeoutResult.Index);
                    }
                }

                // Wait a little bit and retry
                Thread.Sleep(20);
            }
        }
Beispiel #6
0
        public async Task CreateFullAndIncrementalBackupWithCompareExchangeInTheMiddle()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenSession())
                {
                    session.Store(new User
                    {
                        Name = "Toli"
                    }, "users/1");
                    session.SaveChanges();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    Name = "full",
                    FullBackupFrequency = "* */6 * * *",
                    BackupType          = BackupType.Backup
                };

                var result = await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config));

                var documentDatabase = (await GetDocumentDatabaseInstanceFor(store));
                RunBackup(result.TaskId, documentDatabase, true, store);


                CompareExchangeResult <string> compareExchangeResult
                    = store.Operations.Send(
                          new PutCompareExchangeValueOperation <string>("users/1", "Mitzi", 0));

                config.IncrementalBackupFrequency = "* */2 * * *";
                config.TaskId = result.TaskId;
                result        = await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config));

                RunBackup(result.TaskId, documentDatabase, false, store);

                var backupDirectory = Directory.GetDirectories(backupPath).First();

                var databaseName = GetDatabaseName() + "restore";

                RestoreBackupConfiguration config2 = new RestoreBackupConfiguration()
                {
                    BackupLocation        = backupDirectory,
                    DatabaseName          = databaseName,
                    LastFileNameToRestore = Directory.GetFiles(backupDirectory).Last()
                };

                RestoreBackupOperation restoreOperation = new RestoreBackupOperation(config2);
                store.Maintenance.Server.Send(restoreOperation)
                .WaitForCompletion();

                using (var store2 = GetDocumentStore(new Options()
                {
                    CreateDatabase = false,
                    ModifyDatabaseName = s => databaseName
                }))
                {
                    using (var session = store2.OpenSession())
                    {
                        var doc = session.Load <User>("users/1");
                        Assert.NotNull(doc);
                    };
                    CompareExchangeValue <string> readResult =
                        store2.Operations.Send(new GetCompareExchangeValueOperation <string>("users/1"));

                    Assert.Equal("Mitzi", readResult.Value);
                };
            }
        }
Beispiel #7
0
        public CompareExchange()
        {
            using (var store = new DocumentStore())
            {
                {
                    #region get_1
                    CompareExchangeValue <long> readResult =
                        store.Operations.Send(new GetCompareExchangeValueOperation <long>("NextClientId"));

                    long value = readResult.Value;
                    #endregion
                }

                {
                    #region get_2
                    CompareExchangeValue <User> readResult =
                        store.Operations.Send(new GetCompareExchangeValueOperation <User>("AdminUser"));

                    User admin = readResult.Value;
                    #endregion
                }

                {
                    #region get_list_2
                    Dictionary <string, CompareExchangeValue <string> > compareExchangeValues
                        = store.Operations.Send(
                              new GetCompareExchangeValuesOperation <string>(new[] { "Key-1", "Key-2" }));
                    #endregion
                }

                {
                    #region get_list_3
                    // Get values for keys that have the common prefix 'users'
                    // Retrieve maximum 20 entries
                    Dictionary <string, CompareExchangeValue <User> > compareExchangeValues
                        = store.Operations.Send(new GetCompareExchangeValuesOperation <User>("users", 0, 20));
                    #endregion
                }

                {
                    #region put_1
                    CompareExchangeResult <string> compareExchangeResult
                        = store.Operations.Send(
                              new PutCompareExchangeValueOperation <string>("Emails/[email protected]", "users/123", 0));

                    bool successful = compareExchangeResult.Successful;
                    // If successfull is true: then Key '*****@*****.**' now has the value of "users/123"
                    #endregion
                }

                {
                    #region put_2
                    // Get existing value
                    CompareExchangeValue <User> readResult =
                        store.Operations.Send(
                            new GetCompareExchangeValueOperation <User>("AdminUser"));

                    readResult.Value.Age++;

                    // Update value
                    CompareExchangeResult <User> saveResult
                        = store.Operations.Send(
                              new PutCompareExchangeValueOperation <User>("AdminUser", readResult.Value, readResult.Index));

                    // The save result is successful only if 'index' wasn't changed between the read and write operations
                    bool saveResultSuccessful = saveResult.Successful;
                    #endregion
                }

                {
                    #region delete_1
                    // First, get existing value
                    CompareExchangeValue <User> readResult =
                        store.Operations.Send(
                            new GetCompareExchangeValueOperation <User>("AdminUser"));

                    // Delete the key - use the index received from the 'Get' operation
                    CompareExchangeResult <User> deleteResult
                        = store.Operations.Send(
                              new DeleteCompareExchangeValueOperation <User>("AdminUser", readResult.Index));

                    // The delete result is successful only if the index has not changed between the read and delete operations
                    bool deleteResultSuccessful = deleteResult.Successful;
                    #endregion
                }
            }
        }
Beispiel #8
0
        public CompareExchange()
        {
            using (var store = new DocumentStore())
            {
                {
                    #region get_1
                    CompareExchangeValue <long> readResult =
                        store.Operations.Send(new GetCompareExchangeValueOperation <long>("NextClientId"));

                    long value = readResult.Value;
                    #endregion
                }

                {
                    #region get_2
                    CompareExchangeValue <User> readResult =
                        store.Operations.Send(new GetCompareExchangeValueOperation <User>("AdminUser"));

                    User admin = readResult.Value;
                    #endregion
                }

                /*{ This overload is no longer available
                 #region get_list_2
                 *  Dictionary<string, CompareExchangeValue<string>> compareExchangeValues
                 *      = store.Operations.Send(
                 *          new GetCompareExchangeValuesOperation<string>(new[] { "Key-1", "Key-2" }));
                 #endregion
                 * }*/

                {
                    #region get_list_3
                    // Get values for keys that have the common prefix 'users'
                    // Retrieve maximum 20 entries
                    Dictionary <string, CompareExchangeValue <User> > compareExchangeValues
                        = store.Operations.Send(new GetCompareExchangeValuesOperation <User>("users", 0, 20));
                    #endregion
                }

                {
                    #region put_1
                    CompareExchangeResult <string> compareExchangeResult
                        = store.Operations.Send(
                              new PutCompareExchangeValueOperation <string>("Emails/[email protected]", "users/123", 0));

                    bool successful = compareExchangeResult.Successful;
                    // If successfull is true: then Key '*****@*****.**' now has the value of "users/123"
                    #endregion
                }

                {
                    #region put_2
                    // Get existing value
                    CompareExchangeValue <User> readResult =
                        store.Operations.Send(
                            new GetCompareExchangeValueOperation <User>("AdminUser"));

                    readResult.Value.Age++;

                    // Update value
                    CompareExchangeResult <User> saveResult
                        = store.Operations.Send(
                              new PutCompareExchangeValueOperation <User>("AdminUser", readResult.Value, readResult.Index));

                    // The save result is successful only if 'index' wasn't changed between the read and write operations
                    bool saveResultSuccessful = saveResult.Successful;
                    #endregion
                }

                {
                    #region delete_1
                    // First, get existing value
                    CompareExchangeValue <User> readResult =
                        store.Operations.Send(
                            new GetCompareExchangeValueOperation <User>("AdminUser"));

                    // Delete the key - use the index received from the 'Get' operation
                    CompareExchangeResult <User> deleteResult
                        = store.Operations.Send(
                              new DeleteCompareExchangeValueOperation <User>("AdminUser", readResult.Index));

                    // The delete result is successful only if the index has not changed between the read and delete operations
                    bool deleteResultSuccessful = deleteResult.Successful;
                    #endregion
                }

                #region expiration_0
                using (IAsyncDocumentSession session = store.OpenAsyncSession())
                {
                    // Set a time exactly one week from now
                    DateTime expirationTime = DateTime.UtcNow.AddDays(7);

                    // Create a new compare exchange value
                    var cmpxchgValue = session.Advanced.ClusterTransaction.CreateCompareExchangeValue("key", "value");

                    // Edit Metadata
                    cmpxchgValue.Metadata[Constants.Documents.Metadata.Expires] = expirationTime;

                    // Send to server
                    session.SaveChangesAsync();
                }
                #endregion

                using (IAsyncDocumentSession session = store.OpenAsyncSession())
                {
                    #region expiration_1
                    // Retrieve an existing key
                    CompareExchangeValue <string> cmpxchgValue = store.Operations.Send(
                        new GetCompareExchangeValueOperation <string>("key"));

                    // Set time
                    DateTime expirationTime = DateTime.UtcNow.AddDays(7);

                    // Edit Metadata
                    cmpxchgValue.Metadata[Constants.Documents.Metadata.Expires] = expirationTime;

                    // Update value. Index must match the index on the server side,
                    // or the operation will fail.
                    CompareExchangeResult <string> result = store.Operations.Send(
                        new PutCompareExchangeValueOperation <string>(
                            cmpxchgValue.Key,
                            cmpxchgValue.Value,
                            cmpxchgValue.Index));
                    #endregion
                }

                #region metadata_0
                using (IAsyncDocumentSession session = store.OpenAsyncSession(
                           new SessionOptions {
                    TransactionMode = TransactionMode.ClusterWide
                }))
                {
                    // Create a new compare exchange value
                    var cmpxchgValue = session.Advanced.ClusterTransaction.CreateCompareExchangeValue("key", "value");

                    // Add a field to the metadata
                    // with a value of type string
                    cmpxchgValue.Metadata["Field name"] = "some value";

                    // Retrieve metadata as a dictionary
                    IDictionary <string, object> cmpxchgMetadata = cmpxchgValue.Metadata;
                }
                #endregion
            }
        }
Beispiel #9
0
        public async Task CreateFullAndIncrementalBackupWithCompareExchangeInTheMiddle()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenSession())
                {
                    session.Store(new User
                    {
                        Name = "Toli"
                    }, "users/1");
                    session.SaveChanges();
                }

                var config       = Backup.CreateBackupConfiguration(backupPath);
                var backupTaskId = await Backup.UpdateConfigAndRunBackupAsync(Server, config, store);

                CompareExchangeResult <string> compareExchangeResult
                    = store.Operations.Send(
                          new PutCompareExchangeValueOperation <string>("users/1", "Mitzi", 0));

                WaitForValue(() => compareExchangeResult.Successful, true);

                await Backup.RunBackupAsync(Server, backupTaskId, store, isFullBackup : false);

                compareExchangeResult
                    = store.Operations.Send(
                          new PutCompareExchangeValueOperation <string>("users/1", "Mitzi2", compareExchangeResult.Index));

                WaitForValue(() => compareExchangeResult.Successful, true);

                await Backup.RunBackupAsync(Server, backupTaskId, store, isFullBackup : false);

                var backupDirectory = Directory.GetDirectories(backupPath).First();

                var databaseName = GetDatabaseName() + "restore";

                var files = Directory.GetFiles(backupDirectory)
                            .Where(BackupUtils.IsBackupFile)
                            .OrderBackups()
                            .ToArray();

                RestoreBackupConfiguration config2 = new RestoreBackupConfiguration()
                {
                    BackupLocation        = backupDirectory,
                    DatabaseName          = databaseName,
                    LastFileNameToRestore = files.Last()
                };

                RestoreBackupOperation restoreOperation = new RestoreBackupOperation(config2);
                store.Maintenance.Server.Send(restoreOperation)
                .WaitForCompletion();

                using (var store2 = GetDocumentStore(new Options()
                {
                    CreateDatabase = false,
                    ModifyDatabaseName = s => databaseName
                }))
                {
                    using (var session = store2.OpenSession())
                    {
                        var doc = session.Load <User>("users/1");
                        Assert.NotNull(doc);
                    };
                    CompareExchangeValue <string> readResult =
                        store2.Operations.Send(new GetCompareExchangeValueOperation <string>("users/1"));

                    Assert.Equal("Mitzi2", readResult.Value);
                };
            }
        }