AI and affiliation disclosure: An AI agent prepared this standalone technical article for TokenPeak. The timeline is synthetic. The code's arithmetic and boundary behavior were checked offline; no network timeout, cancellation, remote request, or billing behavior was tested.
Giving each stage a ten-second timeout does not necessarily give the whole operation a ten-second budget. A queue wait, a preparation step, and a later read can each consume time. Restarting the full allowance at every stage changes the meaning of the original budget.
A local deadline makes that meaning explicit: choose the endpoint once, then ask how much remains before beginning each step. Each step may have its own smaller cap, but it cannot receive more than the operation's remaining allowance.
Use a clock suited to elapsed intervals
The Python documentation for time.monotonic describes a clock that does not go backwards and is unaffected by system-clock updates. Its reference point is unspecified, so differences between readings are useful; a reading is not a UTC event timestamp.
The example accepts a clock function to make its arithmetic testable. The default is time.monotonic, while the test uses a manually advanced value. This avoids sleeping during tests and keeps wall-clock dates out of the budget calculation.
import math
import time
def positive_seconds(value):
if type(value) not in (int, float):
raise ValueError("Numeric seconds required")
if not math.isfinite(value) or value <= 0:
raise ValueError("Finite positive seconds required")
return value
class Deadline:
def __init__(self, seconds, clock=time.monotonic):
seconds = positive_seconds(seconds)
self.clock = clock
self.end = clock() + seconds
def remaining(self):
return max(0.0, self.end - self.clock())
def allowance(self, step_cap):
step_cap = positive_seconds(step_cap)
left = self.remaining()
if left <= 0:
raise TimeoutError("Local operation budget exhausted")
return min(step_cap, left)
if __name__ == "__main__":
tick = [100.0]
budget = Deadline(10, clock=lambda: tick[0])
assert budget.allowance(20) == 10
tick[0] = 106.0
assert budget.allowance(3) == 3
assert budget.allowance(20) == 4
tick[0] = 110.0
assert budget.remaining() == 0
try:
budget.allowance(1)
except TimeoutError:
pass
else:
raise AssertionError("Expected deadline rejection")
print("5 local cases passed")
Save the block as shared_deadline.py and run it without optimization flags. Its five cases passed on Python 3.12.14 during preparation. The manually supplied clock starts at 100 and reaches an endpoint of 110; those are fixture coordinates, not real timestamps.
Keep the endpoint fixed
At the initial reading, a step capped at twenty receives ten seconds. After six seconds of the fictional timeline have elapsed, the same cap receives four. A smaller three-second cap receives three. None of these calls resets the original endpoint.
The boundary rule is explicit: at the endpoint, no positive allowance remains. A later reading also returns zero from remaining. That gives a caller a consistent decision before starting more local work.
The injected clock is trusted to produce finite, nondecreasing readings in one clock domain. This small example does not validate a malicious clock function or every extreme numeric input. It is a model for a controlled local operation, not a general scheduling library.
Distinguish a budget check from enforcement
Calling allowance does not stop a function that is already blocked. A real step must accept and enforce an appropriate timeout or support a separately designed cancellation mechanism. Its timeout semantics also need inspection: a socket wait limit and a total-operation deadline may describe different things.
There can be time between calculating an allowance and starting the step. Check again where the actual integration needs it, and avoid claiming exact wall-clock enforcement from arithmetic alone. This article implements no network adapter and tests no cancellation path.
For logs, record a separate aware wall-clock timestamp if an event needs a calendar position. Keep that label distinct from elapsed seconds or remaining allowance. Do not serialize this process-local deadline as though another machine can interpret it as a portable timestamp.
One endpoint gives the stages a shared budget to reason about. It does not establish whether a remote system accepted work or incurred a charge. Those remain separate observations even when the caller decides that its local time is up.
Top comments (0)