Module: Wurk::Fetcher::PrivateListKey

Defined in:
lib/wurk/fetcher/private_list_key.rb

Overview

Reads the owner back out of a reliable-fetch private list key (queue:<public>|<host>|<pid>|<nonce>|<idx>, see Reliable.private_queue_name) for the Reaper's liveness check. Pure string work, no Redis.

Constant Summary collapse

NONCE_PATTERN =

The nonce shape Component::PROCESS_NONCE writes (SecureRandom.hex(6)).

/\A[0-9a-f]{12}\z/

Class Method Summary collapse

Class Method Details

.integer?(str) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/wurk/fetcher/private_list_key.rb', line 69

def integer?(str)
  str.is_a?(String) && str.match?(/\A\d+\z/)
end

.narrow_tail(parts) ⇒ Object

<host>|<pid>|<idx> — written before the nonce existed. Such a list can still hold a pre-upgrade process's in-flight jobs across a rolling upgrade, so it stays reclaimable even though nothing writes it anymore.



65
66
67
# File 'lib/wurk/fetcher/private_list_key.rb', line 65

def narrow_tail(parts)
  [parts[-3], parts[-2].to_i, nil, 3] if integer?(parts[-2])
end

.nonce?(str) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/wurk/fetcher/private_list_key.rb', line 73

def nonce?(str)
  str.is_a?(String) && str.match?(NONCE_PATTERN)
end

.owner_tails(parts) ⇒ Object

Owner segments of a private-list key, taken from the right, as [host, pid, nonce, segment_count] readings in preference order (empty when nothing parses). The wide shape is preferred: an all-digit nonce is rare but reachable, and reading such a key narrow would take the pid for the host and the nonce for the pid — draining a live owner's list out from under it.



47
48
49
50
51
# File 'lib/wurk/fetcher/private_list_key.rb', line 47

def owner_tails(parts)
  return [] unless parts.size >= 3 && integer?(parts[-1])

  [wide_tail(parts), narrow_tail(parts)].compact
end

.parse_full(key) ⇒ Object

queue:<public>|<host>|<pid>|<nonce>|<idx> → [public_q, host, pid, nonce], parsed from the right so a | inside the queue name is tolerated. nil when the key isn't a well-formed private list.

With no known prefix to split on, both owner shapes are tried in preference order and the first one leaving a real public queue behind wins. The narrow reading is what saves a pre-nonce key from an all-digit host (queue:q|123456789012|<pid>|<idx> — a bare Docker hostname is 12 hex chars): read wide, its host segment either eats the whole queue name (plain queue — nothing left over) or truncates it at the first pipe and puts the real pid in the nonce slot (pipe-bearing queue). Both misreads are refused: the leftover must be a real queue name and the pseudo-nonce must be nonce-shaped (see wide_tail).



30
31
32
33
34
35
36
37
38
39
# File 'lib/wurk/fetcher/private_list_key.rb', line 30

def parse_full(key)
  parts = key.split('|')
  owner_tails(parts).each do |host, pid, nonce, width|
    public_q = parts[0...-width].join('|')
    next unless public_q.start_with?(Keys::QUEUE_PREFIX) && public_q != Keys::QUEUE_PREFIX

    return [public_q, host, pid, nonce]
  end
  nil
end

.wide_tail(parts) ⇒ Object

<host>|<pid>|<nonce>|<idx> — the shape every current process writes. The nonce slot must carry PROCESS_NONCE's exact shape (NONCE_PATTERN): on a pre-nonce key read wide it holds the real pid, which is never 12 hex, so the guard is what falls such a key through to narrow_tail instead of misreading it.



58
59
60
# File 'lib/wurk/fetcher/private_list_key.rb', line 58

def wide_tail(parts)
  [parts[-4], parts[-3].to_i, parts[-2], 4] if parts.size >= 4 && integer?(parts[-3]) && nonce?(parts[-2])
end