Summary: This page covers the Change API, its usage and behavior.
OverviewThe ISpaceProxy.Change and the ChangeSet allows updating existing objects in space, by specifying only the required change instead of passing the entire updated object. Thus reducing required network traffic between the client and the space, and the network traffic generated from replicating the changes between the space instances (e.g between the primary space instance and its backup). Moreover, using this API also can prevent the need of reading the existing object prior to the change operation because the change operation can specify how to change the existing property without knowing its current value. For instance, implementing atomic counters can be done by increasing a counter property of an integer property by some delta. Another example would be to add a value to a collection and so on. Basic Usage ExampleThe following example demonstrates how to increase the property 'count' in a an object of type 'WordCount' with id 'the' by one. ISpaceProxy space = // ... obtain a space reference String id = "myID"; IdQuery<WordCount> idQuery = new IdQuery<WordCount>(id, routing); space.Change(idQuery, new ChangeSet().Increment("Count", 1)); The Query TemplateThe change operation may receive any query template for matching a single or multiple objects that needs to be changed by the operation. The Change SetThe change operation requires a ChangeSet which described the changes that needs to be done once locating the object specified by the query template. [SpaceClass] public class Account { ... [SpaceId] Guid Id {get; set;} Balance Balance {get; set;} } public class Balance { ... public double Euro {get; set;} public double UsDollar {get; set;} } ISpaceProxy space = // ... obtain a space reference Guid id = ...; IdQuery<Account> idQuery = new IdQuery<Account>(id, routing); space.Change(idQuery, new ChangeSet().Increment("Balance.Euro", 5.2D)); Change Path SpecificationEach operation in the change set acts on a specified string path. This path points to the property that needs to be changed and it has the following semantic:
The following demonstrates how the path works with a dictionary property instead of concrete properties: [SpaceClass] public class Account { ... @SpaceId Guid getId {get; set;} IDictionary<String, double> Balance {get; set;} } ISpaceProxy space = // ... obtain a space reference Guid id = ...; IdQuery<Account> idQuery = new IdQuery<Account>(id, routing); space.Change(idQuery, new ChangeSet().Increment("Balance.Euro", 5.2D)); In this case the key euro inside the dictionary behind the balance will be increased by 5.2. Available Change Set Operations
Using Change with the Embedded modelWith the embedded model, updating (as well adding or removing) a nested collection with large number of elements must use the change API since the default behavior would be to replicate the entire space object and its nested collection elements from the primary to the backup (or other replica primary copies when using the sync-replicate or the async-replicated cluster schema). The Change API reduces the CPU utilization at the primary side, reduce the serialization overhead and reduce the garbage collection activity both at the primary and backup. This improves the overall system stability significantly. Change ResultThe change operations returns a IChangeResult object that provides information regarding the change operation affect. /// <summary> /// Result of a change operation. /// </summary> /// <typeparam name="T"></typeparam> public interface IChangeResult<T> { /// <summary> /// Gets a collection of <see cref="IChangedEntryDetails{T}"/> of the changed /// entries. /// This is only supported if the <see cref="ChangeModifiers.ReturnDetailedResults"/> modifier was used, /// otherwise this method will throw unsupported operation exception. /// </summary> /// <exception cref="NotSupportedException">If the corresponding change /// operation was not used with the <see cref="ChangeModifiers.ReturnDetailedResults"/>.</exception> ICollection<IChangedEntryDetails<T>> Results { get;} /// <summary> /// Gets the number of changed entries. /// </summary> int NumberOfChangedEntries { get; } } ISpaceProxy space = // ... obtain a space reference Guid id = ...; IdQuery<Account> idQuery = new IdQuery<Account>(id, routing); IChangeResult<Account> changeResult = space.Change(idQuery, new ChangeSet().Increment("Balance.Euro", 5.2D)); if (changeResult.NumberOfChangedEntries == 0) { // ... handle no entry found for change } The IChangeResult contains the NumberOfChangedEntries which specifies how many objects where changed by this operation where 0 means none were changed. The Results property gives further details about the objects that were actually changes by providing a collection which gives details for each of the objects that were changed, such as their id and version after the change took affect. By default, in order to reduce network overhead, calling the Results will throw NotSupportedException. In order to get the more detailed result, the ChangeModifiers.ReturnDetailedResults should be passed to the Change operation. ChangeExceptionUpon any error a ChangeException will be thrown containing the following details: public class ChangeException { /// <summary> /// Gets the failed changes. /// </summary> public ICollection<Exception> Errors {get;} /// <summary> /// Gets the entries that failed to change result. /// </summary> public ICollection<IFailedChangedEntryDetails> FailedChanges {get;} /// <summary> /// Gets the successfully done changes. /// </summary> public ICollection<IChangedEntryDetails<object>> SuccessfulChanges {get;} /// <summary> /// Gets the number of succesfull changes /// </summary> public int NumOfSuccessfulChanges {get;} } The NumSuccesfullChanges property contains the number of entries that were successfully changed. Multiple Changes in One OperationOne may apply multiple changes in one Change operation by setting up multiple operation in the change set, this is done simply by chaining changes as follows: ISpaceProxy space = // ... obtain a space reference IdQuery<MyObject> idQuery = new IdQuery<MyObject>(id, routing); space.Change(idQuery, new ChangeSet().Increment("SomeIntProperty", 1) .Set("SomeStringProperty", "NewStringValue) .SetInDictionary("SomeNestedProperty.SomeDictionaryProperty", "MyKey", 2)); The changes will applied to the object sequentially (and atomically) keeping the order applied on the ChangeSet. Changing the Object's LeaseBy default, the change operation will not modify the existing remaining lease of the changed entries. In order to change the lease, the new lease should be specified on the ChangeSet using the lease operation. ISpaceProxy space = // ... obtain a space reference space.Change(idQuery, new ChangeSet().Lease(1000)...); The lease can be changed as part of other changes applied to the object, as well as having the ChangeSet include only the lease modification without any property changes. Change with TimeoutA timeout can be passed to the change operation, this timeout will only be used if any of the objects that needs to be changed is locked under a transaction which is not from the
If there were no matching objects for the specified template, the operation will return immediately without waiting for the timeout to elapse. This is similar to the (Read/Take)IfExists operation semantic. ISpaceProxy space = // ... obtain a space reference Guid id = ...; IdQuery<Account> idQuery = new IdQuery<Account>(id, routing); long timeout = 1000; //1 seconds try { space.Change(idQuery, new ChangeSet().Increment("Balance.Euro", 5.2D), timeout); } catch(ChangeException e) { if (e.FailedChanges.Count > 0)) { foreach(IFailedChangedEntryDetails failedChangedEntry in e.FailedChanges) { if (id.Equals(failedChangedEntry.Id) && failedChangedEntry.Error is OperationTimeoutException) { //.. Indicate the object is still locked under a transaction, maybe retry the operation? } } } } Change and Optimistic LockingThe Change operation has the same semantics as regular space Update operation when it comes to Optimistic Locking. It will increase the version of the changed object and the expected version can be specified in the id query when optimistic locking is needed. ISpaceProxy space = // ... obtain a space reference Guid id = ...; Object routing = id; // In our case the space routing property is the space id property. int version = 2; // We only want to change the object if the object's version in the space is 2. IdQuery<Account> idQuery = new IdQuery<Account>(id, routing, version); try { space.Change(idQuery, new ChangeSet().Increment("Balance.Euro", 5.2D), timeout); } catch(ChangeException e) { if (e.FailedChanges.Count > 0)) { foreach(IFailedChangedEntryDetails failedChangedEntry in e.FailedChanges) { if (id.Equals(failedChangedEntry.Id) && failedChangedEntry.Error is EntryVersionConflictException) { //.. Indicate optimistic locking failure, get the updated version for instance and maybe read updated object and retry? int updatedVersion = failedChangedEntry.Version; } } } }
Change and NotificationsChange will be delivered as a regular update notification, with the state of the object after the change was applied. Change ModifiersThe following modifiers can be used with the change operation
Considerations
|
![]() |
GigaSpaces.com - Legal Notice - 3rd Party Licenses - Site Map - API Docs - Forum - Downloads - Blog - White Papers - Contact Tech Writing - Gen. by Atlassian Confluence |