Geode provides APIs to capture a handful of events in such that a distributed system providing extensive documentation on how to implement listeners and callbacks for processing those can capture events, invoking callbacks to process those events either synchronously or asynchronously.
This document covers CacheWriter
and CacheListener
best practices for handlingCacheEvents
covers best practices for the CacheWriter
and the CacheListener
.
Event Model
Cache Writers
A CacheWriter
is an event handler that synchronously handles “happens-before” events (CacheEvent
) in an ordered fashion. It is mostly used for data validation and in some cases data invoked synchronously prior to an event. A cache writer is often used to validate data prior to an update of that data. It may also do a synchronization with external data sources, offering . This provides a write-through capability for regions handling events that can be local, within the same JVM, or remote, in the case of replicated or partitioned region.
Basic rules:
- There can be only one
CacheWriter
per Regionregion. - For partitioned regions, only the writer in node that hosts the event’s primary node will process the eventbucket of the data will be the one that invokes the cache writer.
- For replicated regions, only the first node to successfully execute the writer will process the event.
- For local regions, only the local cache writer (if defined) will process the event.Unlike cache listeners, you can only install one cache writer in a region for each member.
CacheWriter
can abort operations (fail-fast), and will propagate theCacheWriterException
back aCacheWriterException
will propagate back to the caller.- Being a synchronous callback, it will block the current blocks the application's execution until it the handler completes.
Available CacheWriter
events and callbacks:
Code Block | ||
---|---|---|
| ||
beforeCreate(EntryEvent event)- Invoked before an entry is created. beforeUpdate(EntryEvent event) - Invoked before an entry is updated. beforeDestroy(EntryEvent event) - Invoked before an entry is destroyed. beforeRegionClear(RegionEvent event) - Invoked before a region is cleared. beforeRegionDestroy(RegionEvent event) - Invoked before a region is destroyed. |
It is not recommended to perform long Because CacheWriter handlers are called synchronously, the application does not continue until the handler returns. Therefore, do not do long-running operations inside a CacheWriter
within the current threadhandler. If such a long-running operation is needed, consider processing it the operation asynchronously through an AsyncEventListener
for example. Using an ExecutorService
ExecutorService
to delegate that the execution to a different thread is possible, but considered it is an anti-pattern, since as it breaks no longer implements the fail-fast and happens-before concept of this callbackproperty, and the handling of the event is no longer synchronous, so its timing would not be guaranteed relative to the application's completion of the event.
Cache Listeners
A CacheListener
is an event handler that invoked synchronously responds to events after modifications occurred in the systemto a region occur. The main use cases for a CacheListener
are synchronous write-behind and notifications, triggering actions after certain modifications occur on a region or on the system. It . The CacheListener
can handle cache events related to entries (EntryEvent
) and regions (RegionEvent
), but events can be processed in a different order than the order they’re applied in in which they’ are applied to the region.
Basic rules:
- You can install multiple
CacheListener
in handlers in the same region. - When multiple listeners are installed, they will be executed in the same order they’re registered in the system. One at a timethe handlers are invoked serially. The invocation ordering is the same as the in which the listeners were registered.
- For partitioned regions, only the listeners in the event’s primary node will process the event the node that hosts the primary bucket of the data will be the one that invokes the cache listeners.
- For replicated regions, all nodes with the listener installed will process the event.
- For local regions, only local listener listeners (if defined) will process the event.
- For long running or batch processing, consider using an
AsynchronousEventListener
. - Being a synchronous callback, it will block the current execution until it the execution of each handler blocks the application's execution until the handler completes.
Available CacheListener
events and callbacks:
Code Block | ||
---|---|---|
| ||
afterCreate(EntryEvent<K,V> event) - HandlesInvoked theafter event ofa new key beingis added to a region afterDestroy(EntryEvent<K,V> event) - Handles the event ofInvoked after an entry beingis destroyed afterInvalidate(EntryEvent<K,V> event) - Handles the event ofInvoked after an entry's value beingis invalidated afterRegionClear(RegionEvent<K,V> event) - Handles the event ofInvoked after a region beingis cleared afterRegionCreate(RegionEvent<K,V> event) - Handles the event ofInvoked after a region beingis created afterRegionDestroy(RegionEvent<K,V> event) - Handles the event ofInvoked after a region beingis destroyed afterRegionInvalidate(RegionEvent<K,V> event) - Handles the event ofInvoked after a region beingis invalidated afterRegionLive(RegionEvent<K,V> event) - Handles the event ofInvoked after a region beingbecomes live after receiving the marker from the server afterUpdate(EntryEvent<K,V> event) - Handles the event ofInvoked after an entry's value beingis modified in a region |
General recommendations
When dealing with Geode callbacks, there are some operations that should be avoided or used with extra attention. Some general recommendations are:
- Do not perform distributed operations, such as using using the Distributed Lock service.
- Avoid calling Region methods, particularly on non-colocated, partitioned regions.
- Avoid calling functions through
FunctionService
, since they the function's execution can cause distributed deadlocksdeadlock. - Do not use any Geode APIs inside a
CacheListener
if you have conserve-sockets set to true. - Do not modify region attributes, since those messages will have priority and can cause blocks.
- Avoid configurations where in which listeners or writers are deployed in a few nodes of the distributed system. Prefer a cluster-wide installation where every node can process the callback.
- Any exceptions thrown are caught and logged, so users can troubleshoot using Geode logs.
EntryEvent.getNewValue()
orEntryEvent.getOldValue()
can result in deserializations, unless PDX andread-serialized=true
are used.- Operations inside a
CacheListener
or aCacheWriter
are thread-safe, and entries are locked for the current thread.
When using transactions:
- A
CacheWriter
should not start transactions;. - Both
CacheWriter
and and anyCacheListener
will receive all individual operations as part of a transaction, unlike their transactional counterpartsTransactionWriter
and andTransactionListener
;.
- When a rollback or commit happens, a
CacheWriter
can only be notified by aaTransactionWriter
, and should handle rollback or failures properly;. CacheWriterException
is still propagated to the application, and it should handle the failures in the context of the transaction by continuing or aborting; JTA is the recommended alternative.- In most cases when dealing with transactions, consider using a
TransactionWriter
,CacheWriter.
- With global transactions,
EntryEvent.getTransactionId()
will return the current internal transaction ID. - Use the same transactional data source and make sure it’s it is JTA-enabled, so database operations inside a
CacheWriter
can be rolled back and participate in the same global transaction.
When dealing with transactions always consider using TransactionListener
or or TransactionWriter
for handling transaction events, but do notice that they’re they are cache-wide handlers.