Skip to content

Fix PythonWorker cold start drop issue#289

Open
Abhi-1100 wants to merge 3 commits into
Fincept-Corporation:mainfrom
Abhi-1100:fix/python-worker-cold-start-drop
Open

Fix PythonWorker cold start drop issue#289
Abhi-1100 wants to merge 3 commits into
Fincept-Corporation:mainfrom
Abhi-1100:fix/python-worker-cold-start-drop

Conversation

@Abhi-1100
Copy link
Copy Markdown
Contributor

Summary

Fixed a critical bug where early market data requests were silently dropped
during application cold starts. Asynchronous Python detection caused the
PythonWorker daemon to drop incoming requests before the environment was
fully initialized, leaving watchlist rows, market panels, and equity screens
stuck on spinners or -- values with no way to recover without a restart.

Changes Made

  • Added python_ready() signal to PythonRunner that emits upon successful
    completion of asynchronous Python detection.
  • Implemented route_yfinance_to_daemon() in PythonRunner to intercept
    yfinance_data.py calls and accurately route them, returning false early
    to allow fallback to the subprocess queue when Python is not yet available.
  • Connected the python_ready signal in the PythonWorker constructor to
    automatically trigger ensure_started() once Python resolves.
  • Added a non-blocking QTimer::singleShot 500ms deferred retry loop inside
    PythonWorker::launch_process() to safely hold and queue requests without
    blocking the UI thread while waiting for the Python executable.
  • Verified that PythonWorker::dispatch_queued() natively drains all pending
    requests correctly upon the daemon's ready handshake.

User Impact

  • The application UI remains completely responsive during initial launch and
    background Python detection.
  • Live market data panels such as the Watchlist successfully populate on
    launch without silently failing or requiring manual user refreshes.
  • Background Python environment resolution is now synchronized with incoming
    data requests — queued calls resolve the moment the daemon is ready.

Testing Performed

  • Simulated a delayed cold-start state to force Python detection to take
    several seconds.
  • Triggered rapid market data queries across the application during the
    detection period.
  • Verified the main UI thread remains completely responsive and non-blocking
    throughout.
  • Confirmed all queued data successfully populates across the UI the exact
    moment the Python daemon finishes its background boot sequence.

Files Modified

  • fincept-qt/src/python/PythonRunner.h
  • fincept-qt/src/python/PythonRunner.cpp
  • fincept-qt/src/python/PythonWorker.cpp

Adds python_ready signal, queue draining, and deferred retry mechanism.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

Hi @Abhi-1100 — thanks for the PR!

Our automated scope gate flagged the following:

No scope-approved linked issue. This PR must close an issue that carries one of: good-first-issue, help-wanted, scope:approved. Link it in the PR body with Closes #NNN or via GitHub's "Linked issues" sidebar.

Please read CONTRIBUTING.md. Once an issue with the appropriate label exists and is linked here, re-run this check by pushing an empty commit or editing the PR description. A maintainer can also bypass this gate by adding the scope:approved label to this PR.

PRs that remain unresolved for 7 days will be closed automatically.

@github-actions github-actions Bot added the needs-scope-approval Auto-applied by pr-gate.yml to PRs that fail the scope gate. label May 18, 2026
@Abhi-1100
Copy link
Copy Markdown
Contributor Author

Summary

Fixed a critical bug where AI chat assistant replies were being persisted
to whichever session the user was currently viewing at response completion
time, rather than the session that originally sent the request. If a user
switched sessions or changed their active LLM provider/model during an
active stream, the incoming reply would be committed to the newly selected
session's database table — contaminating chat history and breaking session
persistence.

Changes Made

1. Added request-time state snapshot variables

Added three member variables to AiChatScreen.h to act as an asynchronous
request snapshot, holding context at the exact moment the user hits send:

QString pending_req_session_;
QString pending_req_provider_;
QString pending_req_model_;

2. Snapshotting context on dispatch

In AiChatScreen::on_send() inside AiChatScreen_Messaging.cpp, the active
session, active provider, and active model are now captured at the exact moment
the user initiates the prompt and stored in the member snapshot variables:

pending_req_session_ = active_session_id_;
pending_req_provider_ = LlmService::instance().active_provider();
pending_req_model_ = LlmService::instance().active_model();

3. Persisting to the original session

In AiChatScreen::on_streaming_done(), the database transaction now uses the
captured request snapshot rather than the live UI state at completion time:

ChatRepository::instance().add_message(
pending_req_session_, "assistant", content,
pending_req_provider_, pending_req_model_,
response.total_tokens);

4. Cleanup and lifecycle management

  • Pending context variables are cleared immediately after on_streaming_done
    completes, including on early error paths, to prevent stale context
    carry-over into subsequent requests.
  • Removed unused handle_response() prototype declaration from
    AiChatScreen.h that was left over from a previous implementation.

User Impact

  • Assistant replies always land in the session that asked the question
    regardless of which session the user is viewing when the response completes.
  • Users can freely switch sessions or change LLM provider/model while
    waiting for a long response without corrupting either the source or
    destination session's chat history.
  • Provider and model name persisted on each reply correctly reflects what
    was active when the message was sent, not when the stream finished.
  • Single session usage and non-streaming path are fully unaffected.

Testing Performed

  • Sent a long prompt from Session A, switched to Session B mid-stream —
    verified reply landed in Session A and Session B was untouched.
  • Switched LLM provider mid-stream — verified persisted model name matches
    the provider active at send time, not at completion time.
  • Sent simultaneous long prompts from Session A and Session B — verified
    each reply landed in its correct source session with no cross-contamination.
  • Verified pending context variables are fully cleared after each completion
    including on error paths — no stale context carries over to next request.
  • Verified single session usage shows no regression — replies appear in
    correct order with no duplicates or missing bubbles.

Files Modified

  • fincept-qt/src/screens/ai_chat/AiChatScreen.h
  • fincept-qt/src/screens/ai_chat/AiChatScreen_Messaging.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-scope-approval Auto-applied by pr-gate.yml to PRs that fail the scope gate.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant