Class: Wurk::Fetcher::OrphanGrace
- Inherits:
-
Object
- Object
- Wurk::Fetcher::OrphanGrace
- Defined in:
- lib/wurk/fetcher/orphan_grace.rb
Overview
The Reaper's wait between judging a list orphaned by its heartbeat and draining it.
A live owner can read as having no heartbeat hash: its first beat failed on a Redis blip, CPU-bound jobs held the beat back, or Redis restarted from an older snapshot. Its next beat lands within the wait, and that spares it.
The clock is this process's own and it is shared by nothing else, so it costs the same on every server and at every fleet size. That is the difference from what it replaces, OBJECT IDLETIME: any read of the list (a monitor's LLEN) reset that clock, some servers do not have the command, and a clock kept per sweep only advanced in a process that won the sweep lock twice. The loop thread therefore finishes what any sweep here started, with or without the lock (Reaper#drain_settled).
Defined Under Namespace
Classes: Entry
Constant Summary collapse
- MEMORY =
Lists remembered at once. Past it the memory restarts, and every clock restarting is the conservative direction: the next sweep judges them anew.
10_000
Instance Method Summary collapse
-
#forget(key) ⇒ Object
The owner came back: its next judgement starts a new wait.
-
#initialize(grace) ⇒ OrphanGrace
constructor
A new instance of OrphanGrace.
-
#next_due_in ⇒ Object
Seconds until the next wait ends, nil with nothing waiting.
-
#recent?(key, owner) ⇒ Boolean
true while the list must be left alone.
- #size ⇒ Object
-
#take_settled ⇒ Object
[[key, owner], ...] whose wait is over, removed from memory.
Constructor Details
#initialize(grace) ⇒ OrphanGrace
Returns a new instance of OrphanGrace.
26 27 28 29 30 |
# File 'lib/wurk/fetcher/orphan_grace.rb', line 26 def initialize(grace) @grace = grace @lock = ::Mutex.new @entries = {} end |
Instance Method Details
#forget(key) ⇒ Object
The owner came back: its next judgement starts a new wait.
49 50 51 |
# File 'lib/wurk/fetcher/orphan_grace.rb', line 49 def forget(key) @lock.synchronize { @entries.delete(key) } end |
#next_due_in ⇒ Object
Seconds until the next wait ends, nil with nothing waiting.
64 65 66 67 68 69 70 |
# File 'lib/wurk/fetcher/orphan_grace.rb', line 64 def next_due_in now = monotonic @lock.synchronize do oldest = @entries.each_value.map(&:since).min oldest && [(oldest + @grace) - now, 0].max end end |
#recent?(key, owner) ⇒ Boolean
true while the list must be left alone. owner is what #take_settled
hands back when the wait is over.
34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/wurk/fetcher/orphan_grace.rb', line 34 def recent?(key, owner) return false unless @grace.positive? now = monotonic @lock.synchronize do @entries.clear if @entries.size >= MEMORY && !@entries.key?(key) entry = (@entries[key] ||= Entry.new(now, owner)) next true if now - entry.since < @grace @entries.delete(key) false end end |
#size ⇒ Object
72 73 74 |
# File 'lib/wurk/fetcher/orphan_grace.rb', line 72 def size @lock.synchronize { @entries.size } end |
#take_settled ⇒ Object
[[key, owner], ...] whose wait is over, removed from memory.
54 55 56 57 58 59 60 61 |
# File 'lib/wurk/fetcher/orphan_grace.rb', line 54 def take_settled now = monotonic @lock.synchronize do settled = @entries.select { |_, entry| now - entry.since >= @grace } settled.each_key { |key| @entries.delete(key) } settled.map { |key, entry| [key, entry.owner] } end end |