Class: SuperSettings::Storage::RedisStorage

Inherits:
StorageAttributes show all
Includes:
Transaction
Defined in:
lib/super_settings/storage/redis_storage.rb

Overview

Redis implementation of the SuperSettings::Storage model.

You must define the redis connection to use by setting the redis attribute on the class. This can either be a Redis object or a block that yields a Redis object. You can use the block form if you need to get the Redis object at runtime instead of having a static object.

You can also use the [connection_pool]() gem to provide a pool of Redis connecions for a multi-threaded application. The connection_pool gem is not a dependency of this gem, so you would need to add it to your application dependencies to use it.

Examples:

SuperSettings::Storage::RedisStorage.redis = Redis.new(url: ENV["REDIS_URL"])
SuperSettings::Storage::RedisStorage.redis = lambda { RedisClient.get(:settings) }
SuperSettings::Storage::RedisStorage.redis = ConnectionPool.new(size: 5) { Redis.new(url: ENV["REDIS_URL"]) }

Defined Under Namespace

Classes: HistoryStorage

Constant Summary collapse

SETTINGS_KEY =
"SuperSettings.settings"
UPDATED_KEY =
"SuperSettings.order_by_updated_at"

Class Attribute Summary collapse

Attributes inherited from StorageAttributes

#description, #key, #raw_value, #value_type

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Transaction

included, #persisted=, #persisted?, #save!

Methods inherited from StorageAttributes

#deleted=, #deleted?, #persisted=, #persisted?

Methods included from SuperSettings::Storage

#==, #create_history, #created_at=, #deleted=, #deleted?, #description, #description=, included, #key, #key=, #persisted?, #raw_value, #raw_value=, #save!, #updated_at=, #value_type, #value_type=

Constructor Details

#initializeRedisStorage

Returns a new instance of RedisStorage.



182
183
184
185
186
# File 'lib/super_settings/storage/redis_storage.rb', line 182

def initialize(*)
  @deleted = false
  @persisted = false
  super
end

Class Attribute Details

.redis=(value) ⇒ Object (writeonly)

Sets the attribute redis

Parameters:

  • value

    the value to set the attribute redis to.



136
137
138
# File 'lib/super_settings/storage/redis_storage.rb', line 136

def redis=(value)
  @redis = value
end

Class Method Details

.allObject



92
93
94
95
96
# File 'lib/super_settings/storage/redis_storage.rb', line 92

def all
  with_redis do |redis|
    redis.hgetall(SETTINGS_KEY).values.collect { |json| load_from_json(json) }
  end
end

.create_history(key:, changed_by:, created_at:, value: nil, deleted: false) ⇒ Object



121
122
123
# File 'lib/super_settings/storage/redis_storage.rb', line 121

def create_history(key:, changed_by:, created_at:, value: nil, deleted: false)
  HistoryStorage.create!(key: key, value: value, deleted: deleted, changed_by: changed_by, created_at: created_at)
end

.destroy_allObject



132
133
134
# File 'lib/super_settings/storage/redis_storage.rb', line 132

def destroy_all
  all.each(&:destroy)
end

.find_by_key(key) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/super_settings/storage/redis_storage.rb', line 113

def find_by_key(key)
  json = with_redis { |redis| redis.hget(SETTINGS_KEY, key) }
  return nil unless json

  record = load_from_json(json)
  record unless record.deleted?
end

.last_updated_atObject



125
126
127
128
129
130
# File 'lib/super_settings/storage/redis_storage.rb', line 125

def last_updated_at
  result = with_redis { |redis| redis.zrevrange(UPDATED_KEY, 0, 1, withscores: true).first }
  return nil unless result

  time_at_microseconds(result[1])
end

.microseconds(time) ⇒ Object



162
163
164
# File 'lib/super_settings/storage/redis_storage.rb', line 162

def microseconds(time)
  TimePrecision.new(time, :microsecond).to_f
end

.save_all(changes) ⇒ Object



147
148
149
150
151
152
153
154
155
156
# File 'lib/super_settings/storage/redis_storage.rb', line 147

def save_all(changes)
  with_redis do |redis|
    redis.multi do |multi_redis|
      changes.each do |object|
        object.save_to_redis(multi_redis)
      end
    end
  end
  true
end

.time_at_microseconds(time) ⇒ Object



158
159
160
# File 'lib/super_settings/storage/redis_storage.rb', line 158

def time_at_microseconds(time)
  TimePrecision.new(time, :microsecond).time
end

.updated_since(time) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/super_settings/storage/redis_storage.rb', line 98

def updated_since(time)
  min_score = microseconds(time)
  with_redis do |redis|
    keys = redis.zrangebyscore(UPDATED_KEY, min_score, "+inf")
    return [] if keys.empty?

    settings = []
    redis.hmget(SETTINGS_KEY, *keys).each do |json|
      setting = load_from_json(json) if json
      settings << setting if setting && setting.updated_at > time
    end
    settings
  end
end

.with_redis(&block) ⇒ Object



138
139
140
141
142
143
144
145
# File 'lib/super_settings/storage/redis_storage.rb', line 138

def with_redis(&block)
  connection = (@redis.is_a?(Proc) ? @redis.call : @redis)
  if defined?(ConnectionPool) && connection.is_a?(ConnectionPool)
    connection.with(&block)
  else
    block.call(connection)
  end
end

Instance Method Details

#created_atObject



209
210
211
# File 'lib/super_settings/storage/redis_storage.rb', line 209

def created_at
  self.class.time_at_microseconds(super)
end

#destroyObject



199
200
201
202
203
204
205
206
207
# File 'lib/super_settings/storage/redis_storage.rb', line 199

def destroy
  self.class.with_redis do |redis|
    redis.multi do |multi_redis|
      multi_redis.hdel(SETTINGS_KEY, key)
      multi_redis.zrem(UPDATED_KEY, key)
      HistoryStorage.destroy_all_by_key(key, multi_redis)
    end
  end
end

#history(limit: nil, offset: 0) ⇒ Object



188
189
190
191
192
# File 'lib/super_settings/storage/redis_storage.rb', line 188

def history(limit: nil, offset: 0)
  HistoryStorage.find_all_by_key(key: key, limit: limit, offset: offset).collect do |record|
    HistoryItem.new(key: key, value: record.value, changed_by: record.changed_by, created_at: record.created_at, deleted: record.deleted?)
  end
end

#save_to_redis(redis) ⇒ Object



194
195
196
197
# File 'lib/super_settings/storage/redis_storage.rb', line 194

def save_to_redis(redis)
  redis.hset(SETTINGS_KEY, key, payload_json)
  redis.zadd(UPDATED_KEY, self.class.microseconds(updated_at), key)
end

#updated_atObject



213
214
215
# File 'lib/super_settings/storage/redis_storage.rb', line 213

def updated_at
  self.class.time_at_microseconds(super)
end