diff --git a/README.md b/README.md index 1596b8ad..a8952d0a 100644 --- a/README.md +++ b/README.md @@ -707,7 +707,7 @@ All fields live on `CreditLeaseConfig`. Durations are seconds. Everything below | Option | Type | Default | Description | |---|---|---|---| | `mode` | `str` | `"auto"` | `client`, `server`, or `auto` (client when DataStream is running). | -| `default_reservation_ttl` | `float` | 60 | How long an unsettled hold survives. Capped at one hour in server mode. | +| `default_reservation_ttl` | `float` | 60 | How long an unsettled hold survives. Capped at 24 hours in server mode. | | `default_lease_duration` | `float` | 300 | Lease lifetime requested at acquire and extend. | | `default_lease_size` | `float` | 10000 | Credits requested per acquire, and the minimum extend tranche. | | `low_water_mark` | `float` | 0.25 | Extend in the background when the lease balance dips below this fraction. | diff --git a/src/schematic/client.py b/src/schematic/client.py index 2df4c24a..a5bdb734 100644 --- a/src/schematic/client.py +++ b/src/schematic/client.py @@ -86,7 +86,7 @@ # The longest hold the server will take. A longer configured TTL is clamped to # it, rather than sent and rejected on every check. -MAX_RESERVATION_TTL = 3600.0 +MAX_RESERVATION_TTL = 86400.0 # Room for the two clocks to disagree. expires_at is computed here and measured # against the server's own clock, so a TTL sitting exactly on the cap is # rejected whenever this process runs even slightly ahead. @@ -159,7 +159,7 @@ class CreditLeaseConfig: mode: CreditLeaseMode = "auto" # How long a hold survives unsettled. Size it above the longest expected # gap between check() and track_with_reservation(). Anything above the - # server's one hour cap is clamped, in server mode. Client mode keeps it: + # server's 24 hour cap is clamped, in server mode. Client mode keeps it: # the TTL only drives the local sweeper there. default_reservation_ttl: float = DEFAULT_RESERVATION_TTL # Lease lifetime requested at acquire and extend. Default 5 minutes. @@ -408,7 +408,7 @@ def _resolve_reservation_ttl(logger: logging.Logger, credit_leases: Optional[Cre Client mode is exempt: its TTL never reaches the server, it only tells the local sweeper when to refund an unsettled hold, and the caller may well - want one that outlives an hour. + want one that outlives a day. """ if credit_leases is None: return DEFAULT_RESERVATION_TTL @@ -418,7 +418,7 @@ def _resolve_reservation_ttl(logger: logging.Logger, credit_leases: Optional[Cre effective = MAX_RESERVATION_TTL - RESERVATION_TTL_SKEW_ALLOWANCE if ttl > effective: logger.warning( - f"credit_leases.default_reservation_ttl of {ttl}s is above the server's one hour cap; " + f"credit_leases.default_reservation_ttl of {ttl}s is above the server's 24 hour cap; " f"server-mode holds will be clamped to {effective}s" ) return effective diff --git a/tests/custom/test_client.py b/tests/custom/test_client.py index 90080bd7..fa1ca96b 100644 --- a/tests/custom/test_client.py +++ b/tests/custom/test_client.py @@ -1842,13 +1842,13 @@ def test_an_integral_float_usage_reaches_the_preflight_unchanged(self): ) def test_a_reservation_ttl_above_the_cap_is_clamped(self): - client = self._client(credit_leases=CreditLeaseConfig(default_reservation_ttl=7200.0)) + client = self._client(credit_leases=CreditLeaseConfig(default_reservation_ttl=90000.0)) try: # Short of the cap by the skew allowance, so a client running # slightly fast still asks for something the server accepts. self.assertEqual(client._reservation_ttl, MAX_RESERVATION_TTL - RESERVATION_TTL_SKEW_ALLOWANCE) warning = " ".join(str(call.args[0]) for call in client.logger.warning.call_args_list) - self.assertIn("one hour cap", warning) + self.assertIn("24 hour cap", warning) self.assertIn( f"server-mode holds will be clamped to {MAX_RESERVATION_TTL - RESERVATION_TTL_SKEW_ALLOWANCE}s", warning, @@ -2293,11 +2293,11 @@ async def test_a_fractional_usage_rounds_the_hold_and_the_preflight_up(self): assert kwargs["preflight"] == PreflightRequestBody(usage=3) async def test_a_reservation_ttl_above_the_cap_is_clamped(self): - client = _async_server_client(credit_leases=CreditLeaseConfig(default_reservation_ttl=7200.0)) + client = _async_server_client(credit_leases=CreditLeaseConfig(default_reservation_ttl=90000.0)) try: assert client._reservation_ttl == MAX_RESERVATION_TTL - RESERVATION_TTL_SKEW_ALLOWANCE warning = " ".join(str(call.args[0]) for call in client.logger.warning.call_args_list) - assert "one hour cap" in warning + assert "24 hour cap" in warning assert ( f"server-mode holds will be clamped to {MAX_RESERVATION_TTL - RESERVATION_TTL_SKEW_ALLOWANCE}s" in warning @@ -2995,16 +2995,16 @@ async def test_a_lease_gated_check_reports_one_flag_check_event(self): async def test_client_mode_keeps_a_reservation_ttl_past_the_server_cap(self): client = _async_lease_client( credit_leases=CreditLeaseConfig( - mode="client", default_lease_size=1000.0, default_reservation_ttl=7200.0 + mode="client", default_lease_size=1000.0, default_reservation_ttl=90000.0 ) ) try: # The TTL only drives the local sweeper here, so the server's cap # does not apply and nothing is clamped or warned about. - assert client._reservation_ttl == 7200.0 - assert client._lease_manager.resolve_config("bilcr_inference").reservation_ttl == 7200.0 + assert client._reservation_ttl == 90000.0 + assert client._lease_manager.resolve_config("bilcr_inference").reservation_ttl == 90000.0 warning = " ".join(str(call.args[0]) for call in client.logger.warning.call_args_list) - assert "one hour cap" not in warning + assert "24 hour cap" not in warning finally: await self._drain(client)