Merge pull request #197 from openqj/feat-stream-waiting

feat: browser stream waits through round gaps instead of disconnecting
This commit is contained in:
openqj authored and GitHub committed 2026-10-30 15:29:17 +08:00
commit e2ce04ce4f
4 files changed
+137 -22

No files matched your search

+45
View File
@@ -174,6 +174,51 @@ class BrowserProxyTestCase(unittest.TestCase):
finally:
conn.close()
def test_stream_waits_through_stale_state(self):
"""A stale state must not drop a live task's watch.
Regression for the 2026-10-30 demo watch: the old loop
broke on the first stale read, so every round gap (and
every worker restart) killed the stream. Now a stale
state switches to a waiting heartbeat while the task is
still alive, and only a terminal task status ends it.
"""
Path(self.wt, ".browser-remote-frame.jpg").write_bytes(b"JPEG1")
self._write_state("agent")
conn = http.client.HTTPConnection("127.0.0.1", self.port,
timeout=30)
try:
conn.request("GET", "/tasks/task-b1/browser/stream",
headers={"X-API-Key": self.owner_key})
resp = conn.getresponse()
self.assertEqual(resp.status, 200)
# Each SSE event is two lines: data + blank separator.
line = resp.readline().decode("utf-8")
payload = json.loads(line[6:])
self.assertEqual(payload["image"], "JPEG1")
self.assertEqual(resp.readline().decode("utf-8"), "\n")
# Round gap: state goes stale. The stream must stay
# open and emit a waiting heartbeat within ~5s.
self._write_state("agent", fresh=False)
line = resp.readline().decode("utf-8")
self.assertTrue(line.startswith("data: "), line)
payload = json.loads(line[6:])
self.assertTrue(payload.get("waiting"))
self.assertEqual(payload.get("task_status"), "running")
self.assertEqual(resp.readline().decode("utf-8"), "\n")
# Terminal task status ends the stream.
db = sqlite3.connect(self.db_path)
try:
db.execute("UPDATE tasks SET status = 'completed'"
" WHERE id = 'task-b1'")
db.commit()
finally:
db.close()
line = resp.readline().decode("utf-8")
self.assertEqual(line, "")
finally:
conn.close()
if __name__ == "__main__":
unittest.main()