Process Instance Locking

Introduction

Process Instances and their corresponding Value Stores hold the state of Process execution, also known as Process data. In a production FNZ Studio installation, Process data is the most valuable data and it is changed with every click. Because multiple end users can work concurrently on the same Process Instance, Process data must be protected from concurrent modifications. FNZ Studio uses locking to prevent such modifications. Furthermore, to ensure consistent data, isolation and transactions are used to update Process Instances and their corresponding Value Stores.

Locking

Process Instance locking uses a distributed lock pool. Before updating a Process Instance, a lock from the lock pool has to be acquired. As soon as it is acquired, the Process Instance and its Value Store can be modified. The changes are atomically committed to the Cluster Memory (distributed maps) and the lock is released.

diagram_process_locking.jpg

Acquiring Write Locks

The WorkflowInstanceService interface provides the following methods in order to acquire a write lock:

  • getWorkflowInstance(String)
  • getWorkflowInstanceByTokenId(String)
  • insertWorkflowInstance(WorkflowInstance)
  • deleteWorkflowInstance(String)

Write locks are kept until the thread has completed its work and the changes have been committed. If a thread tries to acquire the same write lock twice during one transaction, the second call is ignored.

The ProcessInstanceCacheLayer class implements the functionality of acquiring write locks. The lock pool itself is implemented by the LockPool class.

Note: The default hashing algorithm used by the Process Instance lock pool is CRC32. You can configure the hashing algorithm through the following configuration property: `nm.cluster.lockpool.processinstances.hash.algorithm`. Valid values are: hashCode, md5, sha256, crc32, murmur3, sipHash24.

Committing Changes and Releasing Write Locks

ClusterUtils.commit() is employed to commit the changes performed during transactions. For HTTP threads spawned by the application server, this is automatically done in a servlet filter: ClusterFilter.

The commit operation loops over all thread-local changes and either inserts/updates or removes Process Instances and their Value Stores in the Cluster Memory (distributed maps). After all changes have been committed, all existing write locks are released.

Isolation

To ensure that modifications performed by one thread do not affect other concurrently running threads, all changes on Process Instances and Value Stores are performed in isolation on a clone of the actual Process Instance or Value Store.

A Process Instance is cloned after the write lock is acquired using one of the methods described above (see Section 2.1). For a new Process Instance, the newly created WorkflowInstance object is used, as only the current thread can see this object until it is committed into the Cluster Memory.

Any changes made to the Process Instance and its Value Store during a transaction are performed on the cloned objects. When the transaction has completed, during the commit operation, the cloned objects that now contain the most up-to-date state are placed back into the Cluster Memory (distributed maps).