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

Behavior.pudu

Pudu57 lines2.3 KB

GitHub ↗
1/** @Chaos.Behavior.Strategy — runs extra behavior before the callback */2module PuduLangResilience.Chaos.Behavior34import PuduLangResilience.Chaos as Chaos5import PuduLangResilience.Constants.Events as Events6import PuduLangResilience.Context as Context7import PuduLangResilience as Resilience8import PuduLangResilience.Strategy as Strategy9import PuduLangResilience.Telemetry as Telemetry1011/** @Chaos.Behavior.Options — what to run and how often */12export type Options[E] = {13  name: Option[Str],14  injection: Chaos.Injection,15  behavior: Option[fn(Chaos.Arguments) -> Result[(), Resilience.Failure[E]]],16  onInjected: Option[fn(Context.Context) -> ()]17}1819/// The default injection with no behavior chosen yet.20export fn defaults[E]() -> Options[E] { Options{name: None, injection: Chaos.defaults(), behavior: None, onInjected: None} }2122/// Runs `behavior` at the given injection settings.23export fn injecting[E](behavior: fn(Chaos.Arguments) -> Result[(), Resilience.Failure[E]], injection: Chaos.Injection) -> Options[E] {24  Options{..defaults(), injection: injection, behavior: Some(behavior)}25}2627/// Every reason the options cannot be followed.28export fn validate[E](options: &Options[E]) -> Array[Str] {29  var problems = Chaos.validate(&options.injection)30  if options.behavior == None { problems = problems.push("behavior is required") }31  problems32}3334/// A behavior injection strategy following the options. A behavior that fails answers its35/// failure without running the callback.36export fn strategy[T, E](options: Options[E]) -> Strategy.Strategy[T, E] {37  Strategy.Strategy {38    name: options.name,39    kind: "ChaosBehavior",40    summary: "injects behavior at rate " + show(options.injection.rate),41    problems: validate(&options),42    attach: Strategy.detached,43    execute: fn(runtime: Strategy.Runtime, context: Context.Context, callback: Strategy.Callback[T, E]) -> Resilience.Outcome[T, E] {44      if !Chaos.shouldInject(&options.injection, &context, &runtime.randomizer) { return callback(context) }45      match options.behavior {46        case Some(behave) => {47          Telemetry.report(&runtime.telemetry, &context, Events.ON_BEHAVIOR, Telemetry.Information, None, Telemetry.BehaviorInjected)48          behave(Chaos.arguments(&context, &runtime.randomizer)) ?49          if let Some(notify) = options.onInjected { notify(context) }50          callback(context)51        }52        case None => callback(context)53      }54    }55  }56}57