Occasionally, you may need to write an OSGi service that executes a specific task that runs on a certain trigger such as a daily job that imports content into the repository.
A very common production setup will have more than one node making up a cluster. Without taking proper precaution, this service would typically be installed and executed on all nodes in that cluster, which is undesirable.
Further, if we do ensure that only one node processes this task and this node fails, we'd like to have another node be able to do the work.
The solution is to have your service implement the ClusterAware interface. Services that implement the ClusterAware interface will be notified about changes to the cluster through the bindRepository() method. This allows the service to conveniently store information about whether or not it is currently running on the master node.
In the gist below, an OSGi service has been created to run on a timed interval. At each interval, it will look to see first if it is running on the master node before proceeding.
If the current master dies, one of the slaves will be promoted to master. Since this event triggers bindRepository to be called on all services that implement ClusterAware and in our example, will have their isMaster value updated accordingly.
To test this out on your own, read more about setting up a basic cluster. Once you have one running you can install a service like the one above and do the following:
- Watch both logs to validate that only one node in the cluster is doing the work
- Shut down the master and confirm that a slave gets promoted to master.
- Validate at the next scheduled interval, the new master is logging that it is now doing the work.