
FixedWindow.pudu
Pudu41 lines1.7 KB
1/** @Limiter.FixedWindow.Module — at most N permits per fixed window */2module PuduLangResilience.Limiter.FixedWindow34import PuduLangResilience.Clock as Clock5import PuduLangResilience.Domain.Algorithms as Algorithms6import PuduLangResilience.Limiter.Engine as Engine7import PuduLangResilience.Limiter as Limiter89/** @Limiter.FixedWindow.Options — permits per window and the queue behind them */10export type Options = {11 permitLimit: Int,12 window: Int,13 autoReplenishment: Bool,14 queueLimit: Int,15 queueOrder: Limiter.QueueOrder,16 clock: Clock.Clock17}181920export fn defaults() -> Options {21 Options{permitLimit: 100, window: 1000, autoReplenishment: true, queueLimit: 0, queueOrder: Limiter.OldestFirst, clock: Clock.system()}22}232425export fn validate(options: &Options) -> Array[Str] {26 var problems: Array[Str] = []27 if options.permitLimit < 1 { problems = problems.push("permitLimit must be at least 1") }28 if options.window < 1 { problems = problems.push("window must be at least 1 ms") }29 if options.queueLimit < 0 { problems = problems.push("queueLimit must not be negative") }30 problems31}323334export fn create(options: &Options) -> Result[Limiter.Limiter, Array[Str]] {35 let problems = validate(options)36 if !problems.isEmpty() { return Err(problems) }37 let queueing = Engine.Queueing{permitLimit: options.permitLimit, queueLimit: options.queueLimit, order: options.queueOrder}38 let start = Algorithms.Window{used: 0, start: Clock.now(&options.clock)}39 Ok(Engine.limiter(start, Algorithms.fixedWindow(options.permitLimit, options.window, options.autoReplenishment), &queueing, options.clock))40}41