lib/picky/backends/redis.rb in picky-3.6.2 vs lib/picky/backends/redis.rb in picky-3.6.3
- old
+ new
@@ -86,30 +86,48 @@
# routines, can do so analogue to this in their own
# backend implementations.
#
# Note: We use the amount and offset hints to speed Redis up.
#
-# def ids combinations, amount, offset
-# if redis_with_scripting?
-# @@script = <<-SCRIPT
-# redis.call('zinterstore', KEYS[1], ARGV[1]);
-# local result = redis.call('zrange', KEYS[1], ARGV[2], ARGV[3])
-# redis.call('del', KEYS[1])
-# return result
-# SCRIPT
-# # Scripting version of #ids.
-# #
-# def ids combinations, amount, offset
-# identifiers = combinations.inject([]) do |identifiers, combination|
-# identifiers << "#{combination.identifier}"
-# end
-#
-# # Assume it's using EVALSHA.
-# #
-# client.eval @@script, generate_intermediate_result_id, identifiers, offset, (offset + amount)
-# end
-# else
+ def ids combinations, amount, offset
+ # Just checked once on the first call.
+ #
+ if redis_with_scripting?
+ @@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'
+ @@sent_once = nil
+
+ # Scripting version of #ids.
+ #
+ def ids combinations, amount, offset
+ identifiers = combinations.inject([]) do |identifiers, combination|
+ identifiers << "#{combination.identifier}"
+ end
+
+ # Assume it's using EVALSHA.
+ #
+ begin
+ client.evalsha @@sent_once,
+ identifiers.size,
+ *identifiers,
+ generate_intermediate_result_id,
+ offset,
+ (offset + amount)
+ rescue RuntimeError => e
+ # Make the server have a SHA-1 for the script.
+ #
+ @@sent_once = Digest::SHA1.hexdigest @@script
+ client.eval @@script,
+ identifiers.size,
+ *identifiers,
+ generate_intermediate_result_id,
+ offset,
+ (offset + amount)
+ end
+ end
+ else
# Non-Scripting version of #ids.
#
def ids combinations, amount, offset
identifiers = combinations.inject([]) do |identifiers, combination|
identifiers << "#{combination.identifier}"
@@ -117,25 +135,37 @@
result_id = generate_intermediate_result_id
# Intersect and store.
#
- client.zinterstore result_id, identifiers
+ 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.
+ # Note: I could also not delete it, but that
+ # would not be clean at all.
#
client.del result_id
results
end
- # end
- # end
+ end
+
+ # Call the newly installed version.
+ #
+ ids combinations, amount, offset
+ end
# Generate a multiple host/process safe result id.
#
# Note: Generated when this class loads.
#
\ No newline at end of file