Class: Picky::Backends::Redis
- Defined in:
- lib/picky/backends/redis.rb,
lib/picky/backends/redis/list.rb,
lib/picky/backends/redis/basic.rb,
lib/picky/backends/redis/float.rb,
lib/picky/backends/redis/string.rb,
lib/picky/backends/redis/directly_manipulable.rb
Defined Under Namespace
Modules: DirectlyManipulable, NonScripting, Scripting Classes: Basic, Float, List, String
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#realtime ⇒ Object
readonly
Returns the value of attribute realtime.
Class Method Summary collapse
Instance Method Summary collapse
-
#at_least_version(major_minor_patch, should_be) ⇒ Object
Compares two versions each in an array [major, minor, patch] format and returns true if the first version is higher or the same as the second one.
-
#check_hiredis_gem ⇒ Object
It’s ok.
-
#check_redis_gem ⇒ Object
It’s ok, the next check will fail if this one does.
-
#create_configuration(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to: [:key] # => value (a value for this config key).
-
#create_inverted(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to: [:token] # => [id, id, id, id, id] (an array of ids).
-
#create_realtime(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to: [id] # => [:sym1, :sym2].
-
#create_similarity(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to: [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to).
-
#create_weights(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to: [:token] # => 1.23 (a weight).
-
#generate_intermediate_result_id ⇒ Object
Use the host and pid (generated lazily in child processes) for the result.
- #host ⇒ Object
- #identifiers_for(combinations) ⇒ Object
-
#ids(combinations, amount, offset) ⇒ Object
Returns the result ids for the allocation.
-
#initialize(options = {}) ⇒ Redis
constructor
A new instance of Redis.
- #maybe_load_hiredis ⇒ Object
- #pid ⇒ Object
-
#redis_version ⇒ Object
Returns an array describing the current Redis version.
-
#redis_with_scripting? ⇒ Boolean
Does the Redis version already include scripting support?.
-
#weight(combinations) ⇒ Object
Returns the total weight for the combinations.
Methods inherited from Backend
Constructor Details
#initialize(options = {}) ⇒ Redis
Returns a new instance of Redis.
12 13 14 15 16 17 18 19 |
# File 'lib/picky/backends/redis.rb', line 12 def initialize = {} maybe_load_hiredis check_hiredis_gem check_redis_gem @client = [:client] || ::Redis.new(:db => ([:db] || 15)) @realtime = [:realtime] end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
9 10 11 |
# File 'lib/picky/backends/redis.rb', line 9 def client @client end |
#realtime ⇒ Object (readonly)
Returns the value of attribute realtime.
9 10 11 |
# File 'lib/picky/backends/redis.rb', line 9 def realtime @realtime end |
Class Method Details
.extract_host ⇒ Object
199 200 201 |
# File 'lib/picky/backends/redis.rb', line 199 def self.extract_host @host ||= Socket.gethostname end |
Instance Method Details
#at_least_version(major_minor_patch, should_be) ⇒ Object
Compares two versions each in an array [major, minor, patch] format and returns true if the first version is higher or the same as the second one. False if not.
Note: Destructive.
80 81 82 83 |
# File 'lib/picky/backends/redis.rb', line 80 def at_least_version major_minor_patch, should_be 3.times { return false if major_minor_patch.shift < should_be.shift } true end |
#check_hiredis_gem ⇒ Object
It’s ok.
25 26 27 28 29 |
# File 'lib/picky/backends/redis.rb', line 25 def check_hiredis_gem require 'redis/connection/hiredis' rescue LoadError # It's ok, the next check will fail if this one does. end |
#check_redis_gem ⇒ Object
It’s ok, the next check will fail if this one does.
30 31 32 33 34 |
# File 'lib/picky/backends/redis.rb', line 30 def check_redis_gem require 'redis' rescue LoadError => e warn_gem_missing 'redis', 'the Redis client' end |
#create_configuration(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to:
[:key] # => value (a value for this config key)
57 58 59 |
# File 'lib/picky/backends/redis.rb', line 57 def create_configuration bundle, _ = nil String.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:configuration", realtime: realtime end |
#create_inverted(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to:
[:token] # => [id, id, id, id, id] (an array of ids)
39 40 41 |
# File 'lib/picky/backends/redis.rb', line 39 def create_inverted bundle, _ = nil List.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:inverted", realtime: realtime end |
#create_realtime(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to:
[id] # => [:sym1, :sym2]
63 64 65 |
# File 'lib/picky/backends/redis.rb', line 63 def create_realtime bundle, _ = nil List.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:realtime", realtime: realtime end |
#create_similarity(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to:
[:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
51 52 53 |
# File 'lib/picky/backends/redis.rb', line 51 def create_similarity bundle, _ = nil List.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:similarity", realtime: realtime end |
#create_weights(bundle, _ = nil) ⇒ Object
Returns an object that on #initial, #load returns an object that responds to:
[:token] # => 1.23 (a weight)
45 46 47 |
# File 'lib/picky/backends/redis.rb', line 45 def create_weights bundle, _ = nil Float.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:weights", realtime: realtime end |
#generate_intermediate_result_id ⇒ Object
Use the host and pid (generated lazily in child processes) for the result.
211 212 213 |
# File 'lib/picky/backends/redis.rb', line 211 def generate_intermediate_result_id @intermediate_result_id ||= "#{host}:#{pid}:picky:result" end |
#host ⇒ Object
202 203 204 |
# File 'lib/picky/backends/redis.rb', line 202 def host self.class.extract_host end |
#identifiers_for(combinations) ⇒ Object
215 216 217 218 219 |
# File 'lib/picky/backends/redis.rb', line 215 def identifiers_for combinations combinations.inject([]) do |identifiers, combination| identifiers << "#{PICKY_ENVIRONMENT}:#{combination.identifier}" end end |
#ids(combinations, amount, offset) ⇒ Object
Returns the result ids for the allocation.
Developers wanting to program fast intersection routines, can do so analogue to this in their own backend implementations.
Note: We use the amount and offset hints to speed Redis up.
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/picky/backends/redis.rb', line 157 def ids combinations, amount, offset # TODO This is actually not correct: # A dumped/loaded Redis backend should use # the Redis backend calculation method. # So loaded? would be more appropriate. # if realtime # Just checked once on the first call. # if redis_with_scripting? @ids_script = "local intersected = redis.call('zinterstore', ARGV[1], #(KEYS), unpack(KEYS)); if intersected == 0 then redis.call('del', ARGV[1]); return {}; end local results = redis.call('zrange', ARGV[1], tonumber(ARGV[2]), tonumber(ARGV[3])); redis.call('del', ARGV[1]); return results;" require 'digest/sha1' @ids_script_hash = nil # Overrides _this_ method. # extend Scripting else # Overrides _this_ method. # extend NonScripting end else # Remove _this_ method and use the super # class method from now on. # # Note: This fails if there are multiple # Redis backends with different versions. # self.class.send :remove_method, __method__ end # Call the newly installed / super class version. # ids combinations, amount, offset end |
#maybe_load_hiredis ⇒ Object
20 21 22 23 24 |
# File 'lib/picky/backends/redis.rb', line 20 def maybe_load_hiredis require 'hiredis' rescue LoadError # It's ok. end |
#pid ⇒ Object
206 207 208 |
# File 'lib/picky/backends/redis.rb', line 206 def pid @pid ||= Process.pid end |
#redis_version ⇒ Object
Returns an array describing the current Redis version.
Note: This method assumes that clients answer
to #info with a hash (string/symbol keys)
detailing the infos.
Example:
backend.redis_version # => [2, 4, 1]
95 96 97 98 99 |
# File 'lib/picky/backends/redis.rb', line 95 def redis_version infos = client.info version_string = infos['redis_version'] || infos[:redis_version] version_string.split('.').map &:to_i end |
#redis_with_scripting? ⇒ Boolean
Does the Redis version already include scripting support?
70 71 72 |
# File 'lib/picky/backends/redis.rb', line 70 def redis_with_scripting? at_least_version redis_version, [2, 6, 0] end |
#weight(combinations) ⇒ Object
Returns the total weight for the combinations.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/picky/backends/redis.rb', line 103 def weight combinations # Note: A nice experiment that generated far too many strings. # # if redis_with_scripting? # @@weight_script = "local sum = 0; for i=1,#(KEYS),2 do local value = redis.call('hget', KEYS[i], KEYS[i+1]); if value then sum = sum + value end end return sum;" # # require 'digest/sha1' # @@weight_sent_once = nil # # # Scripting version of #ids. # # # class << self # def weight combinations # namespaces_keys = combinations.inject([]) do |namespaces_keys, combination| # namespaces_keys << "#{combination.bundle.identifier}:weights" # namespaces_keys << combination.token.text # end # # # Assume it's using EVALSHA. # # # begin # client.evalsha @@weight_sent_once, # namespaces_keys.size, # *namespaces_keys # rescue RuntimeError => e # # Make the server have a SHA-1 for the script. # # # @@weight_sent_once = Digest::SHA1.hexdigest @@weight_script # client.eval @@weight_script, # namespaces_keys.size, # *namespaces_keys # end # end # end # else # class << self # def weight combinations combinations.score # end # end # end # # Call the newly installed version. # # # weight combinations end |