Distributed lock for your scheduled tasks

Overview

ShedLock

Apache License 2 Build Status Maven Central

ShedLock makes sure that your scheduled tasks are executed at most once at the same time. If a task is being executed on one node, it acquires a lock which prevents execution of the same task from another node (or thread). Please note, that if one task is already being executed on one node, execution on other nodes does not wait, it is simply skipped.

ShedLock uses an external store like Mongo, JDBC database, Redis, Hazelcast, ZooKeeper or others for coordination.

Feedback and pull-requests welcome!

ShedLock is not a distributed scheduler

Please note that ShedLock is not and will never be full-fledged scheduler, it's just a lock. If you need a distributed scheduler, please use another project. ShedLock is designed to be used in situations where you have scheduled tasks that are not ready to be executed in parallel, but can be safely executed repeatedly. Moreover, the locks are time-based and ShedLock assumes that clocks on the nodes are synchronized.

Components

Shedlock consists of three parts

  • Core - The locking mechanism
  • Integration - integration with your application, using Spring AOP, Micronaut AOP or manual code
  • Lock provider - provides the lock using an external process like SQL database, Mongo, Redis and others

Usage

To use ShedLock, you do the following

  1. Enable and configure Scheduled locking
  2. Annotate your scheduled tasks
  3. Configure a Lock Provider

Enable and configure Scheduled locking (Spring)

First of all, we have to import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-spring</artifactId>
    <version>4.21.0</version>
</dependency>

Now we need to integrate the library with Spring. In order to enable schedule locking use @EnableSchedulerLock annotation

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "10m")
class MySpringConfiguration {
    ...
}

Annotate your scheduled tasks

import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;

...

@Scheduled(...)
@SchedulerLock(name = "scheduledTaskName")
public void scheduledTask() {
   // To assert that the lock is held (prevents misconfiguration errors)
   LockAssert.assertLocked();
   // do something
}

The @SchedulerLock annotation has several purposes. First of all, only annotated methods are locked, the library ignores all other scheduled tasks. You also have to specify the name for the lock. Only one task with the same name can be executed at the same time.

You can also set lockAtMostFor attribute which specifies how long the lock should be kept in case the executing node dies. This is just a fallback, under normal circumstances the lock is released as soon the tasks finishes. You have to set lockAtMostFor to a value which is much longer than normal execution time. If the task takes longer than lockAtMostFor the resulting behavior may be unpredictable (more than one process will effectively hold the lock).

If you do not specify lockAtMostFor in @SchedulerLock default value from @EnableSchedulerLock will be used.

Lastly, you can set lockAtLeastFor attribute which specifies minimum amount of time for which the lock should be kept. Its main purpose is to prevent execution from multiple nodes in case of really short tasks and clock difference between the nodes.

All the annotations support Spring Expression Language (SpEL).

Example

Let's say you have a task which you execute every 15 minutes and which usually takes few minutes to run. Moreover, you want to execute it at most once per 15 minutes. In that case, you can configure it like this:

import net.javacrumbs.shedlock.core.SchedulerLock;


@Scheduled(cron = "0 */15 * * * *")
@SchedulerLock(name = "scheduledTaskName", lockAtMostFor = "14m", lockAtLeastFor = "14m")
public void scheduledTask() {
   // do something
}

By setting lockAtMostFor we make sure that the lock is released even if the node dies and by setting lockAtLeastFor we make sure it's not executed more than once in fifteen minutes. Please note that lockAtMostFor is just a safety net in case that the node executing the task dies, so set it to a time that is significantly larger than maximum estimated execution time. If the task takes longer than lockAtMostFor, it may be executed again and the results will be unpredictable (more processes will hold the lock).

Configure LockProvider

There are several implementations of LockProvider.

JdbcTemplate

First, create lock table (please note that name has to be primary key)

# MySQL, MariaDB
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until TIMESTAMP(3) NOT NULL,
    locked_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));

# Postgres
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until TIMESTAMP NOT NULL,
    locked_at TIMESTAMP NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));

# Oracle
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until TIMESTAMP(3) NOT NULL,
    locked_at TIMESTAMP(3) NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));

# MS SQL
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL, lock_until datetime2 NOT NULL,
    locked_at datetime2 NOT NULL, locked_by VARCHAR(255) NOT NULL, PRIMARY KEY (name));

# DB2
CREATE TABLE shedlock(name VARCHAR(64) NOT NULL PRIMARY KEY, lock_until TIMESTAMP NOT NULL,
    locked_at TIMESTAMP NOT NULL, locked_by VARCHAR(255) NOT NULL);

Add dependency

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-jdbc-template</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;

...
@Bean
public LockProvider lockProvider(DataSource dataSource) {
            return new JdbcTemplateLockProvider(
                JdbcTemplateLockProvider.Configuration.builder()
                .withJdbcTemplate(new JdbcTemplate(dataSource))
                .usingDbTime() // Works on Postgres, MySQL, MariaDb, MS SQL, Oracle, DB2, HSQL and H2
                .build()
            );
}

By specifying usingDbTime() (introduced in 4.9.3) the lock provider will use UTC time based on the DB server time. If you do not specify this option, current time on the client will be used (the time may differ between clients).

For more fine-grained configuration use other options of the Configuration object

new JdbcTemplateLockProvider(builder()
    .withTableName("shdlck")
    .withColumnNames(new ColumnNames("n", "lck_untl", "lckd_at", "lckd_by"))
    .withJdbcTemplate(new JdbcTemplate(getDatasource()))
    .withLockedByValue("my-value")
    .withTimeZone(TimeZone.getTimeZone("UTC"))
    .build())

If you need to specify a schema, you can set it in the table name using the usual dot notation new JdbcTemplateLockProvider(datasource, "my_schema.shedlock")

Warning

Do not manually delete lock row from the DB table. ShedLock has an in-memory cache of existing locks so the row will NOT be automatically recreated until application restart. If you need to, you can edit the row/document, risking only that multiple locks will be held. Since 1.0.0 you can clean the cache by calling clearCache() on LockProvider.

Mongo

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-mongo</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.mongo.MongoLockProvider;

...

@Bean
public LockProvider lockProvider(MongoClient mongo) {
    return new MongoLockProvider(mongo.getDatabase(databaseName))
}

Please note that MongoDB integration requires Mongo >= 2.4 and mongo-java-driver >= 3.7.0

Reactive Mongo

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-mongo-reactivestreams</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.mongo.reactivestreams.ReactiveStreamsMongoLockProvider;

...

@Bean
public LockProvider lockProvider(MongoClient mongo) {
    return new ReactiveStreamsMongoLockProvider(mongo.getDatabase(databaseName))
}

Please note that MongoDB integration requires Mongo >= 4.x and mongodb-driver-reactivestreams 1.x

DynamoDB

This depends on AWS SDK v1.

Import the project

<dependency>
   <groupId>net.javacrumbs.shedlock</groupId>
   <artifactId>shedlock-provider-dynamodb</artifactId>
   <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.dynamodb.DynamoDBLockProvider;

...

@Bean
public LockProvider lockProvider(com.amazonaws.services.dynamodbv2.document.DynamoDB dynamoDB) {
   return new DynamoDBLockProvider(dynamoDB.getTable("Shedlock"));
}

