
Partitioned.pudu
Pudu52 lines2.3 KB
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]] }141516export fn create(partitionOf: fn(Context.Context) -> Partition) -> Partitioned {17 Partitioned{partitionOf: partitionOf, limiters: Shared.shared(Map.empty())}18}192021export fn acquire(target: &Partitioned, context: &Context.Context, permits: Int) -> Limiter.Lease {22 Limiter.acquire(&limiterFor(target, context), permits, &context.token)23}242526export fn attempt(target: &Partitioned, context: &Context.Context, permits: Int) -> Limiter.Lease {27 Limiter.attempt(&limiterFor(target, context), permits)28}293031export 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}353637export fn keys(source: &Partitioned) -> Array[Str] { Map.keys(&Shared.current(&source.limiters)) }383940fn 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