
Outcome.pudu
Pudu64 lines2.8 KB
1/** @Chaos.Outcome.Strategy — answers a chosen outcome instead of running the callback */2module PuduLangResilience.Chaos.Outcome34import 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.Outcome.Injected — the outcome injected into one execution */12export type Injected[T, E] = { context: Context.Context, outcome: Resilience.Outcome[T, E] }1314/** @Chaos.Outcome.Options — which outcome to inject and how often */15export type Options[T, E] = {16 name: Option[Str],17 injection: Chaos.Injection,18 outcome: Option[Resilience.Outcome[T, E]],19 generator: Option[fn(Chaos.Arguments) -> Option[Resilience.Outcome[T, E]]],20 onInjected: Option[fn(Injected[T, E]) -> ()]21}222324export fn defaults[T, E]() -> Options[T, E] { Options{name: None, injection: Chaos.defaults(), outcome: None, generator: None, onInjected: None} }252627export fn injecting[T, E](outcome: Resilience.Outcome[T, E], injection: Chaos.Injection) -> Options[T, E] {28 Options{..defaults(), injection: injection, outcome: Some(outcome)}29}303132export fn validate[T, E](options: &Options[T, E]) -> Array[Str] {33 var problems = Chaos.validate(&options.injection)34 if options.outcome == None && options.generator == None { problems = problems.push("an outcome or a generator is required") }35 problems36}37383940export fn strategy[T, E](options: Options[T, E]) -> Strategy.Strategy[T, E] {41 Strategy.Strategy {42 name: options.name,43 kind: "ChaosOutcome",44 summary: "injects an outcome at rate " + show(options.injection.rate),45 problems: validate(&options),46 attach: Strategy.detached,47 execute: fn(runtime: Strategy.Runtime, context: Context.Context, callback: Strategy.Callback[T, E]) -> Resilience.Outcome[T, E] {48 if !Chaos.shouldInject(&options.injection, &context, &runtime.randomizer) { return callback(context) }49 let chosen = match options.generator {50 case Some(generate) => generate(Chaos.arguments(&context, &runtime.randomizer))51 case None => options.outcome52 }53 match chosen {54 case Some(outcome) => {55 Telemetry.report(&runtime.telemetry, &context, Events.ON_OUTCOME, Telemetry.Information, Some(Resilience.summarize(&outcome)), Telemetry.OutcomeInjected)56 if let Some(notify) = options.onInjected { notify(Injected{context: context, outcome: outcome}) }57 outcome58 }59 case None => callback(context)60 }61 }62 }63}64