Akka Coordination Lease implementation using Redis and Redlock algorithm.
The library is currently compatible with Akka 2.5.22 and 2.5.23. It is tested with 2 use cases built-in into Akka:
- 
Cluster Singletons (implemented in
ClusterSingletonManagerSettings) - 
Cluster Sharding (implemented in
Shard). 
Add akka-coordination-redis to sbt dependencies:
libraryDependencies ++= Seq(
  "com.github.nstojiljkovic" %% "akka-coordination-redis" % "0.3.1"
)Sample configuration using 5 Redis servers, with minimum amount of locks set to 4:
redisson-red-lock-lease {
  # reference to the lease implementation class
  lease-class = "com.nikolastojiljkovic.akka.coordination.lease.RedissonRedLockLease"
  # if the node that acquired the leases crashes, how long should the lease be held before another owner can get it
  heartbeat-timeout = 120s
  # interval for communicating with the third party to confirm the lease is still held
  heartbeat-interval = 12s
  # interval to time out after acquire and release calls or document
  lease-operation-timeout = 5s
  # minimum number of (single) locks required, defaults to N / 2 + 1 if not defined
  min-locks-amount = 4
  # custom dispatcher to use, defaults to actor system default dispatcher if not specified
  dispatcher = custom-dispatcher
  # common configuration option, not used directly by RedissonRedLockLease
  default-server {
    singleServerConfig {
      address = "redis://10.10.11.40:6379"
      connectionMinimumIdleSize = 8
      connectionPoolSize = 16
    }
    threads = 64
    nettyThreads = 64
    transportMode = NIO
    transportMode = NIO
  }
  # list of servers
  servers = [
    ${redisson-red-lock-lease.default-server} {singleServerConfig.address = "redis://10.10.11.40:6379"},
    ${redisson-red-lock-lease.default-server} {singleServerConfig.address = "redis://10.10.11.41:6379"},
    ${redisson-red-lock-lease.default-server} {singleServerConfig.address = "redis://10.10.11.42:6379"},
    ${redisson-red-lock-lease.default-server} {singleServerConfig.address = "redis://10.10.11.43:6379"},
    ${redisson-red-lock-lease.default-server} {singleServerConfig.address = "redis://10.10.11.44:6379"}
  ]
}If min-locks-amount is not configured it will be calculated as N / 2 + 1 where N is the number of configured Redis servers.
The default-server from the above sample is just used to copy the common configuration to each of the configured servers.
Each of the servers in the servers array accepts any of the configuration options as per
JSON/YAML based Redisson configuration. You should also probably take special
care when configuring the Redisson thread and connection pools.
There's also an option to specify custom execution context used by RedissonRedLockLease (which is completely separate
from the Redisson thread pool) using the dispatcher configuration option. It should point to the name of a custom Akka
dispatcher, configured as per Akka official documentation.
The lease-class, heartbeat-timeout, heartbeat-interval and lease-operation-timeout configuration options all come from
Akka Coordination Lease API.
Redisson is used as a Redis client library. However, Redisson's RedLock implementation does not map 1:1 to Akka Lease API. Notable changes and tweaks are listed bellow:
- 
RedissonRedLock is Redis based distributed reentrant Lock object for Java and implements
java.util.concurrent.locks.Lockinterface. It means that only lock owner thread can unlock it otherwiseIllegalMonitorStateExceptionwould be thrown. On the other hand, Akka Coordination Lease API has configurable owner (without locking the leases to threads) soakka-coordination-redisimplementation uses custom internalRedissonLockWithCustomOwnerAndFixedLeaseTime. It does not comply with the Java lock specification and is therefore marked private. That also means that you should, as per Akka Coordination specification, take special care when picking up a lease name that will be unique for your use case. - 
RedissonRedLock has bunch of functions which throw
UnsupportedOperationException(and which would otherwise be useful for implementing Akka Coordination Lease). Theakka-coordination-redislibrary has custom logic implemented inRedissonRedLockLeaseto overcome the missing functionality from Redisson RedLock implementation.- 
Akka allows to specify both
heartbeat-timeoutandheartbeat-interval. Redisson allows to specifylockWatchdogTimeout(which maps to Akka'sheartbeat-timeoutfor locks withleastTimeset to -1), but theheartbeat-intervalis then locked to 1/3 oflockWatchdogTimeout(hardcoded in a private method inRedissonLock). In order to fully allow Akka'sheartbeat-intervalsetting,RedissonRedLockLeasedoes not use Redisson's watchdog, but instead renews the lease itself. - 
It is assumed that every server configured for each of the (single) locks constituting a distributed RedLock will be actually a single Redis server (though that is not a requirement).
RedissonRedLockLeaselistens for disconnects from each of the configured servers and opts to mark lease as lost on any server disconnect. So if you have anything besidessingleServerConfigas a single lock server (for example Redis cluster), note that acquired leases will be marked as lost if any of the cluster servers goes down. 
 - 
 
Please feel free to create a new pull request for each change or bug fix. Make sure that all of the changes are covered using tests. You can run the full suite of tests using sbt:
> testOnly com.nikolastojiljkovic.akka.coordination.lease.*
See the LICENSE file for details.