Confirmation of Issue Source
Describe the Bug
PollTimer measures elapsed duration with time.time(), which is a wall clock and can move forward or backward after NTP corrections, manual clock changes, or VM suspend/restore. A forward adjustment can make an otherwise healthy deferred chat, collection indexing, or video-generation operation time out immediately. A backward adjustment can extend polling beyond the caller's requested timeout.
Both sync and async polling paths share this helper, so the behavior affects both clients.
Steps to Reproduce
On current main (4dab6a4), this deterministic reproduction simulates a forward wall-clock adjustment:
import datetime
from unittest.mock import patch
from xai_sdk.poll_timer import PollTimer
with patch("xai_sdk.poll_timer.time.time", side_effect=[100.0, 10_000.0]):
timer = PollTimer(
timeout=datetime.timedelta(seconds=10),
interval=datetime.timedelta(seconds=20),
)
print(timer.sleep_interval_or_raise())
Actual result:
TimeoutError: Polling timed out after 9900.0s
Expected result: elapsed timeout accounting should be unaffected by wall-clock changes. Python's time.monotonic() is intended for measuring durations and cannot go backward.
Proposed Fix
Use time.monotonic() for the start timestamp and elapsed-time calculation, with a focused regression test that changes the wall clock independently of monotonic elapsed time. This is an internal implementation change with no public API or normal-case timing change.
Confirmation of Issue Source
Describe the Bug
PollTimermeasures elapsed duration withtime.time(), which is a wall clock and can move forward or backward after NTP corrections, manual clock changes, or VM suspend/restore. A forward adjustment can make an otherwise healthy deferred chat, collection indexing, or video-generation operation time out immediately. A backward adjustment can extend polling beyond the caller's requested timeout.Both sync and async polling paths share this helper, so the behavior affects both clients.
Steps to Reproduce
On current
main(4dab6a4), this deterministic reproduction simulates a forward wall-clock adjustment:Actual result:
Expected result: elapsed timeout accounting should be unaffected by wall-clock changes. Python's
time.monotonic()is intended for measuring durations and cannot go backward.Proposed Fix
Use
time.monotonic()for the start timestamp and elapsed-time calculation, with a focused regression test that changes the wall clock independently of monotonic elapsed time. This is an internal implementation change with no public API or normal-case timing change.