Module: Zizq::JobConfig

Included in:
ActiveJobConfig, Zizq::Job::ClassMethods
Defined in:
lib/zizq/job_config.rb

Overview

Shared class-level configuration DSL for Zizq job classes.

This module provides the queue, priority, retry, backoff, retention, and uniqueness configuration methods. It is extended onto job classes by ‘Zizq::Job` and can also be used with ActiveJob via `Zizq::ActiveJobConfig`.

Modules including this module must implement ‘zizq_serialize` and `zizq_deserialize` to define how job arguments are serialized for the API.

Instance Method Summary collapse

Instance Method Details

#zizq_backoff(exponent: nil, base: nil, jitter: nil) ⇒ Object

Declare the default backoff configuration for this job class.

Times are specified in seconds (optionally fractional). In a Rails app ‘ActiveSupport::Duration` is supported too.

All three parameters must be specified together and are used in the following exponential backoff formula:

delay = base + attempts**exponent + rand(0.0..jitter)*attempts

Example:

zizq_backoff exponent: 4.0, base: 15, jitter: 30

If not configured, the server’s default backoff policy is used.



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/zizq/job_config.rb', line 113

def zizq_backoff(exponent: nil, base: nil, jitter: nil) #: (?exponent: Numeric?, ?base: Numeric?, ?jitter: Numeric?) -> Zizq::backoff?
  if exponent || base || jitter
    unless exponent && base && jitter
      raise ArgumentError, "all of exponent:, base:, jitter: are required"
    end

    @zizq_backoff = { exponent: exponent.to_f, base: base.to_f, jitter: jitter.to_f }
  else
    @zizq_backoff
  end
end

#zizq_deserialize(payload) ⇒ Object

Deserialize positional and keyword arguments from the serialized payload.

Implemented by the including module.

Raises:

  • (NotImplementedError)


36
37
38
# File 'lib/zizq/job_config.rb', line 36

def zizq_deserialize(payload) #: untyped -> [Array[untyped], Hash[Symbol, untyped]]
  raise NotImplementedError, "#{self} must implement zizq_deserialize"
end

#zizq_enqueue_request(*args, **kwargs) ⇒ Object

Build a ‘Zizq::EnqueueRequest` from the class-level job config.

Subclasses can override this to implement dynamic logic such as priority based on arguments:

def self.zizq_enqueue_request(user_id, template:)
  req = super
  req.priority = 0 if template == "urgent"
  req
end


215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/zizq/job_config.rb', line 215

def zizq_enqueue_request(*args, **kwargs) #: (*untyped, **untyped) -> EnqueueRequest
  EnqueueRequest.new(
    type:         name || raise(ArgumentError, "Cannot enqueue anonymous class"),
    queue:        zizq_queue,
    payload:      zizq_serialize(*args, **kwargs),
    priority:     zizq_priority,
    retry_limit:  zizq_retry_limit,
    backoff:      zizq_backoff,
    retention:    zizq_retention,
    unique_while: zizq_unique ? zizq_unique_scope : nil,
    unique_key:   zizq_unique ? zizq_unique_key(*args, **kwargs) : nil
  )
end

#zizq_payload_filter(*args, **kwargs) ⇒ Object

Generate a jq expression that exactly matches payloads with the given arguments.

Implemented by the including module.

Raises:

  • (NotImplementedError)


44
45
46
# File 'lib/zizq/job_config.rb', line 44

def zizq_payload_filter(*args, **kwargs) #: (*untyped, **untyped) -> String
  raise NotImplementedError, "#{self} must implement zizq_payload_filter"
end

#zizq_payload_subset_filter(*args, **kwargs) ⇒ Object

Generate a jq expression that matches a subset of the given arguments.

Implemented by the including module.

Raises:

  • (NotImplementedError)


51
52
53
# File 'lib/zizq/job_config.rb', line 51

def zizq_payload_subset_filter(*args, **kwargs) #: (*untyped, **untyped) -> String
  raise NotImplementedError, "#{self} must implement zizq_payload_subset_filter"
end

#zizq_priority(priority = nil) ⇒ Object

Declare the default priority for this job class.

