
Persistence.pudu
Pudu34 lines1.8 KB
1/** @Domain.Persistence.Module — which connections stay open and which pooled ones are reused */2module PuduLangHttpClient.Domain.Persistence34import Std.Http.Message as Message5import PuduLangHttpClient.Domain.Expiry as Expiry6import PuduLangHttpClient.Domain.Headers as Headers78/** @Domain.Persistence.Idle — one pooled connection waiting for its next request */9export type Idle[C] = { link: C, created: Int, lastUsed: Int }1011/** @Domain.Persistence.Limits — how long a pooled connection may live and sit unused */12export type Limits = { lifetime: Int, idleTimeout: Int }1314151617export fn keepsAlive(version: Str, requestHeaders: &Array[(Str, Str)], responseHeaders: &Array[(Str, Str)], framing: &Message.Framing) -> Bool {18 let asked = Headers.values(requestHeaders, "connection").concat(Headers.values(responseHeaders, "connection"))19 let closing = asked.filter(|value: Str| Headers.lists(value, "close")).length() > 020 let legacy = version == "HTTP/1.0"21 let kept = asked.filter(|value: Str| Headers.lists(value, "keep-alive")).length() > 022 !closing && *framing != Message.UntilClose && (!legacy || kept)23}242526export fn usable[C](idle: &Idle[C], limits: &Limits, now: Int) -> Bool {27 !Expiry.elapsed(idle.created, limits.lifetime, now) && !Expiry.elapsed(idle.lastUsed, limits.idleTimeout, now)28}293031export fn sweep[C](idle: &Array[Idle[C]], limits: &Limits, now: Int) -> (Array[Idle[C]], Array[Idle[C]]) {32 (idle.filter(|one: Idle[C]| usable(&one, limits, now)), idle.filter(|one: Idle[C]| !usable(&one, limits, now)))33}34