Class: Zizq::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/zizq/router.rb,
sig/generated/zizq/router.rbs

Overview

Dispatch jobs by type string, mapping each to a handler block.

Designed for cross-language workflows: payloads are plain JSON values (Hashes / Arrays / strings / numbers), type is a String the producer agrees on with the consumer, and routes are registered explicitly — no Zizq::Job mixin involved.

Zizq.configure do |c|
c.dispatcher = Zizq::Router.new do
  route("send_email") do |payload|
    Mailer.deliver(payload["user_id"], payload["template"])
  end

  route("expire_tokens") do
    TokenSweeper.run
  end

  route("generate_report") do |payload, job|
    Reports.generate(payload["id"], attempts: job.attempts)
  end

  # `def` inside the block defines singleton methods on the
  # router. Route blocks captured *inside* the constructor
  # have lexical `self == router`, so they can call these
  # helpers; routes added outside (`router.route("…") { … }`)
  # keep their own lexical `self` and would need to go through
  # the router explicitly (`router.logger`).
  def logger
    Zizq.configuration.logger
  end

  # Anything else falls back. A common pattern is delegating
  # to `Zizq::Job` for the apps that mix the two styles.
  fallback { |job| Zizq::Job.call(job) }
end
end

Routes can also be registered outside the constructor block:

router = Zizq::Router.new
router.route("send_email") { |payload| ... }

Handlers are called as handler.call(payload, job). Block-arity rules let { |payload| } or { } ignore either argument. Strict-arity lambdas need to declare both.

Defined Under Namespace

Classes: UnknownJobType

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ Router

Returns a new instance of Router.



61
62
63
64
65
# File 'lib/zizq/router.rb', line 61

def initialize(&block)
  @routes = {} #: Hash[String, ^(untyped, Resources::Job) -> void]
  @fallback = nil #: (^(Resources::Job) -> void)?
  instance_eval(&block) if block
end

Instance Method Details

#call(job) ⇒ Object

Dispatch a single job. Looks up the handler by job.type, falls back to the registered fallback if any, otherwise raises UnknownJobType.

Parameters:

  • job (Object)

Returns:

  • (Object)


90
91
92
93
94
95
96
97
98
# File 'lib/zizq/router.rb', line 90

def call(job) #: (Resources::Job) -> void
  handler = @routes[job.type]

  return handler.call(job.payload, job) if handler
  return @fallback.call(job) if @fallback

  raise UnknownJobType,
    "no handler registered for job type #{job.type.inspect}"
end

#fallback {|arg0| ... } ⇒ Object

Register a fallback handler invoked when no route matches. Receives the full Resources::Job (not split into payload / job pair), since the canonical use is delegation to another dispatcher:

fallback { |job| Zizq::Job.call(job) }

Yields:

Yield Parameters:

Yield Returns:

  • (void)

Returns:

  • (Object)


83
84
85
# File 'lib/zizq/router.rb', line 83

def fallback(&handler)
  @fallback = handler
end

#route(type) {|arg0, arg1| ... } ⇒ Object

Register handler for jobs whose type matches.

Parameters:

  • type (String, Symbol)

Yields:

Yield Parameters:

Yield Returns:

  • (void)

Returns:

  • (Object)


71
72
73
# File 'lib/zizq/router.rb', line 71

def route(type, &handler)
  @routes[type.to_s] = handler
end