[PR #150] fix: track process-result delivery separately from a fixed 5-minute expiry #140

Open
opened 2026-10-18 21:11:09 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-terminal/pull/150
Author: @dvystrcil
Created: 8/1/2026
Status: 🔄 Open

Base: main ← Head: fix/two-tier-process-expiry


📝 Commits (1)

  • 9049e21 fix: track process-result delivery separately from a fixed 5-minute expiry

📊 Changes

3 files changed (+61 additions, -8 deletions)

View changed files

📝 CHANGELOG.md (+6 -0)
📝 open_terminal/env.py (+24 -0)
📝 open_terminal/main.py (+31 -8)

📄 Description

Problem

A finished process's in-memory record (and therefore its result) is deleted 5 minutes after completion, regardless of whether anyone has actually retrieved it yet. I hit this with a caller whose own async dispatch loop stalled well past that window -- it came back to a bare {"detail": "Process not found"}, even though the command had genuinely run and finished successfully. There's no way for a well-behaved caller to distinguish "result is gone because nobody read it in time" from "this process ID never existed."

Concretely: submit a long or slow-to-retrieve job, have the caller's own polling loop stall for >5 minutes (network hiccup, downstream LLM call, whatever), and the result is just gone by the time it asks -- a completed command's output becomes unrecoverable, silently.

Fix

Adds delivered_at, tracked separately from finished_at, to BackgroundProcess. A result that's been successfully read at least once (via the initial synchronous /execute response when wait is set, or a /execute/{id}/status poll) only needs the original short expiry (OPEN_TERMINAL_PROCESS_EXPIRY, still defaults to 5 minutes -- unchanged) since the caller already has it. A result nobody has read yet gets a much longer grace period (OPEN_TERMINAL_PROCESS_UNDELIVERED_EXPIRY, defaults to 30 minutes), so a stalled-but-recoverable caller can still get its result when it eventually asks.

Both new settings follow the existing env-var/config.toml pattern (see OPEN_TERMINAL_LOG_RETENTION).

Testing

No test harness exists in this repo currently, so verified two ways:

  • 5 unit-level scenarios against _cleanup_expired() directly: an undelivered result survives past the short window, expires after the long window; a delivered result expires on the short window even with long-window headroom remaining; a running process never expires.
  • End-to-end against the real running server: submitted a job via POST /execute, polled GET /execute/{id}/status, confirmed the output is delivered correctly and delivered_at accounting matches.

Happy to add these as real pytest cases in this PR if that's useful, or split this into a smaller diff if you'd rather review the expiry-tracking and the two new response call-sites separately.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-terminal/pull/150 **Author:** [@dvystrcil](https://github.com/dvystrcil) **Created:** 8/1/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/two-tier-process-expiry` --- ### 📝 Commits (1) - [`9049e21`](https://github.com/open-webui/open-terminal/commit/9049e21016e422e0e9ab853c1fcf3ef51b833439) fix: track process-result delivery separately from a fixed 5-minute expiry ### 📊 Changes **3 files changed** (+61 additions, -8 deletions) <details> <summary>View changed files</summary> 📝 `CHANGELOG.md` (+6 -0) 📝 `open_terminal/env.py` (+24 -0) 📝 `open_terminal/main.py` (+31 -8) </details> ### 📄 Description ## Problem A finished process's in-memory record (and therefore its result) is deleted 5 minutes after completion, regardless of whether anyone has actually retrieved it yet. I hit this with a caller whose own async dispatch loop stalled well past that window -- it came back to a bare `{"detail": "Process not found"}`, even though the command had genuinely run and finished successfully. There's no way for a well-behaved caller to distinguish "result is gone because nobody read it in time" from "this process ID never existed." Concretely: submit a long or slow-to-retrieve job, have the caller's own polling loop stall for >5 minutes (network hiccup, downstream LLM call, whatever), and the result is just gone by the time it asks -- a completed command's output becomes unrecoverable, silently. ## Fix Adds `delivered_at`, tracked separately from `finished_at`, to `BackgroundProcess`. A result that's been successfully read at least once (via the initial synchronous `/execute` response when `wait` is set, or a `/execute/{id}/status` poll) only needs the original short expiry (`OPEN_TERMINAL_PROCESS_EXPIRY`, still defaults to 5 minutes -- unchanged) since the caller already has it. A result nobody has read yet gets a much longer grace period (`OPEN_TERMINAL_PROCESS_UNDELIVERED_EXPIRY`, defaults to 30 minutes), so a stalled-but-recoverable caller can still get its result when it eventually asks. Both new settings follow the existing env-var/`config.toml` pattern (see `OPEN_TERMINAL_LOG_RETENTION`). ## Testing No test harness exists in this repo currently, so verified two ways: - 5 unit-level scenarios against `_cleanup_expired()` directly: an undelivered result survives past the short window, expires after the long window; a delivered result expires on the short window even with long-window headroom remaining; a running process never expires. - End-to-end against the real running server: submitted a job via `POST /execute`, polled `GET /execute/{id}/status`, confirmed the output is delivered correctly and `delivered_at` accounting matches. Happy to add these as real pytest cases in this PR if that's useful, or split this into a smaller diff if you'd rather review the expiry-tracking and the two new response call-sites separately. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No labels
bug
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-webui/open-terminal#140
No description provided.