Concurrency Support - Wolfgang-Schuetzelhofer/jcypher GitHub Wiki
Previous | Next | Table of Contents |
When multiple clients access a database concurrently, you need a mechanism to ensure data consistency.
The appropriate mechanism provided by JCypher is called optimistic locking.
How does it work?
Imagine you have two database clients.
Client 1 reads data from the db, client 2 reads data from the db.
Next client 1 modifies data in the db and after that client 2 tries to modify the same data.
JCypher, by means of optimistic locking, will detect the conflict and will avoid that client 2 stores the data and possibly leaves inconsistent data in the database.
Instead client two will return an error (an optimistic locking error).
Internally JCypher uses version information on every node and relation to provide optimistic locking.
By default, optimistic locking is switched off. You can activate optimistic locking by setting a locking strategy on either an IDomainAccess
(or an IGenericDomainAccess
) when working with complex domain models, or on a Graph
(iot.jcypher.graph.Graph
), when working at the level of the generic graph model respectively.
IDomainAccess da = DomainAccessFactory
.createDomainAccess(dbAccess,domainName)
.setLockingStrategy(Locking.OPTIMISTIC);
IGenericDomainAccess gda = DomainAccessFactory
.createGenericDomainAccess(dbAccess, domainName)
.setLockingStrategy(Locking.OPTIMISTIC);
Graph g = Graph.create(dbAccess)
.setLockingStrategy(Locking.OPTIMISTIC)
If you read data by performing a domain query against a graph database, in the time between creating an IDomainAccess (or an IGenericDomainAccess) and between performing the query, another client may not only have modified the data you are querying (which is no real issue for data currentness), but it may have changed (extended) the underlying domain model (e.g. by storing instances of a domain class which had not been stored before). Note: The meta information, i.e. the information about the stored domain model, is expanded dynamically as new domain objects are persisted.
In the latter case mentioned above, the query to be performed is not complete with respect to the changed domain model, and hence will not produce the correct result.
In such a case, JCypher will detect the domain model change, re-create the domain query based on the changed model, and perform the now corrected query in order to retrieve current data from the graph database.
Note: Currentness on reading data is provided independently of the selected locking strategy. The selected locking strategy only influences consistency of data when writing to the db.
When you work with domain models and domain objects using JCypher, your central access point to a domain is an instance of IDomainAccess
(or IGenericDomainAccess
respectively). Remember how you acquired such an instance using DomainAccessFactory
:
// create an IDomainAccess
IDomainAccess domainAccess =
DomainAccessFactory.createDomainAccess(dbAccess, domainName);
The IDomainAccess
instance you acquire in that way however is not thread-safe. In a multithreaded environment you have to synchronize the access by yourself.
JCypher provides an alternative way to create IDomainAccess
or IGenericDomainAccess
instances, namely the interface IDomainAccessFactory
. Here is how you use it:
// create a thread-safe IDomainAccess
IDomainAccess domainAccess =
IDomainAccessFactory.INSTANCE_SYNCHRONIZED
.createDomainAccess(dbAccess, domainName);
This will return a thread-safe instance of IDomainAccess
.
To retrieve the same IDomainAccess
instance (not thread-safe) as with the DomainAccessFactory
class, you use the interface as follows:
// create an IDomainAccess
IDomainAccess domainAccess =
IDomainAccessFactory.INSTANCE
.createDomainAccess(dbAccess, domainName);
By providing IDomainAccessFactory
, the previous way using class DomainAccessFactory
has become obsolete. Nevertheless DomainAccessFactory
will stay available for backward compatibility.
Note: Domain queries you create by using the thread-safe IDomainAccess
are also thread-safe. But your domain objects, as they simply are pojos are not, and you have to make sure that you don't corrupt data by multithreaded access to those domain objects.
Previous | Next | Table of Contents |