///|
pub(all) struct Tag {
key : String
value : String
} derive(Eq, Debug)
///|
pub(all) struct ExecutionContext {
now_ms : Int
operation : String
tags : Array[Tag]
} derive(Eq)
///|
pub(all) struct AttemptFailure {
code : String
message : String
retryable : Bool
} derive(Eq)
///|
pub(all) enum ActionOutcome[T] {
Success(T)
Failure(AttemptFailure)
}
///|
pub(all) enum ExecuteError {
RejectedByRateLimiter(String)
RejectedByCircuitBreaker(Int)
RejectedByBulkhead(String)
RetryExhausted(String, String, Int)
InvalidPolicy(String)
} derive(Eq, Debug)
///|
pub fn execution_context(now_ms : Int, operation : String) -> ExecutionContext {
{ now_ms, operation, tags: [] }
}
///|
pub fn context_with_tag(
context : ExecutionContext,
key : String,
value : String,
) -> ExecutionContext {
let tags = context.tags.copy()
tags.push({ key, value })
{ now_ms: context.now_ms, operation: context.operation, tags }
}
///|
pub fn retryable_failure(code : String, message : String) -> AttemptFailure {
{ code, message, retryable: true }
}
///|
pub fn permanent_failure(code : String, message : String) -> AttemptFailure {
{ code, message, retryable: false }
}
///|
pub fn format_execute_error(error : ExecuteError) -> String {
match error {
RejectedByRateLimiter(reason) => "rate limiter rejected: " + reason
RejectedByCircuitBreaker(until_ms) =>
"circuit breaker is open until " + until_ms.to_string() + "ms"
RejectedByBulkhead(reason) => "bulkhead rejected: " + reason
RetryExhausted(code, message, attempts) =>
"retry exhausted after " +
attempts.to_string() +
" attempts [" +
code +
"]: " +
message
InvalidPolicy(message) => "invalid policy: " + message
}
}
///|
fn clamp_non_negative(value : Int) -> Int {
if value < 0 {
0
} else {
value
}
}
///|
fn clamp_at_least_one(value : Int) -> Int {
if value <= 0 {
1
} else {
value
}
}
///|
fn min_int(left : Int, right : Int) -> Int {
if left < right {
left
} else {
right
}
}
///|
fn max_int(left : Int, right : Int) -> Int {
if left > right {
left
} else {
right
}
}
///|
fn array_contains(items : Array[String], target : String) -> Bool {
for item in items {
if item == target {
return true
}
}
false
}