Distributed lock library in scala. based on mongodb (using reactivemongo or mongo-scala-driver)
consists of 3 modules:
- scalalock-api - contains the api and the locking logic
- scalalock-mongo - an api implementation using mongodb as the lock persistence store. implementation is dependant on mongo-scala-driver.
- scalalock-reactivemongo - an alternative api implementation using reactivemongo as the mongodb driver. implementation is dependant on reactivemongo.
- Add dependencies to build.sbt:
- Option A - if you're using mongo-scala-driver
libraryDependencies ++= Seq( "com.weirddev" %% "scalalock-api" % "1.0.6", "com.weirddev" %% "scalalock-mongo" % "1.0.6" ) 
- Option B - if you're using reactivemongo
libraryDependencies ++= Seq( "com.weirddev" %% "scalalock-api" % "1.0.6", "com.weirddev" %% "scalalock-reactivemongo" % "1.1.0" //for reactivemongo 1.* 
// "com.weirddev" %% "scalalock-reactivemongo" % "1.0.6" //for reactivemongo 0.* ) ```
- 
wrap the block that should be synchronized across all nodes in cluster with Lock#acquire()method call- For scalalock-mongo(based onmongo-scala-driver)
 import com.mongodb.ConnectionString import com.weirddev.scalalock.mongo.MongoDistributedLock import org.mongodb.scala.{MongoClient, MongoClientSettings, MongoDatabase} import scala.concurrent.Future import scala.concurrent.duration._ protected val db: MongoDatabase = MongoClient(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost:27017")) .build()).getDatabase("test") val distLock:Lock = new MongoDistributedLock(db) distLock.acquire("some_task_id", 10 minutes){ Future{ println("this block needs to execute in isolation across all application nodes in cluster") Thread.sleep(5000) "Task Completed" } } - Alternatively, using scalalock-reactivemongo(based onorg.reactivemongo)
 import com.weirddev.scalalock.reactivemongo.ReactiveMongoDistributedLock import reactivemongo.api.{DefaultDB, MongoConnection, MongoDriver} import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.concurrent.duration._ private val mongoUri: String = "mongodb://localhost:27017/test" val driver = new MongoDriver val database: Future[DefaultDB] = for { uri <- Future.fromTry(MongoConnection.parseURI(mongoUri)) con = driver.connection(uri) dn <- Future(uri.db.get) db <- con.database(dn) } yield db val distLock = new ReactiveMongoDistributedLock(database) distLock.acquire("some_task_id", 10 minutes){ Future{ println("this block needs to execute in isolation across all application nodes in cluster") Thread.sleep(5000) "Task Completed" } } - A simpler alternative using scalalock-reactivemongoin Play! Framework (add a dependency on reactivemongo play, i.e."org.reactivemongo" %% "play2-reactivemongo" % "0.16.5-play26")
 import com.weirddev.scalalock.reactivemongo.ReactiveMongoDistributedLock import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.duration._ import javax.inject.Inject import play.modules.reactivemongo.ReactiveMongoApi class MyRepository @Inject()(override val reactiveMongoApi: ReactiveMongoApi)(implicit val ec: ExecutionContext){ val distLock = new ReactiveMongoDistributedLock(reactiveMongoApi.database) distLock.acquire("some_task_id", 10 minutes){ Future{ println("this block needs to execute in isolation across all application nodes in cluster") Thread.sleep(5000) "Task Completed" } } } 
- For 
- 
If you want to use the lock to synchronize task execution globally in a cluster and mandating a minimal interval - pass the releaseLockWhenDoneasfalse. This will keep the lock state as LOCKED even after task completion. Effectively keeping the lock until expiration - as set by theexpireparam. example:val result = mongoDistLock.acquire(resourceId = "test_task", expire = 30 minutes,releaseLockWhenDone = false){ println("After this block finishes to execute, the lock will retain for 30 minutes before any other task using resource id - test_task - could run again") Thread.sleep(5000) "Done" } For other usage scenarios, review the integrative test code 
Welcomed :) - Please refer to CONTRIBUTING.md file.
Copyright (c) 2016 - 2024 WeirdDev. Licensed for free usage under the terms and conditions of Apache V2 - Apache V2 License.