Please note that the lock table must be created externally with _id as a partition key. DynamoDBUtils#createLockTable may be used for creating it programmatically. A table definition is available from DynamoDBLockProvider's Javadoc.

DynamoDB 2

This depends on AWS SDK v2.

Import the project

<dependency>
   <groupId>net.javacrumbs.shedlock</groupId>
   <artifactId>shedlock-provider-dynamodb2</artifactId>
   <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.dynamodb2.DynamoDBLockProvider;

...

@Bean
public LockProvider lockProvider(software.amazon.awssdk.services.dynamodb.DynamoDbClient dynamoDB) {
   return new DynamoDBLockProvider(dynamoDB, "Shedlock");
}

Please note that the lock table must be created externally with _id as a partition key. DynamoDBUtils#createLockTable may be used for creating it programmatically. A table definition is available from DynamoDBLockProvider's Javadoc.

ZooKeeper (using Curator)

Import

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-zookeeper-curator</artifactId>
    <version>4.21.0</version>
</dependency>

and configure

import net.javacrumbs.shedlock.provider.zookeeper.curator.ZookeeperCuratorLockProvider;

...

@Bean
public LockProvider lockProvider(org.apache.curator.framework.CuratorFramework client) {
    return new ZookeeperCuratorLockProvider(client);
}

By default, nodes for locks will be created under /shedlock node.

Redis (using Spring RedisConnectionFactory)

Import

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-redis-spring</artifactId>
    <version>4.21.0</version>
</dependency>

and configure

import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider;
import org.springframework.data.redis.connection.RedisConnectionFactory;

...

@Bean
public LockProvider lockProvider(RedisConnectionFactory connectionFactory) {
    return new RedisLockProvider(connectionFactory, ENV);
}

Redis lock provider uses classical lock mechanism as described here which may not be reliable in case of Redis master failure.

If you are still using Spring Data Redis 1, import special lock provider shedlock-provider-redis-spring-1 which works around issue #105 or upgrade to Spring Data Redis 2 or higher.

Redis (using Jedis)

Import

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-redis-jedis</artifactId>
    <version>4.21.0</version>
</dependency>

and configure

import net.javacrumbs.shedlock.provider.redis.jedis.JedisLockProvider;

...

@Bean
public LockProvider lockProvider(JedisPool jedisPool) {
    return new JedisLockProvider(jedisPool, ENV);
}

Hazelcast

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <!-- Hazelcast < 4 -->
    <artifactId>shedlock-provider-hazelcast</artifactId>
    <!-- Hazelcast 4 -->
    <!-- <artifactId>shedlock-provider-hazelcast4</artifactId> -->
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.hazelcast.HazelcastLockProvider;

...

@Bean
public HazelcastLockProvider lockProvider(HazelcastInstance hazelcastInstance) {
    return new HazelcastLockProvider(hazelcastInstance);
}

For Hazelcast 4 use shedlock-provider-hazelcast4 module and net.javacrumbs.shedlock.provider.hazelcast4 package.

Couchbase

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-couchbase-javaclient</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.couchbase.javaclient.CouchbaseLockProvider;

...

@Bean
public CouchbaseLockProvider lockProvider(Bucket bucket) {
    return new CouchbaseLockProvider(bucket);
}

For Couchbase 3 use shedlock-provider-couchbase3 module and net.javacrumbs.shedlock.provider.couchbase3 package.

Elasticsearch

I am really not sure it's a good idea to use Elasticsearch as a lock provider. But if you have no other choice, you can. Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-elasticsearch</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import static net.javacrumbs.shedlock.provider.elasticsearch.ElasticsearchLockProvider;

...

@Bean
public ElasticsearchLockProvider lockProvider(RestHighLevelClient highLevelClient) {
    return new ElasticsearchLockProvider(highLevelClient);
}

CosmosDB

CosmosDB support is provided by a third-party module available here

Cassandra

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-cassandra</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.cassandra.CassandraLockProvider;

...

@Bean
public CassandraLockProvider lockProvider(CqlSession cqlSession) {
    return new CassandraLockProvider(cqlSession);
}

Example for creating default keyspace and table in local Cassandra instance:

CREATE KEYSPACE shedlock with replication={'class':'SimpleStrategy', 'replication_factor':1} and durable_writes=true;
CREATE TABLE shedlock.lock (name text PRIMARY KEY, lockUntil timestamp, lockedAt timestamp, lockedBy text);

Please, note that CassandraLockProvider uses Cassandra driver v4, which is part of Spring Boot since 2.3.

Consul

ConsulLockProvider has one limitation: lockAtMostFor setting will have a minimum value of 10 seconds. It is dictated by consul's session limitations.

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-consul</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.consul.ConsulLockProvider;

...

@Bean // for micronaut please define preDestroy property @Bean(preDestroy="close")
public ConsulLockProvider lockProvider(com.ecwid.consul.v1.ConsulClient consulClient) {
    return new ConsulLockProvider(consulClient);
}

Please, note that Consul lock provider uses ecwid consul-api client, which is part of spring cloud consul integration (the spring-cloud-starter-consul-discovery package).

ArangoDB

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-arangodb</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.arangodb.ArangoLockProvider;

...

@Bean
public ArangoLockProvider lockProvider(final ArangoOperations arangoTemplate) {
    return new ArangoLockProvider(arangoTemplate.driver().db(DB_NAME));
}

Please, note that ArangoDB lock provider uses ArangoDB driver v6.7, which is part of arango-spring-data in version 3.3.0.

Etcd

Import the project

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-provider-etcd-jetcd</artifactId>
    <version>4.21.0</version>
</dependency>

Configure:

import net.javacrumbs.shedlock.provider.etcd.jetcd.EtcdLockProvider;

...

@Bean
public LockProvider lockProvider(Client client) {
    return new EtcdLockProvider(client);
}

Multi-tenancy

If you have multi-tenancy use-case you can use a lock provider similar to this one (see the full example)

private static abstract class MultiTenancyLockProvider implements LockProvider {
    private final ConcurrentHashMap<String, LockProvider> providers = new ConcurrentHashMap<>();

    @Override
    public @NonNull Optional<SimpleLock> lock(@NonNull LockConfiguration lockConfiguration) {
        String tenantName = getTenantName(lockConfiguration);
        return providers.computeIfAbsent(tenantName, this::createLockProvider).lock(lockConfiguration);
    }

    protected abstract LockProvider createLockProvider(String tenantName) ;

    protected abstract String getTenantName(LockConfiguration lockConfiguration);
}

Duration specification

All the annotations where you need to specify a duration support the following formats

  • duration+unit - 1s, 5ms, 5m, 1d (Since 4.0.0)
  • duration in ms - 100 (only Spring integration)
  • ISO-8601 - PT15M (see Duration.parse() documentation)

Micronaut integration

Since version 4.0.0, it's possible to use Micronaut framework for integration

Import the project:

<dependency>
    <groupId>net.javacrumbs.shedlock</groupId>
    <artifactId>shedlock-micronaut</artifactId>
    <version>4.21.0</version>
</dependency>