If not called, defaults to the default priority on the Zizq server. Jobs enqueued for this class will use the specified priority unless explicitly overridden during [‘Zizq::enqueue`] or by overriding `::zizq_enqueue_options` on the job class.



75
76
77
78
79
80
81
# File 'lib/zizq/job_config.rb', line 75

def zizq_priority(priority = nil) #: (?Integer?) -> Integer?
  if priority
    @zizq_priority = priority
  else
    @zizq_priority
  end
end

#zizq_queue(name = nil) ⇒ Object

Declare the default queue for this job class.

If not called, defaults to “default”. Jobs enqueued for this class will use the specified queue unless explicitly overridden during

‘Zizq::enqueue`

or by overriding ‘::zizq_enqueue_options` on the job

class.



61
62
63
64
65
66
67
# File 'lib/zizq/job_config.rb', line 61

def zizq_queue(name = nil) #: (?String?) -> String
  if name
    @zizq_queue = name
  else
    @zizq_queue || "default"
  end
end

#zizq_retention(completed: nil, dead: nil) ⇒ Object

Declare the default retention configuration for this job class.

Times are specified in seconds (optionally fractional). In a Rails app ‘ActiveSupport::Duration` is supported too.

Both parameters are optional — only the ones provided will be sent to the server. Omitted values use the server’s defaults.

Example:

zizq_retention completed: 0, dead: 7 * 86_400

If not configured, the server’s default is used.



138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/zizq/job_config.rb', line 138

def zizq_retention(completed: nil, dead: nil) #: (?completed: Numeric?, ?dead: Numeric?) -> Zizq::retention?
  if completed || dead
    result = {} #: Hash[Symbol, Float]

    result[:completed] = completed.to_f if completed
    result[:dead] = dead.to_f if dead

    @zizq_retention = result
  else
    @zizq_retention
  end
end

#zizq_retry_limit(limit = nil) ⇒ Object

Declare the default retry limit for this job class.

The job may fail up to the number of times specified by the retry limit and will exponentially backoff. Once the retry limit is reached, the job is killed and becomes part of the dead set.

If not configured, the server’s default is used.



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

def zizq_retry_limit(limit = nil) #: (?Integer?) -> Integer?
  if limit
    @zizq_retry_limit = limit
  else
    @zizq_retry_limit
  end
end

#zizq_serialize(*args, **kwargs) ⇒ Object

Serialize positional and keyword arguments into a JSON-serializable payload.

Implemented by the including module.

Raises:

  • (NotImplementedError)


29
30
31
# File 'lib/zizq/job_config.rb', line 29

def zizq_serialize(*args, **kwargs) #: (*untyped, **untyped) -> untyped
  raise NotImplementedError, "#{self} must implement zizq_serialize"
end

#zizq_unique(unique = nil, scope: nil) ⇒ Object

Declare uniqueness for this job class.

Requires a pro license.

When enabled, duplicate jobs with the same unique key are rejected at enqueue time. The optional scope controls how long the uniqueness guard lasts:

:queued  — unique while "scheduled" or "ready" (server default)
:active  — unique while "scheduled", "ready", or "in_flight"
:exists  — unique until the job is reaped by the server

Examples:

zizq_unique true                   # unique, server default scope
zizq_unique true, scope: :active   # unique while active
zizq_unique false                  # disable (e.g. in a subclass)


169
170
171
172
173
174
175
176
177
# File 'lib/zizq/job_config.rb', line 169

def zizq_unique(unique = nil, scope: nil) #: (?bool?, ?scope: Zizq::unique_scope?) -> bool
  if unique.nil?
    @zizq_unique || false
  else
    @zizq_unique = !!unique
    @zizq_unique_scope = scope
    @zizq_unique
  end
end

#zizq_unique_key(*args, **kwargs) ⇒ Object

Compute the unique key for a job with the given arguments.

The default implementation uses the class name and hashes the normalized serialized payload. Override this method to customize uniqueness — for example, to ignore certain arguments:

def self.zizq_unique_key(user_id, template:)
  super(user_id)  # unique per user, ignoring template
end


200
201
202
203
# File 'lib/zizq/job_config.rb', line 200

def zizq_unique_key(*args, **kwargs) #: (*untyped, **untyped) -> String
  payload = normalize_payload(zizq_serialize(*args, **kwargs))
  "#{name}:#{Digest::SHA256.hexdigest(JSON.generate(payload))}"
end

#zizq_unique_scope(scope = nil) ⇒ Object

Declare or read the uniqueness scope for this job class.

Usually set via ‘zizq_unique true, scope: :active` but can also be set independently.



183
184
185
186
187
188
189
# File 'lib/zizq/job_config.rb', line 183

def zizq_unique_scope(scope = nil) #: (?Zizq::unique_scope?) -> Zizq::unique_scope?
  if scope
    @zizq_unique_scope = scope
  else
    @zizq_unique_scope
  end
end