Add --file ingestion with restart-safe tailing (ticket 020)

ingest::run_file tails a path like tail -f: reads existing content,
follows appended lines, and detects file recreation/truncation (via
inode on unix, or a shrinking size) to resume tailing the new
instance from its start instead of exiting or stalling. Sequence
numbers keep incrementing across a recreation event since they're
ottyl's own line counter, not tied to the source file. stdin ingest
is unchanged and remains the default when --file is omitted.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
Hugh Kaznowski
2026-09-05 15:08:20 +01:00
co-authored by Claude Sonnet 5
parent b3701cd2e9
commit aaa5596030
2 changed files with 230 additions and 3 deletions
+20 -3
View File
@@ -38,6 +38,12 @@ struct Args {
/// (e.g. `~/.config/ottyl/settings.json` on Linux).
#[arg(long)]
settings_path: Option<PathBuf>,
/// File to tail for log lines, instead of reading from stdin. Behaves like
/// `tail -f`: reads existing content then keeps following appended lines,
/// and keeps tailing if the file is deleted/recreated at the same path.
#[arg(long)]
file: Option<PathBuf>,
}
#[tokio::main]
@@ -86,7 +92,14 @@ async fn main() {
}
}
tokio::spawn(ingest::run(engine_tx.clone()));
match args.file.clone() {
Some(path) => {
tokio::spawn(ingest::run_file(engine_tx.clone(), path));
}
None => {
tokio::spawn(ingest::run(engine_tx.clone()));
}
}
let app = api::router(engine_tx, &args.static_dir, settings, settings_path);
let listener = TcpListener::bind(("0.0.0.0", args.port))
@@ -97,9 +110,13 @@ async fn main() {
.expect("failed to read back bound address")
.port();
let source = match &args.file {
Some(path) => format!("tailing {}", path.display()),
None => "reading logs from stdin".to_string(),
};
eprintln!(
"ottyl serving on http://localhost:{} (reading logs from stdin)",
bound_port
"ottyl serving on http://localhost:{} ({})",
bound_port, source
);
axum::serve(listener, app)