Class: RailsObservatory::RedisModel

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Attributes, ActiveModel::Model, ActiveModel::Serializers::JSON
Defined in:
lib/rails_observatory/models/redis_model.rb

Direct Known Subclasses

Error, JobTrace, MailDelivery, RequestTrace

Defined Under Namespace

Classes: NotFound

Constant Summary collapse

ATTRIBUTE_TYPE_TO_REDIS_TYPE =
{
  string: "TEXT",
  integer: "NUMERIC",
  float: "NUMERIC",
  boolean: "TAG"
}

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.compressed_attributesObject

Returns the value of attribute compressed_attributes.



15
16
17
# File 'lib/rails_observatory/models/redis_model.rb', line 15

def compressed_attributes
  @compressed_attributes
end

.indexed_attributesObject

Returns the value of attribute indexed_attributes.



14
15
16
# File 'lib/rails_observatory/models/redis_model.rb', line 14

def indexed_attributes
  @indexed_attributes
end

Class Method Details

.allObject



51
52
53
54
# File 'lib/rails_observatory/models/redis_model.rb', line 51

def self.all
  total, *results = redis.call("FT.SEARCH", index_name, '*', "SORTBY", "time", "DESC")
  Hash[*results].values.map(&:last).map { JSON.parse(_1) }.map { new(_1) }
end

.attribute(name, *args, indexed: true, compressed: false, **rest) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rails_observatory/models/redis_model.rb', line 18

def self.attribute(name, *args, indexed: true, compressed: false, **rest)
  if indexed
    self.indexed_attributes ||= []
    indexed_attributes << name
  end
  if compressed
    self.compressed_attributes ||= []
    compressed_attributes << name.to_s
  end
  super(name, *args, **rest)
end

.countObject



46
47
48
49
# File 'lib/rails_observatory/models/redis_model.rb', line 46

def self.count
  total, *results = redis.call("FT.SEARCH", index_name, '*', "SORTBY", "time", "DESC")
  total
end

.create_redis_indexObject



79
80
81
82
83
84
# File 'lib/rails_observatory/models/redis_model.rb', line 79

def self.create_redis_index
  schema = indexed_attributes.flat_map do |attr|
    ["$.#{attr}", "AS", "#{attr}", ATTRIBUTE_TYPE_TO_REDIS_TYPE[attribute_types[attr.to_s].type]]
  end
  redis.call("FT.CREATE", index_name, "ON", "JSON", "PREFIX", "1", key_prefix, "SCHEMA", *schema)
end

.ensure_indexObject



93
94
95
# File 'lib/rails_observatory/models/redis_model.rb', line 93

def self.ensure_index
  redis.call("FT._LIST").include?(index_name) || create_redis_index
end

.find(id) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/rails_observatory/models/redis_model.rb', line 56

def self.find(id)
  result = redis.call("JSON.GET", key_name(id), "$") || raise(NotFound, "Could not find #{name} with id #{id}")
  attrs = JSON.parse(result).first

  compressed_attributes.each do |attr|
    val = redis.call("GET", [key_prefix, attr].join("_")  + ":#{id}")
    attrs.merge!(attr => JSON.parse(Zlib.gunzip(val)))
  end

  self.new(attrs)
end

.index_infoObject



86
87
88
89
90
91
# File 'lib/rails_observatory/models/redis_model.rb', line 86

def self.index_info
  info = Hash[*redis.call("FT.INFO", index_name)]
  info['attributes'] = info['attributes'].map { Hash[*_1] }
  info['index_definition'] = Hash[*info['index_definition']]
  info
end

.index_nameObject



75
76
77
# File 'lib/rails_observatory/models/redis_model.rb', line 75

def self.index_name
  "#{key_prefix}-idx"
end

.key_name(id) ⇒ Object



42
43
44
# File 'lib/rails_observatory/models/redis_model.rb', line 42

def self.key_name(id)
  "#{key_prefix}:#{id}"
end

.key_prefixObject



38
39
40
# File 'lib/rails_observatory/models/redis_model.rb', line 38

def self.key_prefix
  name.demodulize.underscore
end

.redisObject



30
31
32
# File 'lib/rails_observatory/models/redis_model.rb', line 30

def self.redis
  Rails.configuration.rails_observatory.redis
end

Instance Method Details

#attribute_names_for_serializationObject



97
98
99
# File 'lib/rails_observatory/models/redis_model.rb', line 97

def attribute_names_for_serialization
  attributes.keys - self.class.compressed_attributes
end

#redisObject



34
35
36
# File 'lib/rails_observatory/models/redis_model.rb', line 34

def redis
  self.class.redis
end

#saveObject



101
102
103
104
105
106
107
108
109
# File 'lib/rails_observatory/models/redis_model.rb', line 101

def save
  redis.multi do |r|
    r.call("JSON.SET", self.class.key_name(id), "$", JSON.generate(as_json))
    self.class.compressed_attributes.each do |attr|
      compressed_value = Zlib.gzip(JSON.generate(@attributes.fetch_value(attr)), level: Zlib::BEST_COMPRESSION)
      r.call("SET", [self.class.key_prefix, attr].join("_")  + ":#{id}", compressed_value)
    end
  end
end