Backend resilience: LLM retry/backoff, OpenAI-compatible embeddings, connection guards - #50
Open
shivswami wants to merge 1 commit into
Open
Backend resilience: LLM retry/backoff, OpenAI-compatible embeddings, connection guards#50shivswami wants to merge 1 commit into
shivswami wants to merge 1 commit into
Conversation
…guards - llm_client: retry transient failures (429/5xx/timeout/connection) with exponential backoff honoring Retry-After; non-retryable errors fail fast - embedding_service: support OpenAI-compatible /v1/embeddings servers (e.g. LMStudio) alongside Ollama, auto-detected from EMBEDDING_BASE_URL - neo4j_storage: verify Neo4j reachable before create_graph/add_text; log batch-embedding failures as errors (empty vectors silently break vector search) - graph build: fail the task explicitly when NER extracts 0 entities instead of reporting a misleading "completed" status
Pxls21
added a commit
to Pxls21/MiroFish-Offline
that referenced
this pull request
Jul 11, 2026
…knobs; hunks rejected where broken or regressive TAKEN: env-tunable parallelism (GRAPH_BUILD_BATCH_SIZE, PROFILE_PARALLEL_COUNT, PROFILE_SEARCH_WORKERS); ThreadPool chunk processing in graph_builder + neo4j add_text_batches; parallel edge/node searches + background profile writes in oasis_profile_generator; max_tokens=4000 on profile JSON calls (anti vLLM-infinite-generation), merged as a union with PR nikmcfly#34 enable_thinking. REJECTED (with reasons): - run.py debug=True hardcode + .env DEBUG=True: author debug leftovers - embedding_service URL hack (broken string-comment splice): PR nikmcfly#50 already landed the correct OpenAI-format auto-detect version - ALL report_agent.py hunks: they REGRESS prompts to Chinese-language guidance (undoing upstream 313fe64 English-only), gut the ReACT loop (min_tool_calls 3->0), and drop inter-section context in parallel gen - REPORT_PARALLEL_SECTIONS knob removed from config/.env: its only consumer was the rejected report_agent hunk; a dead knob is a lying knob
nocode-ananas
added a commit
to nocode-ananas/polylop
that referenced
this pull request
Jul 24, 2026
…j connection guards, 0-entities => FAILED - llm_client.py: retry loop (429/5xx, Retry-After, exp. backoff 2-60s) merged onto Polylop base (24h timeout, JSON repair, for_graph_extraction kept) - neo4j_storage.py: health_check + _verify_connection guards, louder embedding-failure log - api/graph.py: build task with 0 extracted entities now marked FAILED instead of completed - embedding_service.py part of PR nikmcfly#50 NOT taken: Polylop already has the better implementation (Bearer token + index sort) from PR nikmcfly#41 backport - verified: 4 fault-injection tests in container (retry, exhaustion, non-retryable, backoff timing)
nocode-ananas
added a commit
to nocode-ananas/polylop
that referenced
this pull request
Jul 24, 2026
nocode-ananas
added a commit
to nocode-ananas/polylop
that referenced
this pull request
Jul 24, 2026
requestWithRetry() wrapped eight POST endpoints with a 3x retry and exponential backoff. A slow but successful call (a long Mistral run behind /simulation/start or /graph/build) hits the client timeout, gets retried, and starts a second and third run server-side - the user sees one hung click and gets three simulations. Retry removed from all POST call sites (graph: ontology/generate, build; simulation: create, prepare, start, interview/batch; report: generate, chat). The helper stays exported for idempotent GET/polling use and now says so. Audit 2026-06-13, wave 2. Not covered by the PR nikmcfly#50/nikmcfly#51 backport - those touched retry inside the LLM client, not the browser API layer.
nocode-ananas
added a commit
to nocode-ananas/polylop
that referenced
this pull request
Jul 24, 2026
Fixes the simulation lifecycle bugs from the 2026-06-13 audit (section B). No upstream PR covers these — nikmcfly nikmcfly#30/nikmcfly#41/nikmcfly#50/nikmcfly#51 are already backported and address other areas. Every finding was reproduced against the unpatched code before fixing, using backend/tests/test_simulation_lifecycle.py: 11/31 checks pass on the baseline, 31/31 with this patch. Stop had no effect on reconnected simulations stop_simulation only ever looked at cls._processes, which is empty after a backend restart. The status flipped to 'stopped' while the process kept running — and kept calling the LLM API, costing real money. Added a PID-based termination path (SIGTERM, then SIGKILL) for simulations we have no Popen handle for. Manually stopped runs were reported as failed/completed The monitor thread woke up to the SIGTERM exit code and overwrote the stop with 'failed'; the orphan monitor could report 'completed'. An explicit stop is now recorded and wins over the exit-code verdict. stop_simulation also waits for the monitor instead of racing it. Double start was possible Nothing serialized check-and-spawn, so concurrent /start requests (the axios interceptor retries POSTs up to 3x) each spawned a process into the same directory. Added a per-simulation lock, and a liveness check so a start is refused while the real process is alive even if the status file claims otherwise. state.json and run_state.json drifted apart Nothing wrote the terminal status into state.json when a simulation ended on its own, so finished runs kept showing as running (live: sim_cb2ebb78e07a, run_state 'completed' vs state.json 'running'). The runner now mirrors its terminal status into state.json through one shared, atomic writer. /stop records STOPPED instead of PAUSED — the process is terminated, not suspended, no view renders 'paused', and PAUSED overwrote the runner's own status. PID reuse could adopt an unrelated process os.kill(pid, 0) only proves some process holds that PID. The start command line is now recorded and verified before a process is adopted or signalled; an unverifiable PID closes the run instead of hanging it on 'running' forever. psutil is not in the runtime image, so this is stdlib only (/proc, with a ps fallback for macOS). Also in this change - run_state.json is written atomically; concurrent readers used to see truncated JSON (40008 corrupted reads in a 2s test on the old code) - a 'running' state with no PID no longer hangs forever on reconnect - failed runs get a completed_at timestamp like every other terminal state - the orphan reconnect is skipped in the Flask reloader's parent process: with DEBUG on, create_app runs twice, and two monitor threads in two processes were writing the same run_state.json Not touched on purpose: FLASK_HOST/DEBUG/NEO4J_PASSWORD hardening, declined 2026-07-15. The reloader guard above makes the lifecycle robust against debug mode instead of turning it off.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Improves backend robustness for local deployments (Ollama / LMStudio / Neo4j in Docker) where services are flaky or use non-Ollama providers.
Why
Changes
llm_client.py— retry transient failures (429 / 5xx / timeout / connection) with exponential backoff (2/4/8…s, capped at 60s), honoringRetry-After; non-retryable errors fail fast. Configurable viaLLM_MAX_RETRIES.embedding_service.py— support OpenAI-compatible/v1/embeddingsendpoints alongside Ollama; format auto-detected fromEMBEDDING_BASE_URL.neo4j_storage.py—health_check()+ pre-flight_verify_connection()beforecreate_graph/add_text; batch-embedding failures now logged as errors (empty vectors silently break vector search).graph.py— a build that extracts 0 entities now fails the task explicitly with an actionable message instead of showing "completed".Notes / limitations
:11434→ Ollama;/v1in path → OpenAI). A non-default Ollama port behind a/v1proxy could misdetect._verify_connectionadds oneRETURN 1round-trip before eachadd_text.Tested
backend/venv).