lib/picky/backends/redis.rb in picky-4.6.3 vs lib/picky/backends/redis.rb in picky-4.6.4
- old
+ new
@@ -167,108 +167,28 @@
@@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_sent_once = nil
- # Scripting version of #ids.
+ # Overrides _this_ method.
#
- class << self
- def ids combinations, amount, offset
- identifiers = combinations.inject([]) do |identifiers, combination|
- identifiers << "#{combination.identifier}"
- end
-
- # Assume it's using EVALSHA.
- #
- begin
- if identifiers.size > 1
- client.evalsha @@ids_sent_once,
- identifiers.size,
- *identifiers,
- generate_intermediate_result_id,
- offset,
- (offset + amount)
- else
- client.zrange identifiers.first,
- offset,
- (offset + amount)
- end
- rescue RuntimeError => e
- # Make the server have a SHA-1 for the script.
- #
- @@ids_sent_once = Digest::SHA1.hexdigest @@ids_script
- client.eval @@ids_script,
- identifiers.size,
- *identifiers,
- generate_intermediate_result_id,
- offset,
- (offset + amount)
- end
- end
- end
+ extend Scripting
else
- # Non-Scripting version of #ids.
+ # Overrides _this_ method.
#
- class << self
- def ids combinations, amount, offset
- identifiers = combinations.inject([]) do |identifiers, combination|
- identifiers << "#{combination.identifier}"
- end
-
- result_id = generate_intermediate_result_id
-
- # Little optimization.
- #
- if identifiers.size > 1
- # Intersect and store.
- #
- intersected = client.zinterstore result_id, identifiers
-
- # Return clean and early if there has been no intersection.
- #
- if intersected.zero?
- client.del result_id
- return []
- end
-
- # Get the stored result.
- #
- results = client.zrange result_id, offset, (offset + amount)
-
- # Delete the stored result as it was only for temporary purposes.
- #
- # Note: I could also not delete it, but that
- # would not be clean at all.
- #
- client.del result_id
- else
- results = client.zrange identifiers.first, offset, (offset + amount)
- end
-
- results
- end
- end
+ extend NonScripting
end
else
- class << self
- def ids combinations, _, _
- # Get the ids for each combination.
- #
- id_arrays = combinations.inject([]) do |total, combination|
- total << combination.ids
- end
-
- # Call the optimized C algorithm.
- #
- # Note: It orders the passed arrays by size.
- #
- Performant::Array.memory_efficient_intersect id_arrays
- end
- end
+ # 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 version.
+ # Call the newly installed / super class version.
#
ids combinations, amount, offset
end
# Generate a multiple host/process safe result id.
@@ -288,9 +208,88 @@
end
# Use the host and pid (generated lazily in child processes) for the result.
#
def generate_intermediate_result_id
@intermediate_result_id ||= "#{host}:#{pid}:picky:result"
+ end
+
+ # Uses Lua scripting on Redis 2.6.
+ #
+ module Scripting
+ def ids combinations, amount, offset
+ identifiers = combinations.inject([]) do |identifiers, combination|
+ identifiers << "#{combination.identifier}"
+ end
+
+ # Assume it's using EVALSHA.
+ #
+ begin
+ if identifiers.size > 1
+ client.evalsha @@ids_sent_once,
+ identifiers.size,
+ *identifiers,
+ generate_intermediate_result_id,
+ offset,
+ (offset + amount)
+ else
+ client.zrange identifiers.first,
+ offset,
+ (offset + amount)
+ end
+ rescue RuntimeError => e
+ # Make the server have a SHA-1 for the script.
+ #
+ @@ids_sent_once = Digest::SHA1.hexdigest @@ids_script
+ client.eval @@ids_script,
+ identifiers.size,
+ *identifiers,
+ generate_intermediate_result_id,
+ offset,
+ (offset + amount)
+ end
+ end
+ end
+
+ # Does not use Lua scripting, < Redis 2.6.
+ #
+ module NonScripting
+ def ids combinations, amount, offset
+ identifiers = combinations.inject([]) do |identifiers, combination|
+ identifiers << "#{combination.identifier}"
+ end
+
+ result_id = generate_intermediate_result_id
+
+ # Little optimization.
+ #
+ if identifiers.size > 1
+ # Intersect and store.
+ #
+ intersected = client.zinterstore result_id, identifiers
+
+ # Return clean and early if there has been no intersection.
+ #
+ if intersected.zero?
+ client.del result_id
+ return []
+ end
+
+ # Get the stored result.
+ #
+ results = client.zrange result_id, offset, (offset + amount)
+
+ # Delete the stored result as it was only for temporary purposes.
+ #
+ # Note: I could also not delete it, but that
+ # would not be clean at all.
+ #
+ client.del result_id
+ else
+ results = client.zrange identifiers.first, offset, (offset + amount)
+ end
+
+ results
+ end
end
end
end
\ No newline at end of file