Skip to content

evolution-gaming/cassandra-sync

Repository files navigation

cassandra-sync

Build Status Coverage Status Codacy Badge Version License: MIT

This tiny library provides mechanism of synchronization via locks stored in Cassandra table. This synchronization is especially useful for preventing concurrent schema changes. Sad that concurrent schema changes is not supported by Cassandra on it's own.

Concept

Basically this is a mutex implementation via records stored in cassandra. We insert record in order to acquire the lock and remove record when done. We also provide expiry duration per lock in case we failed to remove record. There is nice statement which ideally describes the concept.

Usage

def example(session: CassandraSession[IO]) = {
  for {
    cassandraSync <- CassandraSync.of(session, keyspace = "app")
    result        <- cassandraSync("id", expiry = 3.seconds, timeout = 10.seconds) {
      // put your code here 
      // the lock in cassandra per id will ensure that your code runs strictly sequentially
    }
  } yield result
}

Schema & queries

So you still need to create table to store locks there and better don't let app to do that, especially concurrently from different nodes. At Evolution Gaming this table is created along with keyspace creation by ops department.

CREATE TABLE IF NOT EXISTS keyspace.locks(
  id TEXT PRIMARY KEY,
  expiry_ms BIGINT,
  timestamp TIMESTAMP,
  metadata TEXT);

-- Acquire lock
INSERT INTO keyspace.locks (id, expiry_ms, timestamp, metadata) VALUES (?, ?, ?, ?)
  IF NOT EXISTS USING TTL ?;

-- Release lock
-- This DELETE should also be a LWT op as mixing LWT and normal ops is prohibited
DELETE FROM keyspace.locks WHERE id = ? IF EXISTS;

Setup

addSbtPlugin("com.evolution" % "sbt-artifactory-plugin" % "0.0.2")

libraryDependencies += "com.evolutiongaming" %% "cassandra-sync" % latestVersion