Better rename during rotations - #9
Merged
Merged
Conversation
…rename
The agent is now the sole authority on file identity and rotation. The server
no longer decides identity from content; it only appends to an agent-named
`target` and renames it when told to.
- hello: write to `<dir>/<target>`; report {length, prefix_sha1} and never
rotate. Absent `target` falls back to the legacy rotate-on-mismatch path so a
v2 server can be deployed ahead of the agent.
- data: keep the explicit offset check (now a clean ProtocolError); lazily
create a new target on the first append.
- rename: idempotent in-band control frame within the connection dir; the open
fd survives the rename. fsync the segment file and the parent directory on
rename so completed segments and their final names are crash-durable.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…an path
Replace the per-inode follow_file with a per-path coordinator that owns all
segment connections and is the sole authority on rotation. Each segment binds to
an explicit `target`: in steady state one live segment streams the current inode
into `foo.log`; across a rotation a closing segment drains the old inode into
`foo.log.<iso_dt>` while a new live segment streams the new inode into `foo.log`.
The one ordering constraint -- seal before opening the new live segment -- is a
single awaited rename ack in the coordinator, so the two connections never share
a name and the server has nothing to arbitrate.
- client: explicit `target` in hello; `send_rename` control frame.
- marker_watcher: parrot lh-logrotate's <iso_dt> (.lh-logrotate-waiting) and
<sha13> (.lh-logrotate-{compressed,uploaded}, uploaded as fallback).
- coordinator: seal -> drain-to-marker -> finalize for lh-logrotate files; an
orphan path (self-generated <iso_dt> + `.orphan`, EOF-stable completion) for
markerless rotations; no-write-before-seal recovery for a stale remote target.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrite the rotation e2e test to drive the real lh-logrotate marker flow end-to-end (waiting -> sealed -> compressed -> finalized) against the v2 server, asserting the live mirror name equals the rotated name. Document the v2 protocol (explicit target, prefix_sha1 reporting, idempotent rename, rotation naming) and record the design in PLAN_v2.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… target The server no longer has a pre-target fallback. An explicit, validated `target` is now required in the handshake; a missing or invalid target is rejected. With it, the content-based rotate-on-prefix-mismatch path (`serve_legacy`) is gone -- the agent is the sole authority on file identity and rotation. `serve_v2` is renamed to `serve_client` accordingly. Lazy target creation now validates the first `data` frame's metadata and offset strictly (integer offset 0, rejecting bool) before opening the file, so a malformed first frame never leaves a stray empty file behind. Also drop the PLAN_v2.md design doc and de-version the surviving "v2" references now that there is a single protocol (the `logline-agent-v1` wire token is unrelated and unchanged). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
messa
reviewed
Jun 4, 2026
| # orphan (markerless). lh-logrotate writes the marker as it rotates, so | ||
| # the real wait is usually ~0; this is headroom for scan jitter. It also | ||
| # bounds how long the new live segment is delayed, so keep it small. | ||
| self.seal_marker_grace = 10 |
Contributor
There was a problem hiding this comment.
U takovychto konfiguracnich hodnot by bylo fajn pridat suffix typu _seconds
messa
approved these changes
Jun 4, 2026
The agent now sends the source `directory` and the destination leaf name `target` as separate header fields instead of a single `path`. The server is the sole authority on neither: it maps `directory` to the mangled <dest>/<hostname>/<directory> and writes the agent-chosen `target` as the leaf. The basename of `path` was only ever computed and then discarded -- the destination filename is `target`, which differs from the source basename for sealed/finalized segments. Server: build_destination_path() becomes build_destination_dir(), mapping the mangled directory under <dest>/<hostname>/ and leaving the leaf to the caller's `target`. All path-traversal hardening is preserved; the final resolved-inside-base check now guards the host-only case too. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rename the agent Configuration attributes to carry their units: durations get a `_seconds` suffix and byte counts a `_bytes` suffix (for example tail_read_interval -> tail_read_interval_seconds and prefix_length -> prefix_length_bytes). No behavioural change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
No description provided.