Scarlet
 

Scarlet - APIs for Jira developers

Developing Jira plugins and other kind of extensions in a cluster environment is, as often as not, the same as in a single-instance environment: you have to use the same concepts and APIs described in the standard Jira documentation, without taking care of the cluster infrastructure. However, sometimes you may need to be aware of the cluster environment, in order to interact with it: Scarlet provides a set of simple APIs to use for accomplishing common cluster-related tasks in your own code.

Developing Jira distributed services

Jira services are standard Java classes that periodically run within Jira and execute some given task.

In a Jira clustered environment, the default behaviour is to run a service once per cluster: that is, the service will be fired on one single (unspecified) node, then it will wait for its period and be fired again on one single (unspecified, maybe different) node, and so on.
You can change this behaviour for your custom services by just letting them implement the com.sourcesense.scarlet.service.JiraDistributedService empty interface. Doing so, your service will run in distributed mode: that is, the service will be fired and executed on every cluster node, then it will wait for its period and be fired on all nodes again, and so on.

Choosing between the two behaviours depends on what you actually want to do.
However, it's just a matter of implementing an empty interface.

Developing Jira distributed actions

Jira distributed actions are Scarlet-specific classes used to execute arbitrary code on every cluster node. The difference between a distributed service (described above) and a distributed action is that the former is configured through the Jira web interface and runs periodically, while the latter is used and executed programmatically.

To develop and use a Jira distributed action you have to:

  1. Implement the com.sourcesense.scarlet.invoker.JiraDistributedAction interface.
    The execute method contains the logic that will be distributed on every cluster node and accepts a map of parameters whose keys and values must either:
    • Be a primitive wrapper class (i.e. java.lang.Integer).
    • Be a java.lang.String
    • Implement the com.sourcesense.scarlet.invoker.JiraDistributedParameter interface and only have attributes of these types.
    Other parameter types may not properly work.
  2. Register the action class by calling the com.sourcesense.scarlet.invoker.JiraDistributedInvoker#registerAction(Class) method.
    To access the JiraDistributedInvoker you have to go through the Jira ComponentManager; i.e.:
                            ComponentManager.getComponentInstanceOfType(JiraDistributedInvoker.class)
                        
  3. Invoke the action by calling the com.sourcesense.scarlet.invoker.JiraDistributedInvoker#invokeAction(Class, Map) method. Please note that every time the invokeAction method is executed, a new instance of the action class in created.

Advanced APIs

The APIs described in the following sections are meant for advanced usage only.
You can skip this section and come back later if needed.

Accessing the CacheGroup APIs

The com.sourcesense.scarlet.cache.CacheGroup is a common caching API provided by Scarlet.
It is a local cache with distributed cache invalidation strategy, so it's not a replicated cache: every cluster node has its own cache with its own data and there's no network overhead, given that there's no replication.

As a rule of thumb, your plugins shouldn't share any state in the cluster, and just use distributed actions to update nodes in case of important events.

However, if you really need to cache your plugin data and keep your cache updated among cluster nodes, you can use the CacheGroup APIs by accessing it through the com.sourcesense.scarlet.cache.CacheGroupHolder#getCacheGroup() method, which returns you the main com.sourcesense.scarlet.cache.CacheGroup class. To access the CacheGroupHolder you have to go through the Jira ComponentManager; i.e.:

                    ComponentManager.getComponentInstanceOfType(CacheGroupHolder.class)
                
Important
Do not directly access the com.sourcesense.scarlet.cache.CacheGroup class!

Please take a look at the com.sourcesense.scarlet.cache.CacheGroup javadoc for more details.