Class: Kaal::Backend::SQLiteAdapter

Inherits:
Adapter
  • Object
show all
Includes:
DispatchLogging
Defined in:
lib/kaal/backend/sqlite_adapter.rb

Overview

Distributed backend adapter using any ActiveRecord-backed SQL database.

Despite the “SQLiteAdapter” name, this adapter works with any SQL database supported by Rails (SQLite, PostgreSQL, MySQL, etc.) via ActiveRecord. It stores locks in a database table with TTL-based expiration and uses a UNIQUE constraint on the key column to ensure atomicity.

Suitable for single-server or development environments. For production multi-node deployments, use Redis or PostgreSQL adapters instead.

Examples:

Using the adapter with any SQL database

Kaal.configure do |config|
  config.backend = Kaal::Backend::SQLiteAdapter.new
  config.enable_log_dispatch_registry = true  # Enable dispatch logging
end

Instance Method Summary collapse

Methods included from DispatchLogging

#log_dispatch_attempt, #parse_lock_key, parse_lock_key

Methods inherited from Adapter

#with_lock

Instance Method Details

#acquire(key, ttl) ⇒ Boolean

Attempt to acquire a distributed lock in the database.

Attempts to insert a new lock record. If the key already exists, cleans up any expired locks and retries once. This avoids unnecessary cleanup in the common case and reduces the window for race conditions.

Parameters:

  • key (String)

    the lock key

  • ttl (Integer)

    time-to-live in seconds

Returns:

  • (Boolean)

    true if acquired, false if held by another process



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/kaal/backend/sqlite_adapter.rb', line 64

def acquire(key, ttl)
  now = Time.current
  expires_at = now + ttl.seconds
  acquired = false
  attempt_cleanup = false

  2.times do
    Kaal::CronLock.cleanup_expired if attempt_cleanup
    begin
      Kaal::CronLock.create!(
        key: key,
        acquired_at: now,
        expires_at: expires_at
      )
      acquired = true
      break
    rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
      attempt_cleanup = true
    rescue ActiveRecord::StatementInvalid => e
      raise unless wrapped_contention_error?(e)

      attempt_cleanup = true
    end
  end

  log_dispatch_attempt(key) if acquired

  acquired
rescue StandardError => e
  raise LockAdapterError, "SQLite acquire failed for #{key}: #{e.message}"
end

#definition_registryKaal::Definition::DatabaseEngine

Get the definition registry for database-backed definition persistence.

Returns:



50
51
52
# File 'lib/kaal/backend/sqlite_adapter.rb', line 50

def definition_registry
  @definition_registry ||= Kaal::Definition::DatabaseEngine.new
end

#dispatch_registryKaal::Dispatch::DatabaseEngine

Get the dispatch registry for database logging.

Returns:



42
43
44
# File 'lib/kaal/backend/sqlite_adapter.rb', line 42

def dispatch_registry
  @dispatch_registry ||= Kaal::Dispatch::DatabaseEngine.new
end

#release(key) ⇒ Boolean

Release a previously acquired lock.

Parameters:

  • key (String)

    the lock key to release

Returns:

  • (Boolean)

    true if released (key existed and was deleted), false if not held



101
102
103
104
105
106
# File 'lib/kaal/backend/sqlite_adapter.rb', line 101

def release(key)
  deleted = Kaal::CronLock.where(key: key).delete_all
  deleted.positive?
rescue StandardError => e
  raise LockAdapterError, "SQLite release failed for #{key}: #{e.message}"
end