aboutsummaryrefslogtreecommitdiff
path: root/lib/argument_deduplication/argument.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/argument_deduplication/argument.rb')
-rw-r--r--lib/argument_deduplication/argument.rb49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/argument_deduplication/argument.rb b/lib/argument_deduplication/argument.rb
new file mode 100644
index 000000000..60be6bca2
--- /dev/null
+++ b/lib/argument_deduplication/argument.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module ArgumentDeduplication
+ class Argument
+ def self.from_value(value)
+ new(Digest::SHA256.base64digest(value), value)
+ end
+
+ attr_reader :content_hash, :value
+
+ def initialize(content_hash, value)
+ @content_hash = content_hash
+ @value = value
+ end
+
+ def push!
+ with_redis do |redis|
+ redis.multi do |transaction|
+ transaction.set("#{PREFIX}:value:#{content_hash}", value, ex: TTL)
+ transaction.incr("#{PREFIX}:refcount:#{content_hash}")
+ transaction.expire("#{PREFIX}:refcount:#{content_hash}", TTL)
+ end
+ end
+ end
+
+ def pop!
+ with_redis do |redis|
+ redis.decr("#{PREFIX}:refcount:#{content_hash}")
+
+ redis.watch("#{PREFIX}:refcount:#{content_hash}") do
+ if redis.get("#{PREFIX}:refcount:#{content_hash}").to_i <= 0
+ redis.multi do |transaction|
+ transaction.del("#{PREFIX}:refcount:#{content_hash}")
+ transaction.del("#{PREFIX}:value:#{content_hash}")
+ end
+ else
+ redis.unwatch
+ end
+ end
+ end
+ end
+
+ private
+
+ def with_redis(&block)
+ Sidekiq.redis(&block)
+ end
+ end
+end