Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-resilience

Resilience pipelines for Pudu: retry, circuit breaker, timeout, fallback, hedging, rate limiting, and chaos injection

0.1.0Apache-2.01

InstallClose

Chaos.pudu

Pudu52 lines2.1 KB

GitHub ↗
1/** @Resilience.Chaos.Module — when a chaos strategy injects */2module PuduLangResilience.Chaos34import Std.Decimal as Decimal5import PuduLangResilience.Context as Context6import PuduLangResilience.Randomizer as Randomizer78/** @Resilience.Chaos.Injection — how often, and whether, chaos is injected */9export type Injection = {10  rate: Decimal,11  rateGenerator: Option[fn(Context.Context) -> Decimal],12  enabled: Bool,13  enabledGenerator: Option[fn(Context.Context) -> Bool]14}1516/** @Resilience.Chaos.Arguments — what a chaos generator decides from */17export type Arguments = { context: Context.Context, randomizer: Randomizer.Randomizer }1819/// Enabled, injecting into one execution in a thousand.20export fn defaults() -> Injection { Injection{rate: 0.001d, rateGenerator: None, enabled: true, enabledGenerator: None} }2122/// Enabled, injecting into every execution.23export fn always() -> Injection { Injection{..defaults(), rate: 1d} }2425/// Enabled, injecting into the given share of executions, from 0 to 1.26export fn atRate(rate: Decimal) -> Injection { Injection{..defaults(), rate: rate} }2728/// Every reason the injection settings cannot be followed.29export fn validate(injection: &Injection) -> Array[Str] {30  if injection.rate < 0d || injection.rate > 1d { ["rate must be from 0 to 1"] } else { [] }31}3233/// Whether to inject into the execution holding `context`: never while disabled, otherwise with34/// the probability the rate names. A generated rate outside 0 to 1 is taken as the nearer bound.35export fn shouldInject(injection: &Injection, context: &Context.Context, randomizer: &Randomizer.Randomizer) -> Bool {36  let enabled = match injection.enabledGenerator {37    case Some(decide) => decide(*context)38    case None => injection.enabled39  }40  if !enabled { return false }41  let rate = match injection.rateGenerator {42    case Some(generate) => generate(*context)43    case None => injection.rate44  }45  Randomizer.chance(randomizer, rate)46}4748/// The arguments chaos generators receive for one execution.49export fn arguments(context: &Context.Context, randomizer: &Randomizer.Randomizer) -> Arguments {50  Arguments{context: *context, randomizer: *randomizer}51}52