Custom StorageProvider

Your database is not supported out of the box? Implement a custom JobRunr StorageProvider for any database.

On this page

JobRunr supports all major SQL and NoSQL databases out of the box. If yours is not listed, you have two options.

Use an API-compatible database

Many databases speak a wire protocol that JobRunr already supports, so you can reuse an existing StorageProvider:

  • PostgreSQL-compatible databases (TimescaleDB, YugabyteDB, AWS Aurora PostgreSQL, …) work with the PostgreSQL driver. See PostgreSQL and CockroachDB.
  • MySQL-compatible databases (AWS Aurora MySQL, TiDB, …) work with the MySQL driver. See MySQL.
  • MongoDB-compatible databases (Amazon DocumentDB, …) work with the MongoDB driver. See Amazon DocumentDB.

If your database is API-compatible with any of these, start there.

Note

Support for Redis and Elasticsearch was deprecated in JobRunr v7 and removed in v8. If you relied on LettuceStorageProvider, JedisStorageProvider, or ElasticSearchStorageProvider, migrate to one of the supported databases.

Implement a custom StorageProvider

For anything else, you can implement the org.jobrunr.storage.StorageProvider interface yourself. This is what every built-in provider does, so the existing implementations are your best reference - browse them in the JobRunr source on GitHub.

Then register it like any other provider:

JobRunr.configure()
    .useStorageProvider(new MyCustomStorageProvider(/* ... */))
    .useBackgroundJobServer()
    .initialize();

When using a framework, expose your implementation as a StorageProvider bean and JobRunr will pick it up.

Test your implementation thoroughly

A StorageProvider is the backbone of JobRunr - if it misbehaves, jobs are lost, duplicated, or processed more than once. That is why JobRunr ships StorageProviderTest, the same abstract test suite every built-in provider is verified against. To be fully compatible, your implementation has to pass it. It is published as a test fixtures artifact, so you can depend on it directly:

<dependency>
  <groupId>org.jobrunr</groupId>
  <artifactId>jobrunr</artifactId>
  <version>8.8.0</version>
  <classifier>test-fixtures</classifier>
  <scope>test</scope>
</dependency>

Extend it and hand it your provider:

class MyCustomStorageProviderTest extends StorageProviderTest {

    @Override
    protected StorageProvider getStorageProvider() {
        return new MyCustomStorageProvider(/* ... */);
    }

    @Override
    protected void cleanup(int testMethodIndex) {
        // wipe the database between tests
    }
}

You may deliberately skip part of it. For instance, if you know you will never use recurring jobs, for instance, you can disable those tests. What you cannot skip is making sure the unsupported paths degrade gracefully instead of crashing JobRunr. The InMemoryStorageProvider and its tests are a good, dependency-free starting point to study.

Caution

Test exhaustively, including concurrent access from multiple background job servers. JobRunr relies on the StorageProvider for distributed coordination; incomplete testing can lead to jobs being processed twice or skipped in production.


Back to the Storage overview.