class Barrage::Generators::RedisWorkerId
Constants
- RACE_CONDITION_TTL
Public Class Methods
new(options = {})
click to toggle source
Calls superclass method
Barrage::Generators::Base::new
# File lib/barrage/generators/redis_worker_id.rb, line 10 def initialize(options = {}) @worker_id = nil @worker_ttl = 0 @real_ttl = 0 super @data = [] @finalizer_proc = Finalizer.new(@data) ObjectSpace.define_finalizer(self, @finalizer_proc) end
Public Instance Methods
generate()
click to toggle source
# File lib/barrage/generators/redis_worker_id.rb, line 20 def generate now = Time.now.to_i if @worker_ttl - now <= 0 @data[1] = @worker_id = renew_worker_id # check redis after half of real ttl @worker_ttl = now + ttl / 2 @real_ttl = now + ttl @data[2] = @real_ttl end @worker_id end
Also aliased as: current
redis()
click to toggle source
# File lib/barrage/generators/redis_worker_id.rb, line 37 def redis @redis ||= @data[0] = Redis.new(options["redis"] || {}) end
ttl()
click to toggle source
# File lib/barrage/generators/redis_worker_id.rb, line 33 def ttl options["ttl"] end
Private Instance Methods
renew_worker_id()
click to toggle source
# File lib/barrage/generators/redis_worker_id.rb, line 60 def renew_worker_id if @real_ttl - Time.now.to_i - RACE_CONDITION_TTL <= 0 @worker_id = nil end new_worker_id = redis.evalsha( script_sha, argv: [2 ** length, rand(2 ** length), @worker_id, ttl, RACE_CONDITION_TTL] ) new_worker_id or raise StandardError, "Renew redis worker id failed" return new_worker_id.to_i end
script_sha()
click to toggle source
# File lib/barrage/generators/redis_worker_id.rb, line 72 def script_sha @script_sha ||= redis.script(:load, <<-EOF.gsub(/^ {12}/, '')) local max_value = tonumber(ARGV[1]) local new_worker_id = ARGV[2] local old_worker_id = ARGV[3] local ttl = tonumber(ARGV[4]) local race_condition_ttl = tonumber(ARGV[5]) local loop_cnt = 0 local worker_id = nil local candidate_worker_id = tonumber(new_worker_id) if type(old_worker_id) == "string" and string.len(old_worker_id) > 0 and redis.call('EXISTS', "barrage:worker:" .. old_worker_id) == 1 then redis.call("EXPIRE", "barrage:worker:" .. old_worker_id, ttl + race_condition_ttl) worker_id = old_worker_id else while redis.call("SETNX", "barrage:worker:" .. candidate_worker_id, 1) == 0 and loop_cnt < max_value do candidate_worker_id = (candidate_worker_id + 1) % max_value loop_cnt = loop_cnt + 1 end if loop_cnt >= max_value then return nil else worker_id = candidate_worker_id end redis.call("EXPIRE", "barrage:worker:" .. worker_id, ttl + race_condition_ttl) end return worker_id EOF end