Configure default lockAtMostFor value (application.yml):

shedlock:
  defaults:
    lock-at-most-for: 1m

Configure lock provider:

@Singleton
public LockProvider lockProvider() {
    ... select and configure your lock provider
}

Configure the scheduled task:

@Scheduled(fixedDelay = "1s")
@SchedulerLock(name = "myTask")
public void myTask() {
    assertLocked();
    ...
}

Locking without a framework

It is possible to use ShedLock without a framework

LockingTaskExecutor executor = new DefaultLockingTaskExecutor(lockProvider);

...

Instant lockAtMostUntil = Instant.now().plusSeconds(600);
executor.executeWithLock(runnable, new LockConfiguration("lockName", lockAtMostUntil));

Extending the lock

Some lock providers support extension of the lock. For the time being, it requires manual lock manipulation, directly using LockProvider and calling extend method on the SimpleLock.

Modes of Spring integration

ShedLock supports two modes of Spring integration. One that uses an AOP proxy around scheduled method (PROXY_METHOD) and one that proxies TaskScheduler (PROXY_SCHEDULER)

Scheduled Method proxy

Since version 4.0.0, the default mode of Spring integration is an AOP proxy around the annotated method.

The main advantage of this mode is that it plays well with other frameworks that want to somehow alter the default Spring scheduling mechanism. The disadvantage is that the lock is applied even if you call the method directly. If the method returns a value and the lock is held by another process, null or an empty Optional will be returned (primitive return types are not supported).

Final and non-public methods are not proxied so either you have to make your scheduled methods public and non-final or use TaskScheduler proxy.

Method proxy sequenceDiagram

TaskScheduler proxy

This mode wraps Spring TaskScheduler in an AOP proxy. It can be switched-on like this (PROXY_SCHEDULER was the default method before 4.0.0):

@EnableSchedulerLock(interceptMode = PROXY_SCHEDULER)

If you do not specify your task scheduler, a default one is created for you. If you have special needs, just create a bean implementing TaskScheduler interface and it will get wrapped into the AOP proxy automatically.

@Bean
public TaskScheduler taskScheduler() {
    return new MySpecialTaskScheduler();
}

Alternatively, you can define a bean of type ScheduledExecutorService and it will automatically get used by the tasks scheduling mechanism.

TaskScheduler proxy sequence diagram

Spring XML configuration

Spring XML configuration is not supported as of version 3.0.0. If you need it, please use version 2.6.0 or file an issue explaining why it is needed.

Lock assert

To prevent misconfiguration errors, like AOP misconfiguration, missing annotation etc., you can assert that the lock works by using LockAssert:

@Scheduled(...)
@SchedulerLock(..)
public void scheduledTask() {
    // To assert that the lock is held (prevents misconfiguration errors)
    LockAssert.assertLocked();
    // do something
}

In unit tests you can switch-off the assertion by calling LockAssert.TestHelper.makeAllAssertsPass(true) on given thread (as in this example).

Kotlin gotchas

The library is tested with Kotlin and works fine. The only issue is Spring AOP which does not work on final method. If you use @SchedulerLock with @Scheduled annotation, everything should work since Kotling Spring compiler plugin will automatically 'open' the method for you. If @Scheduled annotation is not present, you have to open the method by yourself.

Caveats

Locks in ShedLock have an expiration time which leads to the following possible issues.

  1. If the task runs longer than lockAtMostFor, the task can be executed more than once
  2. If the clock difference between two nodes is more than lockAtLeastFor or minimal execution time the task can be executed more than once.

Troubleshooting

Help, ShedLock does not do what it's supposed to do!

  1. Upgrade to the newest version
  2. Check the storage. If you are using JDBC, check the ShedLock table. If it's empty, ShedLock is not properly configured. If there is more than one record with the same name, you are missing a primary key.
  3. Use ShedLock debug log. ShedLock logs interesting information on DEBUG level with logger name net.javacrumbs.shedlock. It should help you to see what's going on.
  4. For short-running tasks consider using lockAtLeastFor. If the tasks are short-running, they could be executed one after another, lockAtLeastFor can prevent it.
  5. If you encounter weird error complaining that a Proxy is not class of ThreadPoolTaskScheduler please check https://github.com/lukas-krecan/ShedLock/issues/115 or this StackOverflow quesiton

Requirements and dependencies

  • Java 8
  • slf4j-api

Release notes

4.21.0

  • Elastic unlock using IMMEDIATE refresh policy #422
  • DB2 JDBC lock provider uses microseconds in DB time
  • Various library upgrades

4.20.1

  • Fixed DB JDBC server time #378

4.20.0

  • Support for etcd (thanks grofoli)

4.19.1

  • Fixed devtools compatibility #368

4.19.0

  • Support for enhanced configuration in Cassandra provider (thanks DebajitKumarPhukan)
  • LockConfigurationExtractor exposed as a Spring bean #359
  • Handle CannotSerializeTransactionException #364

4.18.0

  • Fixed Consul support for tokens and added enhanced Consul configuration (thanks DrWifey)

4.17.0

  • Consul support for tokens

4.16.0

  • Spring - EnableSchedulerLock.order param added to specify AOP proxy order
  • JDBC - Log unexpected exceptions at ERROR level
  • Hazelcast upgraded to 4.1

4.15.1

  • Fix session leak in Consul provider #340 (thanks @haraldpusch)

4.15.0

  • ArangoDB lock provider added (thanks @patrick-birkle)

4.14.0

  • Support for Couchbase 3 driver (thanks @blitzenzzz)
  • Removed forgotten configuration files form micronaut package (thanks @drmaas)
  • Shutdown hook for Consul (thanks @kaliy)

4.13.0

  • Support for Consul (thanks @kaliy)
  • Various dependencies updated
  • Deprecated default LockConfiguration constructor

4.12.0

  • Lazy initialization of SqlStatementsSource #258

4.11.1

  • MongoLockProvider uses mongodb-driver-sync
  • Removed deprecated constructors from MongoLockProvider

4.10.1

  • New Mongo reactive streams driver (thanks @codependent)

4.9.3

  • Fixed JdbcTemplateLockProvider useDbTime() locking #244 thanks @gjorgievskivlatko

4.9.2

  • Do not fail on DB type determining code if DB connection is not available

4.9.1

  • Support for server time in DB2
  • removed shedlock-provider-jdbc-internal module

4.9.0

  • Support for server time in JdbcTemplateLockProvider
  • Using custom non-null annotations
  • Trimming time precision to milliseconds
  • Micronaut upgraded to 1.3.4
  • Add automatic DB tests for Oracle, MariaDB and MS SQL.

4.8.0

  • DynamoDB 2 module introduced (thanks Mark Egan)
  • JDBC template code refactored to not log error on failed insert in Postgres
    • INSERT .. ON CONFLICT UPDATE is used for Postgres

4.7.1

  • Make LockAssert.TestHelper public

4.7.0

  • New module for Hazelcasts 4
  • Ability to switch-off LockAssert in unit tests

4.6.0

  • Support for Meta annotations and annotation inheritance in Spring

4.5.2

  • Made compatible with PostgreSQL JDBC Driver 42.2.11

