Class: AtprotoAuth::Storage::Redis

Inherits:
Interface
  • Object
show all
Defined in:
lib/atproto_auth/storage/redis.rb

Overview

Redis storage implementation

Defined Under Namespace

Classes: RedisError

Instance Method Summary collapse

Constructor Details

#initialize(redis_client: nil) ⇒ Redis

Returns a new instance of Redis.



12
13
14
15
# File 'lib/atproto_auth/storage/redis.rb', line 12

def initialize(redis_client: nil)
  super()
  @redis_client = redis_client || ::Redis.new
end

Instance Method Details

#acquire_lock(key, ttl:) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'lib/atproto_auth/storage/redis.rb', line 84

def acquire_lock(key, ttl:)
  validate_key!(key)
  validate_ttl!(ttl)

  lock_key = "atproto:locks:#{key}"
  @redis_client.set(lock_key, Time.now.to_i, nx: true, ex: ttl)
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to acquire lock: #{e.message}"
end

#delete(key) ⇒ Object



36
37
38
39
40
41
42
# File 'lib/atproto_auth/storage/redis.rb', line 36

def delete(key)
  validate_key!(key)

  @redis_client.del(key).positive?
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to delete value: #{e.message}"
end

#exists?(key) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
48
49
50
# File 'lib/atproto_auth/storage/redis.rb', line 44

def exists?(key)
  validate_key!(key)

  @redis_client.exists?(key)
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to check existence: #{e.message}"
end

#get(key) ⇒ Object



27
28
29
30
31
32
33
34
# File 'lib/atproto_auth/storage/redis.rb', line 27

def get(key)
  validate_key!(key)

  value = @redis_client.get(key)
  value.nil? || value == "" ? nil : value
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to get value: #{e.message}"
end

#multi_get(keys) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/atproto_auth/storage/redis.rb', line 52

def multi_get(keys)
  keys.each { |key| validate_key!(key) }

  values = @redis_client.mget(keys)
  result = {}

  # Only include non-nil values in result hash
  keys.zip(values).each do |key, value|
    next if value.nil? || value == ""

    result[key] = value
  end

  result
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to get multiple values: #{e.message}"
end

#multi_set(hash, ttl: nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/atproto_auth/storage/redis.rb', line 70

def multi_set(hash, ttl: nil)
  hash.each_key { |key| validate_key!(key) }
  validate_ttl!(ttl) if ttl

  @redis_client.multi do |tx|
    hash.each do |key, value|
      tx.set(key, value, ex: ttl)
    end
  end
  true
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to set multiple values: #{e.message}"
end

#release_lock(key) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/atproto_auth/storage/redis.rb', line 94

def release_lock(key)
  validate_key!(key)

  lock_key = "atproto:locks:#{key}"
  @redis_client.del(lock_key).positive?
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to release lock: #{e.message}"
end

#set(key, value, ttl: nil) ⇒ Object



17
18
19
20
21
22
23
24
25
# File 'lib/atproto_auth/storage/redis.rb', line 17

def set(key, value, ttl: nil)
  validate_key!(key)
  validate_ttl!(ttl) if ttl

  @redis_client.set(key, value, ex: ttl)
  true
rescue ::Redis::BaseError => e
  raise RedisError, "Failed to set value: #{e.message}"
end

#with_lock(key, ttl: 30) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/atproto_auth/storage/redis.rb', line 103

def with_lock(key, ttl: 30)
  raise ArgumentError, "Block required" unless block_given?

  acquired = acquire_lock(key, ttl: ttl)
  raise LockError, "Failed to acquire lock" unless acquired

  begin
    yield
  ensure
    release_lock(key)
  end
rescue ::Redis::BaseError => e
  raise RedisError, "Lock operation failed: #{e.message}"
end