New batch API for custom field value retrieval

We are moving CustomFieldPrefetchedData, NonNullCustomFieldProvider and DefaultNonNullCustomFieldProvider to new packages to make it possible to run plugins compiled with the new APIs on older versions of Jira.

Moreover, to further improve Jira custom fields performance, with the 8.12 release we are introducing new APIs in:

  • com.atlassian.jira.issue.customfields.vdi.NonNullCustomFieldProvider and
  • com.atlassian.jira.issue.customfields.persistence.CustomFieldValuePersister.

NonNullCustomFieldProvider

For now, we have been using getCustomFieldInfo(Issue issue) to fetch custom field values for a given issue.

@Deprecated
Map<String, CustomFieldPrefetchedData> getCustomFieldInfo(Issue issue);

It remains unchanged for the time being, however we have also introduced similar API getCustomFieldInfo(List<Issue> issues).

Map<Long, Map<String, CustomFieldPrefetchedData>> getCustomFieldInfo(List<Issue> issues);

It is by default used only in DC licensed Jira instances during a full reindex process. Jira administrator can further configure this feature with jira.custom.field.indexing.batch.size property. Setting its value to 1 switches Jira to use getCustomFieldInfo(Issue issue) instead. Any other number defines the number of issues that will be passed to getCustomFieldInfo(List<Issue> issues), by default this number is 50. Returned values are mapped to custom field id (e.g. customfield_10000) and further grouped by issue id.

The goal of this API is to improve performance by reducing the number of times the most time-consuming operation executes - for example, a database search.

CustomFieldValuePersister

For the same reasons, a new API is introduced in CustomFieldValuePersister.

@ExperimentalApi
default Map<Long, List<CustomFieldValue>> getValues(final Set<Long> issueIds) {
    throw new UnsupportedOperationException();
}

List of CustomFieldValue objects is grouped by issue id. This is very similar to the API introduced in 8.10.

@ExperimentalApi
default List<CustomFieldValue> getValues(final long issueId) {
    throw new UnsupportedOperationException();
}

What’s next?

We aim to completely remove the use of getCustomFieldInfo(Issue issue) over the next few minor releases and switch completely to using getCustomFieldInfo(List<Issue> issues) instead.

When implementing the new SPI, please keep in mind that one day lists containing only one element might be passed down to your code. Ideally, your implementation should recognise such scenario and act accordingly.

If you have problems implementing the new SPI and introducing more batch SPIs in other parts of Jira would help, let us know and we will have a look at that.

3 Likes

Just a quick update to clarify some things. The jira.custom.field.indexing.batch.size parameter can be provided from the terminal when running the application like any other JVM parameter (-Djira.custom.field.indexing.batch.size=0) or in jira-config.properties file (jira.custom.field.indexing.batch.size=0).