Keep CLI log compaction on live inode
This commit is contained in:
@@ -682,15 +682,17 @@ def compact_log_file(path, max_bytes=MAX_SERVICE_LOG_BYTES):
|
|||||||
newline_index = chunk.find(b"\n")
|
newline_index = chunk.find(b"\n")
|
||||||
if newline_index >= 0 and newline_index + 1 < len(chunk):
|
if newline_index >= 0 and newline_index + 1 < len(chunk):
|
||||||
chunk = chunk[newline_index + 1 :]
|
chunk = chunk[newline_index + 1 :]
|
||||||
tmp_path = file_path.with_suffix(file_path.suffix + ".tmp")
|
|
||||||
try:
|
try:
|
||||||
tmp_path.write_bytes(chunk)
|
# Preserve the inode used by a running gateway process. Replacing the
|
||||||
tmp_path.replace(file_path)
|
# path here would leave its inherited stdout/stderr descriptors
|
||||||
|
# writing to a deleted file.
|
||||||
|
with file_path.open("r+b") as handle:
|
||||||
|
handle.seek(0)
|
||||||
|
handle.write(chunk)
|
||||||
|
handle.truncate()
|
||||||
|
handle.flush()
|
||||||
except OSError:
|
except OSError:
|
||||||
try:
|
return
|
||||||
tmp_path.unlink(missing_ok=True)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_port_available(kind, port):
|
def ensure_port_available(kind, port):
|
||||||
|
|||||||
@@ -313,3 +313,19 @@ def test_manifest_rejects_a_minimum_contract_newer_than_installer():
|
|||||||
assert "newer bootstrap installer" in str(exc)
|
assert "newer bootstrap installer" in str(exc)
|
||||||
else:
|
else:
|
||||||
raise AssertionError("incompatible minimum contract must be rejected")
|
raise AssertionError("incompatible minimum contract must be rejected")
|
||||||
|
|
||||||
|
|
||||||
|
def test_cli_log_compaction_preserves_live_writer_inode(tmp_path):
|
||||||
|
module = load_installer()
|
||||||
|
log_path = tmp_path / "gateway.log"
|
||||||
|
log_path.write_bytes((b"old-line\n" * 200) + b"recent-line\n")
|
||||||
|
inode_before = log_path.stat().st_ino
|
||||||
|
|
||||||
|
with log_path.open("ab", buffering=0) as live_writer:
|
||||||
|
module.compact_log_file(log_path, 128)
|
||||||
|
live_writer.write(b"after-cli-compaction\n")
|
||||||
|
|
||||||
|
assert log_path.stat().st_ino == inode_before
|
||||||
|
content = log_path.read_bytes()
|
||||||
|
assert content.endswith(b"after-cli-compaction\n")
|
||||||
|
assert b"recent-line\n" in content
|
||||||
|
|||||||
Reference in New Issue
Block a user