Skip to content

post-commit graphify rebuild leaves stale .rebuild.lock with accumulating PIDs (no newline separator) #858

Closed

Description

@cnchg

Summary

After a successful background rebuild kicked off by the auto-installed post-commit hook, graphify-out/.rebuild.lock is not deleted. Worse, each subsequent rebuild appears to append its PID to the file (no newline separator), so the lock file grows into a long concatenation of digits over time.

Two practical problems result:

  1. Any consumer that waits on the lock to clear before doing post-rebuild work (e.g. a publish script copying graph.html to a web root) blocks forever / until its own timeout.
  2. The accumulated PID string makes the lock unparseable by humans or downstream tooling.

Reproduction

# In any repo with `graphify hook install` set up:
git commit -m "trigger rebuild"   # post-commit launches background graphify rebuild
# wait for the rebuild log to say "Rebuilt: N nodes, M edges, ..."

ls -la graphify-out/.rebuild.lock
# -> file still exists despite rebuild having finished

cat graphify-out/.rebuild.lock
# observed on a project after ~9 rebuilds:
# 142313214261481429191143626914397531450233145457914587111478496
# (no newline; that's 9 concatenated 7-digit PIDs)

Observed environment

  • graphify (PyPI graphifyy) — recent (Python 3.11 via pipx)
  • Hook installed via graphify hook install
  • The rebuild path involved is graphify.watch._rebuild_code (called by the body of .git/hooks/post-commit)
  • OS: Rocky Linux 9.6

Why this matters

The auto-installed post-commit hook returns immediately and spawns the rebuild detached. Users typically chain follow-up work behind the lock — e.g. the aioffice-publish-start block I have on top of graphify's hook waits up to 15 min for .rebuild.lock to disappear before publishing the graph to a webroot. When the lock never disappears, the chain stalls until its own timeout, and the public-facing graph silently goes stale.

It also means processes that read the lock to find the owning PID can't — there's no separator.

Suspected fix

In graphify/watch.py (where .rebuild.lock is written), the rebuild path should:

  1. Write the lock atomically and overwrite rather than append (mode='w', not mode='a').
  2. Wrap the rebuild in a try / finally so the lock is removed even on exception or timeout.
  3. Optionally include a trailing newline + the current PID so external waiters can kill -0 $(cat lock) to detect a stale-owner case.

Happy to PR if the diagnosis matches the actual code path.

Cross-reference

Discovered in the same session as #857 — both bugs surfaced while debugging why session-log nodes weren't appearing connected in the knowledge graph. See https://github.com/cnchg/digitalleafco/blob/main/docs/sessions/2026-05-13-graphify-extract-cache-bug.md for the full investigation log.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions