Repository navigation
Isolate serve I/O, fix mutate and snapshot honesty, and stop false orphan prunes - #206
Merged
Merged
Conversation
Concurrent serve commands captured stdout on process-global streams, so envelopes could swap. Each request now uses context-local streams. Mutate splits on LF only, snapshot save keeps undeclared properties and a missing id column, and housekeep resolves edge ends by hid and nickname before prune --apply will delete anything. Co-authored-by: chouswei <chouswei@users.noreply.github.com>
chouswei
marked this pull request as ready for review
October 8, 2026 17:40
chouswei
added a commit
that referenced
this pull request
Oct 8, 2026
Hatch, project.toml, changelog, and the version map name the serve request isolation and housekeep endpoint fixes (#206). Not 0.20.
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.
Summary
Endleaf Keeper reports against 0.19.18 and 0.19.20, plus a housekeep data-loss hazard. No version bump and no release.
memnet servecommands no longer share stdout/stderr. Each request captures streams on contextvars. TCP andmemnet-mcp --transport gatewayare covered. No serve-wide lock. Listen backlog is 128.splitlinesseparators stay inside the value.idwhen the live SCHEMA omitted it. An unloadable key fails closed.MATCH (n:Label) SETcase-folds the label.MATCH … MATCH … CREATEstaysparse_error. TTL is minutes; expiry is checked on access.prune orphans/prune stale --applyrefuseprune_referencedinstead of deleting a node an edge still names.pi-endleaf,MEMNET_GATEWAY_TOKEN, HTTP status for every gateway code, decision 11 closed, concurrency).Root cause (serve output mix-up)
_handle_requestand in-processrun_argvassignedsys.stdout,sys.stderr, andsys.stdinto one shared pair of buffers for the duration of the command. The TCP server is aThreadingTCPServer, so two commands in flight wrote into whichever buffer was installed last. Exit codes are locals and did not themselves swap; the success text (ok=1 fail=0and the other session's records) did, so a failed write could look successful.Throughput
No serve-wide lock. On this VM, 12 successful TCP mutates at once took 0.494 s against 0.525 s one after another (ratio 0.94). The work is CPU-bound under the GIL, so the overlap is small. The added cost is a contextvar lookup per write, not a queue.
Answers
Cst) while the SCHEMA tag isCST, so the extra never reached the emitted map. Fixed by canonical tag. A SCHEMA withoutidis still legal at open (id need not be first or present). Save appendsidon the snapshot SCHEMA and mints a nickname. The live map is unchanged until load. A key that cannot reload (foo bar) issnapshot_unsaveable.id_conflictbecause the stored tag was the raw spelling. Labels now case-fold. A different known label that matches nothing isnot_found.parse_error. The comma form with--allow-new-relationcreates the edge.--ttlis minutes (1..1440). 130 s idle is inside 60 minutes. There is no background sweeper.purge_expiredruns on access, and a successful access slides the deadline. Access after real expiry refusessession_expired._elN. The orphan check compared each node's nickname to those ids, so every node looked unreferenced andprune orphans --applywould delete them. Nothing automatic runsprune --apply(no sweep, no MCP tool). Only the CLI does, and only with--apply.Test plan
pytest(full suite, one live AgensGraph test skipped)ruff checkandruff format --checkon the CI paths