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

Partitioned.pudu

Pudu52 lines2.3 KB

GitHub ↗
1/** @Limiter.Partitioned.Module — one limiter per partition of executions */2module PuduLangResilience.Limiter.Partitioned34import Std.Map as Map5import PuduLangResilience.Context as Context6import PuduLangResilience.Limiter as Limiter7import PuduLangResilience.Utils.Shared as Shared89/** @Limiter.Partitioned.Partition — the key of a partition and how to make its limiter */10export type Partition = { key: Str, create: fn() -> Limiter.Limiter }1112/** @Limiter.Partitioned.Partitioned — limiters made on first use, one per key */13export type Partitioned = { partitionOf: fn(Context.Context) -> Partition, limiters: Shared.Shared[Map[Str, Limiter.Limiter]] }1415/// A partitioned limiter choosing each execution's partition with `partitionOf`.16export fn create(partitionOf: fn(Context.Context) -> Partition) -> Partitioned {17  Partitioned{partitionOf: partitionOf, limiters: Shared.shared(Map.empty())}18}1920/// Requests `permits` from the partition of the context, waiting as that limiter allows.21export fn acquire(target: &Partitioned, context: &Context.Context, permits: Int) -> Limiter.Lease {22  Limiter.acquire(&limiterFor(target, context), permits, &context.token)23}2425/// Requests `permits` from the partition of the context without waiting.26export fn attempt(target: &Partitioned, context: &Context.Context, permits: Int) -> Limiter.Lease {27  Limiter.attempt(&limiterFor(target, context), permits)28}2930/// The counts of a partition's limiter, once it has been used.31export fn statistics(source: &Partitioned, key: Str) -> Option[Limiter.Statistics] {32  let limiter = Map.get(&Shared.current(&source.limiters), key) ?33  Some(Limiter.statistics(&limiter))34}3536/// The keys of every partition used so far, in order.37export fn keys(source: &Partitioned) -> Array[Str] { Map.keys(&Shared.current(&source.limiters)) }3839/// The limiter of the context's partition, made under the lock on first use.40fn limiterFor(target: &Partitioned, context: &Context.Context) -> Limiter.Limiter {41  let partition = (target.partitionOf)(*context)42  Shared.change(&target.limiters, fn(held: Map[Str, Limiter.Limiter]) -> (Map[Str, Limiter.Limiter], Limiter.Limiter) {43      match Map.get(&held, partition.key) {44        case Some(existing) => (held, existing)45        case None => {46          let made = (partition.create)()47          (Map.insert(&held, partition.key, made), made)48        }49      }50    })51}52