Class: Wurk::Web::Search
- Inherits:
-
Object
- Object
- Wurk::Web::Search
- Defined in:
- lib/wurk/web/search.rb
Overview
Pro feature parity: substring search across queues / retries / scheduled / dead. Spec: docs/target/sidekiq-pro.md §10.1 ("Search box on Retry/Scheduled/Dead pages, substring across job payload via ZSCAN"). Wurk ships it free, extended to also cover the queue LIST.
ZSET stores are ZSCAN-paged and filtered client-side against the literal
substring — the same shape as the queue LIST's paged LRANGE filter —
rather than ZSCAN MATCH: MATCH returns only matches, never the count of
elements Redis walked, so a no-match keystroke couldn't be metered and
could round-trip an enormous ZSET. Both paths charge the shared scan
budget so a keystroke never full-walks a multi-million-entry store.
Result shape mirrors Wurk::Api::Serializers#sorted_entry so the SPA
renders search hits with the same component as a sorted-set row.
Constant Summary collapse
- DEFAULT_LIMIT =
100- MAX_LIMIT =
500- KINDS =
%w[queues retry scheduled dead].freeze
- QUEUE_PAGE =
50- ZSCAN_PAGE =
200- SCAN_LIMIT_PER_QUEUE =
A queue LIST has no SCAN, so a keystroke must never full-walk a multi-million-entry queue. Bound each queue's scan and the whole request's scan;
truncated?flips when we stop early so the API can tell the UI it's showing partial results. 5_000- SCAN_BUDGET =
20_000
Instance Attribute Summary collapse
-
#kinds ⇒ Object
readonly
Returns the value of attribute kinds.
-
#limit ⇒ Object
readonly
Returns the value of attribute limit.
-
#substring ⇒ Object
readonly
Returns the value of attribute substring.
Instance Method Summary collapse
-
#each ⇒ Object
Streams matching hits across every selected store.
-
#initialize(substring, kinds: KINDS, limit: DEFAULT_LIMIT) ⇒ Search
constructor
A new instance of Search.
- #to_a ⇒ Object
-
#truncated? ⇒ Boolean
True when a scan stopped at a bound (a queue's per-queue cap, a sorted set's page loop, or the shared per-request budget) with elements left unexamined — the hit list may be incomplete.
Constructor Details
#initialize(substring, kinds: KINDS, limit: DEFAULT_LIMIT) ⇒ Search
Returns a new instance of Search.
39 40 41 42 43 44 45 46 |
# File 'lib/wurk/web/search.rb', line 39 def initialize(substring, kinds: KINDS, limit: DEFAULT_LIMIT) @substring = substring.to_s @kinds = (Array(kinds).map(&:to_s) & KINDS) @kinds = KINDS.dup if @kinds.empty? @limit = limit.to_i.clamp(1, MAX_LIMIT) @truncated = false @scanned = 0 end |
Instance Attribute Details
#kinds ⇒ Object (readonly)
Returns the value of attribute kinds.
37 38 39 |
# File 'lib/wurk/web/search.rb', line 37 def kinds @kinds end |
#limit ⇒ Object (readonly)
Returns the value of attribute limit.
37 38 39 |
# File 'lib/wurk/web/search.rb', line 37 def limit @limit end |
#substring ⇒ Object (readonly)
Returns the value of attribute substring.
37 38 39 |
# File 'lib/wurk/web/search.rb', line 37 def substring @substring end |
Instance Method Details
#each ⇒ Object
Streams matching hits across every selected store. Stops at limit.
Yields Hashes shaped like sorted_entry payloads with an extra
:kind discriminator + :name (queue name or set name).
57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/wurk/web/search.rb', line 57 def each(&) return enum_for(:each) unless block_given? return if @substring.empty? @scanned = 0 @truncated = false emitted = 0 each_hit do |row| yield row emitted += 1 break if emitted >= @limit end end |
#to_a ⇒ Object
71 72 73 |
# File 'lib/wurk/web/search.rb', line 71 def to_a each.to_a end |
#truncated? ⇒ Boolean
True when a scan stopped at a bound (a queue's per-queue cap, a sorted
set's page loop, or the shared per-request budget) with elements left
unexamined — the hit list may be incomplete. Meaningful only after
each/to_a has driven the scan.
52 |
# File 'lib/wurk/web/search.rb', line 52 def truncated? = @truncated |