diff options
| -rw-r--r-- | lua/clever_f/repeat_resolver.lua | 36 | ||||
| -rw-r--r-- | tests/run.lua | 17 |
2 files changed, 53 insertions, 0 deletions
diff --git a/lua/clever_f/repeat_resolver.lua b/lua/clever_f/repeat_resolver.lua index e246ef8..5e1dc41 100644 --- a/lua/clever_f/repeat_resolver.lua +++ b/lua/clever_f/repeat_resolver.lua @@ -18,6 +18,22 @@ local function fail(message, level) error(message, (level or 1) + 1) end +local function is_nonnegative_integer(value) + return type(value) == "number" + and value >= 0 + and value < math.huge + and value == math.floor(value) +end + +local function require_policy(service) + if service ~= nil and (type(service) ~= "table" + or type(service.sample_timeouts) ~= "function") + then + fail("RepeatResolver policy must provide sample_timeouts", 3) + end + return service +end + local resolver_metatable = { __index = RepeatResolver, __newindex = function() @@ -48,6 +64,7 @@ function RepeatResolver.new(options) local resolver = setmetatable({}, resolver_metatable) resolver_records[resolver] = { + policy = require_policy(options.policy or options.policy_service), state = state, } return resolver @@ -77,6 +94,21 @@ end RepeatResolver.eligibility = RepeatResolver.decide RepeatResolver.resolve_eligibility = RepeatResolver.decide +function RepeatResolver:sample_repeat_timeout_ms() + local service = resolver_records[self].policy + if service == nil then + fail("RepeatResolver requires a policy to sample repeat timeout", 2) + end + local sampled = service:sample_timeouts() + local timeout = type(sampled) == "table" and sampled.repeat_timeout_ms or nil + if not is_nonnegative_integer(timeout) then + fail("repeat_timeout_ms sample must be a nonnegative integer", 2) + end + return timeout +end + +RepeatResolver.sample_repeat_timeout = RepeatResolver.sample_repeat_timeout_ms + function M.new(options) return RepeatResolver.new(options) end @@ -95,6 +127,10 @@ end M.eligibility = M.decide +function M.sample_repeat_timeout_ms(options) + return RepeatResolver.new(options):sample_repeat_timeout_ms() +end + setmetatable(M, { __call = function(_, options) return RepeatResolver.new(options) diff --git a/tests/run.lua b/tests/run.lua index b010908..a2bf7e1 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -3843,6 +3843,23 @@ test("Primary eligibility repeats at a matching numeric landing", function() ) end) +test("Repeated primary timeout is sampled from live policy", function() + fresh_sequence_state() + local host = MemoryHost.new({ + configuration = { repeat_timeout_ms = 75 }, + }) + local resolver = repeat_resolver.new({ + policy = policy.new(host), + }) + + same(75, resolver:sample_repeat_timeout_ms()) + host:set_configuration("repeat_timeout_ms", 125) + same(125, resolver:sample_repeat_timeout_ms()) + fails(function() + repeat_resolver.new():sample_repeat_timeout_ms() + end, "requires a policy") +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then |