4.5.1

  • Inject redis template

4.5.0

  • ClockProvider introduced
  • MongoLockProvider(MongoDatabase) introduced

4.4.0

  • Support for non-void returning methods when PROXY_METHOD interception is used

4.3.1

  • Introduced shedlock-provider-redis-spring-1 to make it work around Spring Data Redis 1 issue #105 (thanks @rygh4775)

4.3.0

  • Jedis dependency upgraded to 3.2.0
  • Support for JedisCluster
  • Tests upgraded to JUnit 5

4.2.0

  • Cassandra provider (thanks @mitjag)

4.1.0

  • More configuration option for JdbcTemplateProvider

4.0.4

  • Allow configuration of key prefix in RedisLockProvider #181 (thanks @krm1312)

4.0.3

  • Fixed junit dependency scope #179

4.0.2

  • Fix NPE caused by Redisson #178

4.0.1

  • DefaultLockingTaskExecutor made reentrant #175

4.0.0

Version 4.0.0 is a major release changing quite a lot of stuff

  • net.javacrumbs.shedlock.core.SchedulerLock has been replaced by net.javacrumbs.shedlock.spring.annotation.SchedulerLock. The original annotation has been in wrong module and was too complex. Please use the new annotation, the old one still works, but in few years it will be removed.
  • Default intercept mode changed from PROXY_SCHEDULER to PROXY_METHOD. The reason is that there were a lot of issues with PROXY_SCHEDULER (for example #168). You can still use PROXY_SCHEDULER mode if you specify it manually.
  • Support for more readable duration strings
  • Support for lock assertion LockAssert.assertLocked()
  • Support for Micronaut added

3.0.1

  • Fixed bean definition configuration #171

3.0.0

  • EnableSchedulerLock.mode renamed to interceptMode
  • Use standard Spring AOP configuration to honor Spring Boot config (supports proxyTargetClass flag)
  • Removed deprecated SpringLockableTaskSchedulerFactoryBean and related classes
  • Removed support for XML configuration

2.6.0

  • Updated dependency to Spring 2.1.9
  • Support for lock extensions (beta)

2.5.0

  • Zookeeper supports lockAtMostFor and lockAtLeastFor params
  • Better debug logging

2.4.0

  • Fixed potential deadlock in Hazelcast (thanks @HubertTatar)
  • Finding class level annotation in proxy method mode (thanks @volkovs)
  • ScheduledLockConfigurationBuilder deprecated

2.3.0

  • LockProvides is initialized lazilly so it does not change DataSource initialization order

2.2.1

  • MongoLockProvider accepts MongoCollection as a constructor param

2.2.0

  • DynamoDBLockProvider added

2.1.0

  • MongoLockProvider rewritten to use upsert
  • ElasticsearchLockProvider added

2.0.1

  • AOP proxy and annotation configuration support

1.3.0

  • Can set Timezone to JdbcTemplateLock provider

1.2.0

  • Support for Couchbase (thanks to @MoranVaisberg)

1.1.1

  • Spring RedisLockProvider refactored to use RedisTemplate

1.1.0

  • Support for transaction manager in JdbcTemplateLockProvider (thanks to @grmblfrz)

1.0.0

  • Upgraded dependencies to Spring 5 and Spring Data 2
  • Removed deprecated net.javacrumbs.shedlock.provider.jedis.JedisLockProvider (use net.javacrumbs.shedlock.provider.redis.jedis.JedisLockProvide instead)
  • Removed deprecated SpringLockableTaskSchedulerFactory (use ScheduledLockConfigurationBuilder instead)

0.18.2

  • ablility to clean lock cache

0.18.1

  • shedlock-provider-redis-spring made compatible with spring-data-redis 1.x.x

0.18.0

  • Added shedlock-provider-redis-spring (thanks to @siposr)
  • shedlock-provider-jedis moved to shedlock-provider-redis-jedis

0.17.0

  • Support for SPEL in lock name annotation

0.16.1

  • Automatically closing TaskExecutor on Spring shutdown

0.16.0

  • Removed spring-test from shedlock-spring compile time dependencies
  • Added Automatic-Module-Names

0.15.1

  • Hazelcast works with remote cluster

0.15.0

  • Fixed ScheduledLockConfigurationBuilder interfaces #32
  • Hazelcast code refactoring

0.14.0

  • Support for Hazelcast (thanks to @peyo)

0.13.0

  • Jedis constructor made more generic (thanks to @mgrzeszczak)

0.12.0

  • Support for property placeholders in annotation lockAtMostForString/lockAtLeastForString
  • Support for composed annotations
  • ScheduledLockConfigurationBuilder introduced (deprecating SpringLockableTaskSchedulerFactory)

0.11.0

  • Support for Redis (thanks to @clamey)
  • Checking that lockAtMostFor is in the future
  • Checking that lockAtMostFor is larger than lockAtLeastFor

0.10.0

  • jdbc-template-provider does not participate in task transaction

0.9.0

  • Support for @SchedulerLock annotations on proxied classes

0.8.0

  • LockableTaskScheduler made AutoClosable so it's closed upon Spring shutdown

0.7.0

  • Support for lockAtLeastFor

0.6.0

  • Possible to configure defaultLockFor time so it does not have to be repeated in every annotation

0.5.0

  • ZooKeeper nodes created under /shedlock by default

0.4.1

  • JdbcLockProvider insert does not fail on DataIntegrityViolationException

0.4.0

  • Extracted LockingTaskExecutor
  • LockManager.executeIfNotLocked renamed to executeWithLock
  • Default table name in JDBC lock providers

0.3.0

  • @ShedlulerLock.name made obligatory
  • @ShedlulerLock.lockForMillis renamed to lockAtMostFor
  • Adding plain JDBC LockProvider
  • Adding ZooKeepr LockProvider
Comments
  • Better insert statement for MySQL

    Better insert statement for MySQL

    @lukas-krecan Syntax error has been corrected, can you please check it now

    Mysql update on conflict syntax works as below

    INSERT INTO shedlock(name,lock_until,locked_at,locked_by) VALUES('shedlock', '2022-09-05 11:58:52.059', '2022-09-05 12:58:52.059','admin') ON DUPLICATE KEY UPDATE lock_until = '2022-10-31 11:58:52.059', locked_at= '2022-10-31 12:58:52.059', locked_by='Iadmin';

    MySql reference link -

    https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

    opened by onlinemd 16
  • RedisFactoryLockProvider impl

    RedisFactoryLockProvider impl

    #47 for this issue. For this implementation you need SpringBoot.

    Configuration is pretty same as the Jedis version but it uses RedisConnectionFactory instead of JedisPool.

    opened by ghost 13
  • HazelcastLockProvider deadlock

    HazelcastLockProvider deadlock

    HazelcastLockProvider is using IMap.lock(lockname) to lock map key entry and releases it in finally block. But if something happens (i.e. instance that obtained lock dies) before it call IMap.unlock(lockname) then structure will stay locked and all other instances that will try obtain lock will wait for possibility to acquire lock.

    Solution to this is could be using IMap.lock(lockName, leaseTime, timeUint) that allows to set TTL for the lock on map key entry.

    In Hazelcast log it results with information like this:

    java.lang.IllegalMonitorStateException: Current thread is not owner of the lock! -> Owner: a408fed4-77c7-4552-9143-6220039c5e84, thread ID: 116#012#011at com.hazelcast.concurrent.lock.operations.UnlockOperation.unlock(UnlockOperation.java:75)#012#011at com.hazelcast.concurrent.lock.operations.UnlockOperation.run(UnlockOperation.java:64)#012#011at com.hazelcast.spi.Operation.call(Operation.java:170)#012#011at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:208)#012#011at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:197)#012#011at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:413)#012#011at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:153)#012#011at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:123)#012#011at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:110)#012java.lang.IllegalMonitorStateException: Current thread is not owner of the lock! -> Owner: a408fed4-77c7-4552-9143-6220039c5e84, thread ID: 116

    And all workers using Shedlock are disabled with stacktrace:

    sun.misc.Unsafe . park (Unsafe.java) (Native) java.util.concurrent.locks.LockSupport . park (LockSupport.java:304) com.hazelcast.spi.impl.AbstractInvocationFuture . get (AbstractInvocationFuture.java:156) com.hazelcast.client.spi.ClientProxy . invokeOnPartition (ClientProxy.java:153) com.hazelcast.client.spi.ClientProxy . invoke (ClientProxy.java:147) com.hazelcast.client.proxy.ClientMapProxy . lock (ClientMapProxy.java:571) com.hazelcast.client.proxy.ClientMapProxy . lock (ClientMapProxy.java:562) net.javacrumbs.shedlock.provider.hazelcast.HazelcastLockProvider . lock (HazelcastLockProvider.java:76) net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor . executeWithLock (DefaultLockingTaskExecutor.java:38) some.package.TaskProcessor . executeUnderLock (TaskProcessor.java:79)

    I can open an PR to fix it.

    opened by HubertTatar 12
  • Datasource missing in TestNG/H2

    Datasource missing in TestNG/H2

    We are using Shedlock 2.2 JDBCTemplate lock provider along with Spring boot 2/ testNG. It works fine in non test profiles with Mysql.

    However when the QA collegue start testing with TestNG/embedded H2, the autowired DataSource used in our original testNG test to create tables before test becomes null. The log doesn't show anything meaningful. But with @EnableSchedulerLock commented and it works again. Strangely, debugging shows that JDBCTemplate receives the data source just fine.

    I am not very good with Spring boot auto configuration details. So any clues how would the test datasource be affected?

    I will get the code later.

    opened by acxlam 11
  • ShedLock failed to recover

    ShedLock failed to recover

    Describe the bug

    1. Which version do you use - shedlock-spring:4.25.0
    2. Which Lock Provider - shedlock-provider-jdbc-template:4.25.0

    Hello, we have been using the ShedLock for 5 months without any issues. However, last week we encountered a database (CockroachDB) outage that took about 6 minutes. After the database was restored the ShedLock failed to recover. It just stopped trying to retry the query.

    Do you have any idea what may have prevented the ShedLock from being restored?

    Exception during the outage:

    com.service.locks.CustomLockProvider Releasing lock watchJobs_schedulerLock
    Jan 28 05:48:56  	org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [UPDATE shedlock SET lock_until = ? WHERE name = ?]; SQL state [XXUUU]; error code [0]; ERROR: remote wall time is too far ahead (582.23817ms) to be trustworthy; nested exception is org.postgresql.util.PSQLException: ERROR: remote wall time is too far ahead (582.23817ms) to be trustworthy
    Jan 28 05:48:56 	Caused by: org.postgresql.util.PSQLException: ERROR: remote wall time is too far ahead (582.23817ms) to be trustworthy
    ...
    Jan 28 05:50:52	Caused by: org.postgresql.util.PSQLException: ERROR: remote wall time is too far ahead (664.529504ms) to be trustworthy
    

    Full log:

    Jan 28 05:50:46  [thread-1] org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler Unexpected error occurred in scheduled task
    Jan 28 05:50:46  org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [UPDATE shedlock SET lock_until = ?, locked_at = ?, locked_by = ? WHERE name = ? AND lock_until <= ?]; SQL state [XXUUU]; error code [0]; ERROR: remote wall time is too far ahead (663.496474ms) to be trustworthy; nested exception is org.postgresql.util.PSQLException: ERROR: remote wall time is too far ahead (663.496474ms) to be trustworthy
    org.springframework.jdbc.UncategorizedSQLException
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1542)
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:667)
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:960)
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:981)
    Jan 28 05:50:46  at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:328)
    Jan 28 05:50:46  at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:333)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.lambda$execute$0(JdbcTemplateStorageAccessor.java:111)
    Jan 28 05:50:46  at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.execute(JdbcTemplateStorageAccessor.java:111)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.updateRecord(JdbcTemplateStorageAccessor.java:77)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.support.StorageBasedLockProvider.doLock(StorageBasedLockProvider.java:91)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.support.StorageBasedLockProvider.lock(StorageBasedLockProvider.java:65)
    Jan 28 05:50:46  at com.my.package.service.locks.CustomLockProvider.lock(CustomLockProvider.java:34)
    Jan 28 05:50:46  at jdk.internal.reflect.GeneratedMethodAccessor86.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    Jan 28 05:50:46  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
    Jan 28 05:50:46  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
    Jan 28 05:50:46  at com.sun.proxy.$Proxy115.lock(Unknown Source)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor.executeWithLock(DefaultLockingTaskExecutor.java:63)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.spring.aop.MethodProxyScheduledLockAdvisor$LockingInterceptor.invoke(MethodProxyScheduledLockAdvisor.java:86)
    Jan 28 05:50:46  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    Jan 28 05:50:46  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    Jan 28 05:50:46  at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    Jan 28 05:50:46  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    Jan 28 05:50:46  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    Jan 28 05:50:46  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
    Jan 28 05:50:46  at com.my.package.service.monitoring.DataJobMonitor$$EnhancerBySpringCGLIB$$46c5c2fc.watchJobs(<generated>)
    Jan 28 05:50:46  at jdk.internal.reflect.GeneratedMethodAccessor84.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    Jan 28 05:50:46  at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
    Jan 28 05:50:46  at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    Jan 28 05:50:46  at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    Jan 28 05:50:46  at java.base/java.lang.Thread.run(Unknown Source)
    Jan 28 05:50:46  Caused by: org.postgresql.util.PSQLException: ERROR: remote wall time is too far ahead (663.496474ms) to be trustworthy
    Jan 28 05:50:46  at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2552)
    Jan 28 05:50:46  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2284)
    Jan 28 05:50:46  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:322)
    Jan 28 05:50:46  at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
    Jan 28 05:50:46  at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
    Jan 28 05:50:46  at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
    Jan 28 05:50:46  at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:130)
    Jan 28 05:50:46  at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
    Jan 28 05:50:46  at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.lambda$update$2(JdbcTemplate.java:965)
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651)
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:960)
    Jan 28 05:50:46  at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:981)
    Jan 28 05:50:46  at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:328)
    Jan 28 05:50:46  at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:333)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.lambda$execute$0(JdbcTemplateStorageAccessor.java:111)
    Jan 28 05:50:46  at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.execute(JdbcTemplateStorageAccessor.java:111)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.updateRecord(JdbcTemplateStorageAccessor.java:77)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.support.StorageBasedLockProvider.doLock(StorageBasedLockProvider.java:91)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.support.StorageBasedLockProvider.lock(StorageBasedLockProvider.java:65)
    Jan 28 05:50:46  at com.my.package.service.locks.CustomLockProvider.lock(CustomLockProvider.java:34)
    Jan 28 05:50:46  at jdk.internal.reflect.GeneratedMethodAccessor86.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    Jan 28 05:50:46  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
    Jan 28 05:50:46  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
    Jan 28 05:50:46  at com.sun.proxy.$Proxy115.lock(Unknown Source)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor.executeWithLock(DefaultLockingTaskExecutor.java:63)
    Jan 28 05:50:46  at net.javacrumbs.shedlock.spring.aop.MethodProxyScheduledLockAdvisor$LockingInterceptor.invoke(MethodProxyScheduledLockAdvisor.java:86)
    Jan 28 05:50:46  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    Jan 28 05:50:46  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    Jan 28 05:50:46  at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    Jan 28 05:50:46  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    Jan 28 05:50:46  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    Jan 28 05:50:46  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
    Jan 28 05:50:46  at com.my.package.service.monitoring.DataJobMonitor$$EnhancerBySpringCGLIB$$46c5c2fc.watchJobs(<generated>)
    Jan 28 05:50:46  at jdk.internal.reflect.GeneratedMethodAccessor84.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    Jan 28 05:50:46  at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    Jan 28 05:50:46  at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
    Jan 28 05:50:46  at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    Jan 28 05:50:46  at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    Jan 28 05:50:46  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    Jan 28 05:50:46  at java.base/java.lang.Thread.run(Unknown Source)
    Jan 28 05:50:47  [thread-1] org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler Unexpected error occurred in scheduled task
    Jan 28 05:50:47  org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [UPDATE shedlock SET lock_until = ?, locked_at = ?, locked_by = ? WHERE name = ? AND lock_until <= ?]; SQL state [XXUUU]; error code [0]; ERROR: remote wall time is too far ahead (663.071882ms) to be trustworthy; nested exception is org.postgresql.util.PSQLException: ERROR: remote wall time is too far ahead (663.071882ms) to be trustworthy
    org.springframework.jdbc.UncategorizedSQLException
    Jan 28 05:50:47  at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1542)
    Jan 28 05:50:47  at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:667)
    Jan 28 05:50:47  at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:960)
    Jan 28 05:50:47  at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:981)
    Jan 28 05:50:47  at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:328)
    Jan 28 05:50:47  at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:333)
    Jan 28 05:50:47  at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.lambda$execute$0(JdbcTemplateStorageAccessor.java:111)
    Jan 28 05:50:47  at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    
    opened by mivanov1988 10
  • https://github.com/lukas-krecan/ShedLock/issues/366 added provider fo…

    https://github.com/lukas-krecan/ShedLock/issues/366 added provider fo…

    Implemented a provider for etcd like requested by @goudai in https://github.com/lukas-krecan/ShedLock/issues/366.

    Note that etcds leases only support TTLs in seconds, therefore the integration tests needed some adjustments for this provider.

    opened by grofoli 10
  • Shedlock 4.0.0 locks schedule but does not execute

    Shedlock 4.0.0 locks schedule but does not execute

    Read the documentation Read the documentation, especially the troubleshooting section.

    Describe the bug

    1. shedlock v4.0.0
    2. shedlock-provider-jdbc-template v4.0.0
    3. Config:
    @Configuration
    @EnableScheduling
    @EnableSchedulerLock(defaultLockAtMostFor = "30s")
    public class SchedulingConfiguration {
        @Bean
        public TaskScheduler taskScheduler() {
            return new ConcurrentTaskScheduler();
        }
    
        @Bean
        public LockProvider lockProvider(DataSource dataSource) {
            // specify SCHEMA.tableName to prevent 'table or view does not exist' for database user with permissions
            return new JdbcTemplateLockProvider(dataSource, "SCHEMA_NAME.shedlock");
        }
    }
    

    Implementation:

    @Component
    public class SomeImplementingService {
        @Scheduled(cron = "${cron}")
        @SchedulerLock(name = "uniqueName", lockAtLeastFor = "1m", lockAtMostFor = "15m")
        @Transactional
        public void scheduledMethod() {
            someMethod.performAction();
            // includes log line
        }
    }
    
    1. ShedLock logs n/a but I have application logs
    2019-12-04 17:16:00,004 [pool-5-thread-1] DEBUG org.springframework.beans.factory.support.AbstractBeanFactory Returning cached instance of singleton bean 'lockProvider'
    2019-12-04 17:16:00,005 [pool-5-thread-1] DEBUG org.springframework.jdbc.core.JdbcTemplate Executing prepared SQL statement [UPDATE SCHEMA.shedlock SET lock_until = ?, locked_at = ?, locked_by = ? WHERE name = ? AND lock_until <= ?]
    
    2019-12-04 17:16:00,010 [pool-5-thread-1] DEBUG net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor Locked 'uniqueName', lock will be held at most until 2019-12-04T16:31:00.004Z
    2019-12-04 17:16:00,011 [pool-5-thread-1] DEBUG org.springframework.beans.factory.support.AbstractBeanFactory Returning cached instance of singleton bean 'lockProvider'
    2019-12-04 17:16:00,011 [pool-5-thread-1] DEBUG org.springframework.jdbc.core.JdbcTemplate Executing prepared SQL statement [UPDATE SCHEMA.shedlock SET lock_until = ?, locked_at = ?, locked_by = ? WHERE name = ? AND lock_until <= ?]
    2019-12-04 17:16:00,012 [pool-5-thread-1] DEBUG XXX creating new proxy around given statement object: xyz.StatementDecoratorInterceptor$StatementProxy[Proxy=1291751840; Sql=UPDATE SCHEMA.shedlock SET lock_until = ?, locked_at = ?, locked_by = ? WHERE name = ? AND lock_until <= ?; Delegate=oracle.jdbc.driver.OraclePreparedStatementWrapper@6c95158b; Connection=DisposableConnectionFacade[null]]
    2019-12-04 17:16:00,014 [pool-5-thread-1] DEBUG net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor Not executing 'uniqueName'. It's locked.
    2019-12-04 17:16:00,014 [pool-5-thread-1] DEBUG org.springframework.jdbc.core.JdbcTemplate Executing prepared SQL statement [UPDATE SCHEMA.shedlock SET lock_until = ? WHERE name = ?]
    2019-12-04 17:16:00,015 [pool-5-thread-1] DEBUG XXX creating new proxy around given statement object: xyz.StatementDecoratorInterceptor$StatementProxy[Proxy=981941923; Sql=UPDATE SCHEMA.shedlock SET lock_until = ? WHERE name = ?; Delegate=oracle.jdbc.driver.OraclePreparedStatementWrapper@58dcda9a; Connection=DisposableConnectionFacade[null]]
    2019-12-04 17:16:00,018 [pool-5-thread-1] DEBUG net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor Task finished, lock 'uniqueName' will be released at 2019-12-04T16:17:00.004Z
    

    ... there is no mention of my scheduled task being executed. Application log line about activity is missing. Also I checked and the action is indeed not performed.

    Expected behavior My scheduled method performed its action and logs the result. Shedlock writes a lock + release time to database

    Actual behavior Shedlock prevents execution and instead logs Not executing 'uniqueName'. It's locked. However, Shedlock succesfully writes lock to database and afaik changes the end time after 'finishing' the task

    This is on a test environment with only one node active, so no concurrency here. I did not implement a ScheduledLockConfiguration because I understand that ScheduledLockConfigurationBuilder is deprecated. Should't shedlock intercept Spring's `ConcurrentTaskScheduler' automatically, or do I need to implement additional config?

    opened by maartenvanheek 10
  • Shedlock prevents Tomcat from graceful shutdown

    Shedlock prevents Tomcat from graceful shutdown

    When using Shedlock in a Spring Boot app run on external Tomcat, the Tomcat fails to shutdown gracefully and has to be killed.

    Steps to reproduce:

    1. Download Tomcat 8.5.45 from https://tomcat.apache.org/download-80.cgi and unzip
    2. Build the attached project and copy WAR file to webapps directory of previously extracted archive
    3. Change to a directory where Tomcat has been extracted
    4. Run the bin\startup.bat script and wait for the Tomcat to boot up
    5. Run the bin\shutdown.bat script

    It should get stuck and the last log seen should be like the one below:

    28-Aug-2019 16:14:04.995 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8009"]

    demo.zip

    opened by rgala 10
  • RedisConnectionFactory support

    RedisConnectionFactory support

    Hello there,

    People who use SpringBoot and Redis have some problem with your Redis-provider. SpringBoot gives us some nice and easy configuration with RedisConnectionFactory. This CF uses the same RedisPool inside the implementation but that is private so no way to get it. Instead it gives us RedisConnection.

    I created some nice implementation for your LockProvider interface. I can give it back to the community but I need some information about proper contributions here for that.

    Thanks in advance.

    opened by ghost 10
  • DataIntegrityViolationException instead of DuplicateKeyException

    DataIntegrityViolationException instead of DuplicateKeyException

    Hi,

    We are in the process of upgrading to Spring Boot 3 and see stacktraces in our logs that are caused by shedlock. It seems that Spring throws a DataIntegrityViolationException and not a DuplicateKeyException anymore. In our own code we made a workaround to also catch DataIntegrityViolationException and check if the message contains "Duplicate entry".

    When the message of the exception contains "Duplicate entry", the exception should be logged on DEBUG level and not ERROR.

    This is the stacktrace:

    org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [INSERT INTO shedlock(name, lock_until, locked_at, locked_by) VALUES(?, TIMESTAMPADD(MICROSECOND, ?, UTC_TIMESTAMP(3)), UTC_TIMESTAMP(3), ?)]; Duplicate entry 'updateAutomationCounts' for key 'shedlock.PRIMARY'
    	at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:87)
    	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70)
    	at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1539)
    	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:667)
    	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:960)
    	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:981)
    	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:328)
    	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:333)
    	at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.lambda$execute$0(JdbcTemplateStorageAccessor.java:117)
    	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    	at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.execute(JdbcTemplateStorageAccessor.java:117)
    	at net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateStorageAccessor.insertRecord(JdbcTemplateStorageAccessor.java:68)
    	at net.javacrumbs.shedlock.support.StorageBasedLockProvider.doLock(StorageBasedLockProvider.java:82)
    	at net.javacrumbs.shedlock.support.StorageBasedLockProvider.lock(StorageBasedLockProvider.java:65)
    	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:211)
    	at jdk.proxy2/jdk.proxy2.$Proxy215.lock(Unknown Source)
    	at net.javacrumbs.shedlock.core.DefaultLockingTaskExecutor.executeWithLock(DefaultLockingTaskExecutor.java:63)
    	at net.javacrumbs.shedlock.spring.aop.MethodProxyScheduledLockAdvisor$LockingInterceptor.invoke(MethodProxyScheduledLockAdvisor.java:86)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
    	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
    	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
    	at BatchingAutomationCounterScheduler$$SpringCGLIB$$0.updateCounts(<generated>)
    	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
    	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
    	at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:358)
    	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
    	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    	at java.base/java.lang.Thread.run(Thread.java:1589)
    Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'updateAutomationCounts' for key 'shedlock.PRIMARY'
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:555)
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:339)
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1061)
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1009)
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1320)
    	at software.aws.rds.jdbc.mysql.shading.com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:994)
    	at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
    	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
    	at org.springframework.jdbc.core.JdbcTemplate.lambda$update$2(JdbcTemplate.java:965)
    	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651)
    	... 34 common frames omitted
    
    opened by bdeneuter 9
  • Use shedlock-parent as BOM

    Use shedlock-parent as BOM

    Mainly references springdoc/springdoc-openapi#1405 Related to #431

    If I use this library then I should declare two dependencies like below:

    implementation 'net.javacrumbs.shedlock:shedlock-spring:4.35.0'
    implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template:4.35.0'
    

    But there are shedlock-parent artifact that can work as BOM so we can use like:

    implementation platform('net.javacrumbs.shedlock:shedlock-parent:4.36.0')
    implementation 'net.javacrumbs.shedlock:shedlock-spring'
    implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template'
    

    (Since I'm not using maven, I have no idea how maven users can utilize this functionality)

    Also, I think showing child artifacts in https://mvnrepository.com or somewhere is better than only in documents or searching for a single artifact from the repository.

    • Ref: https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi/1.6.3 (search for 'springdoc-openapi-' to see child artifacts)
    • Current: https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-parent/4.35.0
    opened by KENNYSOFT 9
  • #1284 Added SpEL support to @SchedulerLock name attribute

    #1284 Added SpEL support to @SchedulerLock name attribute

    This PR adds SpEL support to @SchedulerLock "name" attribute (#1284)

    I think it does not add much complexity to ShedLock.

    What do you think @lukas-krecan?

    opened by ipalbeniz 1
  • Support ArangoDB Driver 7.0

    Support ArangoDB Driver 7.0

    A first snapshot release of ArangoDB Java Driver version 7.0 has been published, see https://github.com/arangodb/arangodb-java-driver/releases/tag/v7.0.0-SNAPSHOT-1.

    Please keep in mind that this is a snapshot release. It is suited for testing purposes only and is NOT for production usage. It is solely meant to allow users and libraries maintainers trying out the new features and reviewing the API changes, before the general availability of the stable release.

    You might consider verifying if your project is compatible with it and can benefit from the new added features.

    Here you can find a detailed description of the new features and API changes: https://github.com/arangodb/arangodb-java-driver/blob/v7/docs

    Feedback and questions are welcome in our dedicated driverdev Slack channel (https://arangodb-community.slack.com/archives/C1R1A2TFC).

    -- Michele Rastelli Java Engineer ArangoDB GmbH

    opened by rashtao 0
  • SpEL referencing method parameter not working

    SpEL referencing method parameter not working

    Since 0.17.0 version ShedLock supports SpEL, but this is not working:

    @SchedulerLock(name = "{#hotelCode}", lockAtMostFor = "60s")
    public void printMessage(final String hotelCode, final String message) {
    ...
    }
    

    This is what we get in Redis: imagen

    Also tried withoud curly braces "{ }"

    opened by spekdrum 6
  • Bump mssql-jdbc from 11.2.1.jre11 to 12.1.0.jre11-preview

    Bump mssql-jdbc from 11.2.1.jre11 to 12.1.0.jre11-preview

    Bumps mssql-jdbc from 11.2.1.jre11 to 12.1.0.jre11-preview.

    Release notes

    Sourced from mssql-jdbc's releases.

    [11.2.1] HotFix & Stable Release

    Fixed issues

    • Made com.microsoft.azure:msal4j an optional dependency again 1893
    • Fixed query cancellation bug that intermittently occurs in batch queries 1897
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 1
  • More

    More "Kotlin Gotchas" with abstract classes

    I have some trouble with the ShedLock 4.43.0 in combination with Kotlin 1.7.22 and SpringBoot 2.7.6 (all latest versions) and JRE 11. The description in "Kotlin gotchas" in the documentation says "If @Scheduled annotation is not present, you have to open the method by yourself." - In my case the annotation was present but I still had to open the methods manually. This was necessary because the methods were in an "abstract class" but the @Scheduled in the derived class.

    Maybe it's worth mentioning in the Gotchas section.

    My example is in https://github.com/lathspell/spring_kotlin_abstract_bug and roughly:

      class Foo(something: Something): AbstractFoo(something) {
        @Scheduled...
        @SchedulerLock...
        fun cronjob() {...}
      }
    
      class AbstractFoo(private val something: Something) {
         fun save() { // here "something" is NULL although defined as not-nullable!
      }
    

    Originally I wanted to report this as a but to the "kotlin-spring" or Kotlin "all-open" plugin but then I noticed that the problem only occurs when using the @SchedulerLock annotation.

    Can you elaborate why this breaks the Spring CGI-proxy stuff? Is there maybe something that ShedLock could do better?

    It's pretty nasty when you have a working project, then add ShedLock and suddenly NullPointerExceptions turn up!

    opened by lathspell 2
  • Job not fired again after connection to database was lost

    Job not fired again after connection to database was lost

    Version: 4.42.0 Provider: JdbcTemplateLockProvider Config: @EnableSchedulerLock(defaultLockAtMostFor = "10m", defaultLockAtLeastFor = "10m")

    When connection to database is lost during a job run (and then re-established), it will not be triggered again, although the lock_until is in the past. ("n.j.s.core.DefaultLockingTaskExecutor Not executing 'xxxx'. It's locked.") After a restart (Spring Boot) it is triggered again as expected.

    opened by buschluschni 11
Owner
Lukáš Křečan
Lukáš Křečan
A distributed task scheduling framework

XXL-JOB XXL-JOB, a distributed task scheduling framework. -- Home Page -- Introduction XXL-JOB is a distributed task scheduling framework. It's core d

许雪里 23.3k Jan 9, 2023
ClockMonster is a self-hosted service for scheduling one-time or repeating jobs within your system

ClockMonster ClockMonster is a self-hosted service for scheduling one-time or repeating jobs within your system. Jobs for now are HTTP POST requests,

Scott Hiett 17 Dec 15, 2022
Tasks Planner : A minimalist collaborative app for scheduling and managing your tasks with the team and getting notifications through discord.

Tasks Planner ✨ Overview Tasks planner is a minimalist collaborative app for planning and managing your tasks with the team and get notifications thro

MILIARI Adnane 7 Dec 1, 2022
Distributed scheduled job framework

ElasticJob - distributed scheduled job solution Official website: https://shardingsphere.apache.org/elasticjob/ ElasticJob is a distributed scheduling

The Apache Software Foundation 7.8k Jan 5, 2023
A distributed lock that supports the use of Redis and Zookeeper, out of the box, fast and easy to use

lock-spring-boot-starter A distributed lock that supports the use of Redis and Zookeeper, out of the box, fast and easy to use 一款基于 Redis 和 Zookeeper

Pear Stack 9 Oct 15, 2022
Fetches the credentials for your August/Yale lock for use with AugustESP32 library

AugustLockCredentials Fetches the credentials for your August/Yale lock for use with AugustESP32 library. You can install from PlayStore or using the

James Brown 2 Sep 16, 2022
Oyvey skid with decent ca and pastebin hwid lock lmao

McDonald-1.1.7-Cracked It wasn't obfuscated so it isn't really a "crack", just had to remove the HWID authentication from the main class. Uhm, the gui

null 6 Dec 2, 2022
A CLI to lock the terminal while being afk.

LockCLI A CLI to lock the terminal while being afk. Usage: [lock, unlock] LockCLI from Source Have JDK 8+ Installed Compile main class and run in any

null 4 Dec 17, 2021
A small client useful for a variety of tasks ranging from raiding to duping.

CornClient A small utility mod for Minecraft useful for a variety of tasks ranging from raiding to duping. Support You can open an issue for help or f

Arilius Collection 115 Jan 4, 2022
Library for composability of interdependent non-blocking I/O tasks

Composer Composer helps you to organize and execute multiple interdependent asynchronous input/output tasks such as webservice calls, database read/wr

krupal 19 Oct 8, 2021
Force clear delaying & no longer needed Gradle tasks.

gradle-cleaner-intellij-plugin Force clear delaying & no longer needed Gradle tasks. Description Plugin for Intellij IDEA which performs simple comman

Kirill Biakov 26 Oct 28, 2021
tasks, async await, actors and channels for java

AsyncUtils tasks, async, await, actors and channels for java This project tries to explore several approaches to simplify async/concurrent programming

Michael Hoffer 6 Dec 1, 2022
A smart personal voice assistant powered by Alan AI. Enjoy hands free application that can manage daily tasks

Todogenix A smart personal voice assistant using Alan AI. Intro Todogenix is a personal assistant app powered by Alan AI that helps store and manage o

Venu Sai Madisetti 8 Mar 15, 2022
Automating cleanup, maintenance and troubleshooting tasks in Cloud Computing

Cloud Janitor Cloud Janitor is a tool to automate complex maintenance and troubleshooting tasks in cloud computing. It's built considering the securit

Caravana Cloud 79 Jan 6, 2023
Distributed and fault-tolerant realtime computation: stream processing, continuous computation, distributed RPC, and more

IMPORTANT NOTE!!! Storm has Moved to Apache. The official Storm git repository is now hosted by Apache, and is mirrored on github here: https://github

Nathan Marz 8.9k Dec 26, 2022
Your Software. Your Structures. Your Rules.

jQAssistant Master Repository We splitted jQAssistant in multiple single repositories to be able to build a better and more flexible build an release

null 179 Dec 19, 2022
Replicate your Key Value Store across your network, with consistency, persistance and performance.

Chronicle Map Version Overview Chronicle Map is a super-fast, in-memory, non-blocking, key-value store, designed for low-latency, and/or multi-process

Chronicle Software : Open Source 2.5k Dec 29, 2022