//// Background-job integration patterns for ecosystem compatibility (M26).
import gleam/int
/// Queue backend profile.
pub type QueueBackend {
GleamWorkerPool(pool_size: Int)
ObanBridge(module: String)
MixedQueue(primary: String, fallback: String)
}
/// Retry/timeout policy for one job class.
pub type RetryPolicy {
RetryPolicy(max_attempts: Int, base_backoff_ms: Int, timeout_ms: Int)
}
/// One job integration pattern.
pub type Pattern {
Pattern(
name: String,
backend: QueueBackend,
retry_policy: RetryPolicy,
tenant_partitioned: Bool,
dead_letter_enabled: Bool,
)
}
/// Critical-path integration pattern.
pub fn critical_path_pattern() -> Pattern {
Pattern(
name: "critical_path_jobs",
backend: ObanBridge(module: "MyApp.Workers"),
retry_policy: RetryPolicy(
max_attempts: 10,
base_backoff_ms: 250,
timeout_ms: 15_000,
),
tenant_partitioned: True,
dead_letter_enabled: True,
)
}
/// Mixed-runtime integration pattern.
pub fn mixed_runtime_pattern() -> Pattern {
Pattern(
name: "mixed_runtime_jobs",
backend: MixedQueue(primary: "Oban", fallback: "GleamWorkers"),
retry_policy: RetryPolicy(
max_attempts: 6,
base_backoff_ms: 500,
timeout_ms: 20_000,
),
tenant_partitioned: True,
dead_letter_enabled: True,
)
}
/// Local development integration pattern.
pub fn local_dev_pattern() -> Pattern {
Pattern(
name: "local_dev_jobs",
backend: GleamWorkerPool(pool_size: 4),
retry_policy: RetryPolicy(
max_attempts: 3,
base_backoff_ms: 100,
timeout_ms: 5000,
),
tenant_partitioned: True,
dead_letter_enabled: True,
)
}
/// Validate job integration constraints.
pub fn valid(pattern: Pattern) -> Bool {
backend_valid(pattern.backend)
&& retry_policy_valid(pattern.retry_policy)
&& pattern.tenant_partitioned
&& pattern.dead_letter_enabled
}
/// Stable backend label.
pub fn backend_label(backend: QueueBackend) -> String {
case backend {
GleamWorkerPool(pool_size) ->
"gleam_worker_pool:" <> int.to_string(pool_size)
ObanBridge(module) -> "oban_bridge:" <> module
MixedQueue(primary, fallback) ->
"mixed_queue:" <> primary <> ":" <> fallback
}
}
/// Stable pattern signature.
pub fn signature(pattern: Pattern) -> String {
"jobs:"
<> pattern.name
<> "|backend="
<> backend_label(pattern.backend)
<> "|max_attempts="
<> int.to_string(pattern.retry_policy.max_attempts)
<> "|base_backoff_ms="
<> int.to_string(pattern.retry_policy.base_backoff_ms)
<> "|timeout_ms="
<> int.to_string(pattern.retry_policy.timeout_ms)
<> "|tenant_partitioned="
<> bool_label(pattern.tenant_partitioned)
<> "|dead_letter_enabled="
<> bool_label(pattern.dead_letter_enabled)
}
/// Pattern backend.
pub fn backend(pattern: Pattern) -> QueueBackend {
pattern.backend
}
/// Pattern name.
pub fn name(pattern: Pattern) -> String {
pattern.name
}
fn backend_valid(backend: QueueBackend) -> Bool {
case backend {
GleamWorkerPool(pool_size) -> pool_size > 0
ObanBridge(module) -> module != ""
MixedQueue(primary, fallback) -> primary != "" && fallback != ""
}
}
fn retry_policy_valid(policy: RetryPolicy) -> Bool {
policy.max_attempts > 0 && policy.base_backoff_ms > 0 && policy.timeout_ms > 0
}
fn bool_label(value: Bool) -> String {
case value {
True -> "true"
False -> "false"
}
}