Skip to content

The daemon writes the agent register under the name it should have, not the one it has #2549

Closed

Description

@argszero

Observed

EmrgServer.__init__ builds the daemon's agent registry from the register's canonical
path, not from the one the register is actually at:

# emrg/server/daemon.py:872
self._agents_log = agents_file(runtime_dir)

That handle is both read and written: _register_agent calls AgentRegistry.for_dir,
which runs on every session open (emrg/server/daemon.py:2931, :3847).

Every other register reader in the package goes through
emrg.config.register_for_reading (#2545), which answers the file that exists -- a
register still carrying its pre-rename name projects.yml is a state
migrate_legacy_registry documents and tolerates: a read-only home, a permission
boundary, a concurrent caller that got there first each leave the legacy file exactly
where it is, and the daemon still starts.

AgentRegistry._read answers a missing file with [] (emrg/server/agents.py),
and for_dir writes back what it read. So on such a host the first session opened reads
"no rows" and creates a new agents.yml holding exactly the one row it just
registered.

register_for_reading prefers the new name whenever it exists (deliberately, so an
older daemon that re-creates the legacy file cannot shadow the current register), so
from that moment every reader in the package answers the one-row register and every
entry left in the legacy file is gone from view -- silently: nothing raised, nothing was
logged, and _read never saw those rows at all.

Why this is the same defect as #2548, one call site over

#2548 removed exactly this shape from the scheduler's self-heal and left the daemon's
handle alone on the argument that the startup migration moves the register before the
server object exists. That argument holds on a healthy host and fails on the host the
derivation exists for: the migration is documented to be able to fail, and
register_for_reading was introduced because that state is reachable.

Expected

The invariant #2548 stated -- read and write address one file, and it is the file the
register is actually at -- must hold for the daemon's registry too.

What the fix must satisfy

  1. On a host whose register is at projects.yml and whose migration cannot complete,
    opening a session adds its row to that file and creates no agents.yml.
  2. On a host whose register is at agents.yml (every healthy host) behaviour is
    unchanged, and so is the case where neither name exists yet: the row lands in
    agents.yml.
  3. A test constructs the first state from a temporary directory, and is red without the
    change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions