Class: SimpleAcp::Storage::Redis

Inherits:
Base
  • Object
show all
Defined in:
lib/simple_acp/storage/redis.rb

Overview

Redis-backed storage for distributed deployments.

Stores data in Redis with configurable TTL for automatic expiration. Suitable for multi-process or multi-server deployments.

Examples:

storage = SimpleAcp::Storage::Redis.new(
  url: "redis://localhost:6379",
  ttl: 3600  # 1 hour
)
server = SimpleAcp::Server::Base.new(storage: storage)

Constant Summary collapse

DEFAULT_TTL =

Default TTL of 24 hours

86_400
KEY_PREFIX =

Default key prefix

"acp:"

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Redis

Initialize Redis storage.

Parameters:

  • options (Hash) (defaults to: {}) —

    configuration options

Options Hash (options):

  • :redis (Redis) —

    existing Redis connection

  • :url (String) —

    Redis URL (default: $REDIS_URL or localhost)

  • :ttl (Integer) —

    TTL in seconds (default: 86400)

  • :prefix (String) —

    key prefix (default: "acp:")

  • :host (String) —

    Redis host

  • :port (Integer) —

    Redis port

  • :db (Integer) —

    Redis database number

  • :password (String) —

    Redis password

  • :ssl (Boolean) —

    use SSL



35
36
37
38
39
40
# File 'lib/simple_acp/storage/redis.rb', line 35

def initialize(options = {})
  super
  @redis = options[:redis] || connect_redis(options)
  @ttl = options[:ttl] || DEFAULT_TTL
  @prefix = options[:prefix] || KEY_PREFIX
end

Instance Method Details

#add_event(run_id, event) ⇒ Object

See Also:



115
116
117
118
119
# File 'lib/simple_acp/storage/redis.rb', line 115

def add_event(run_id, event)
  @redis.rpush(events_key(run_id), event.to_json)
  @redis.expire(events_key(run_id), @ttl)
  event
end

#clear! ⇒ void

This method returns an undefined value.

Clear all stored data.



142
143
144
145
# File 'lib/simple_acp/storage/redis.rb', line 142

def clear!
  keys = @redis.keys("#{@prefix}*")
  @redis.del(*keys) unless keys.empty?
end

#close ⇒ Object

See Also:



128
129
130
# File 'lib/simple_acp/storage/redis.rb', line 128

def close
  @redis.close if @redis.respond_to?(:close)
end

#delete_run(run_id) ⇒ Object

See Also:



66
67
68
69
70
71
72
73
74
# File 'lib/simple_acp/storage/redis.rb', line 66

def delete_run(run_id)
  run = get_run(run_id)
  return unless run

  @redis.del(run_key(run_id))
  @redis.del(events_key(run_id))
  @redis.srem(agent_runs_key(run.agent_name), run_id)
  @redis.srem(session_runs_key(run.session_id), run_id) if run.session_id
end

#delete_session(session_id) ⇒ Object



110
111
112
# File 'lib/simple_acp/storage/redis.rb', line 110

def delete_session(session_id)
  @redis.del(session_key(session_id))
end

#get_events(run_id, limit: 100, offset: 0) ⇒ Object

See Also:



122
123
124
125
# File 'lib/simple_acp/storage/redis.rb', line 122

def get_events(run_id, limit: 100, offset: 0)
  events_data = @redis.lrange(events_key(run_id), offset, offset + limit - 1)
  events_data.map { |data| Models::Events.from_hash(JSON.parse(data)) }
end

#get_run(run_id) ⇒ Object

See Also:



43
44
45
46
47
48
# File 'lib/simple_acp/storage/redis.rb', line 43

def get_run(run_id)
  data = @redis.get(run_key(run_id))
  return nil unless data

  Models::Run.from_hash(JSON.parse(data))
end

#get_session(session_id) ⇒ Object

See Also:



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

def get_session(session_id)
  data = @redis.get(session_key(session_id))
  return nil unless data

  Models::Session.from_hash(JSON.parse(data))
end

#list_runs(agent_name: nil, session_id: nil, limit: 10, offset: 0) ⇒ Object

See Also:



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/simple_acp/storage/redis.rb', line 77

def list_runs(agent_name: nil, session_id: nil, limit: 10, offset: 0)
  run_ids = if agent_name
              @redis.smembers(agent_runs_key(agent_name))
            elsif session_id
              @redis.smembers(session_runs_key(session_id))
            else
              @redis.keys("#{@prefix}run:*").map { |k| k.sub("#{@prefix}run:", "") }
            end

  runs = run_ids.filter_map { |id| get_run(id) }
  runs = runs.sort_by { |r| r.created_at || Time.at(0) }.reverse

  {
    runs: runs.drop(offset).take(limit),
    total: runs.length
  }
end

#ping ⇒ Object

See Also:



133
134
135
136
137
# File 'lib/simple_acp/storage/redis.rb', line 133

def ping
  @redis.ping == "PONG"
rescue StandardError
  false
end

#save_run(run) ⇒ Object

See Also:



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/simple_acp/storage/redis.rb', line 51

def save_run(run)
  @redis.setex(run_key(run.run_id), @ttl, run.to_json)

  # Index by agent name
  @redis.sadd(agent_runs_key(run.agent_name), run.run_id)

  # Index by session if present
  if run.session_id
    @redis.sadd(session_runs_key(run.session_id), run.run_id)
  end

  run
end

#save_session(session) ⇒ Object

See Also:



104
105
106
107
# File 'lib/simple_acp/storage/redis.rb', line 104

def save_session(session)
  @redis.setex(session_key(session.id), @ttl, session.to_json)
  session
end