pub struct FileTailer { /* private fields */ }Expand description
Polls a log file for new data at a configurable interval.
Opens Player.log read-only with shared access (no file locking
conflicts with MTGA), seeks to the end on startup, and reads only
new bytes from the last offset on each poll cycle. Raw lines are
fed into a LineBuffer for log entry boundary detection.
§Connection health
The last_event_at timestamp is updated
whenever new data is read, providing a heartbeat signal for
connection health monitoring.
§Example
use std::path::Path;
use manasight_parser::log::tailer::FileTailer;
let mut tailer = FileTailer::open(Path::new("/path/to/Player.log")).await?;
// Poll once for new data.
let entries = tailer.poll().await?;
for entry in &entries {
println!("Got entry: {:?}", entry.header);
}
// Check when data was last seen.
if let Some(ts) = tailer.last_event_at() {
println!("Last data at: {ts}");
}Implementations§
Source§impl FileTailer
impl FileTailer
Sourcepub async fn open(path: &Path) -> Result<Self, TailerError>
pub async fn open(path: &Path) -> Result<Self, TailerError>
Opens a log file for tailing, seeking to the end.
The file is opened read-only. On startup, the file position is
set to the end so that only new data written after this point
is returned by subsequent poll calls.
§Errors
Returns TailerError::Io if the file cannot be opened or
the seek operation fails.
Sourcepub async fn open_from_start(path: &Path) -> Result<Self, TailerError>
pub async fn open_from_start(path: &Path) -> Result<Self, TailerError>
Opens a log file for tailing from the beginning.
Unlike open, this does not seek to the end.
All existing content will be read on the first poll.
Useful for testing or for catch-up parsing of Player-prev.log.
§Errors
Returns TailerError::Io if the file cannot be opened.
Sourcepub fn set_poll_interval_ms(&mut self, ms: u64)
pub fn set_poll_interval_ms(&mut self, ms: u64)
Sets the poll interval in milliseconds.
The default is 50 ms. Values below 10 ms are clamped to 10 ms to avoid busy-spinning.
Sourcepub fn poll_interval_ms(&self) -> u64
pub fn poll_interval_ms(&self) -> u64
Returns the poll interval in milliseconds.
Sourcepub fn last_event_at(&self) -> Option<DateTime<Utc>>
pub fn last_event_at(&self) -> Option<DateTime<Utc>>
Returns the timestamp of the last successful data read.
None if no data has been read yet. This is intended for
connection health monitoring — if this timestamp is stale,
the log file may not be updating (MTGA closed, crashed, etc.).
Sourcepub fn offset(&self) -> u64
pub fn offset(&self) -> u64
Returns the current byte offset in the file.
This is the position from which the next poll
will read.
Sourcepub fn take_rotation(&mut self) -> Option<RotationInfo>
pub fn take_rotation(&mut self) -> Option<RotationInfo>
Takes the rotation info from the last poll cycle, if any.
Returns Some(RotationInfo) exactly once after a rotation is
detected by poll. Subsequent calls return None
until the next rotation.
Sourcepub async fn poll(&mut self) -> Result<Vec<LogEntry>, TailerError>
pub async fn poll(&mut self) -> Result<Vec<LogEntry>, TailerError>
Polls the file for new data and returns any complete log entries.
Reads all new bytes appended since the last poll, splits them
into lines, and feeds each line into the LineBuffer. Any
complete log entries (flushed by a new header boundary) are
collected and returned.
A partial line at the end of the read (not terminated by a newline) is buffered internally and prepended to the next read.
Returns an empty Vec if no new data is available.
§Errors
Returns TailerError::Io if the read operation fails.
Sourcepub fn flush(&mut self) -> Vec<LogEntry>
pub fn flush(&mut self) -> Vec<LogEntry>
Flushes any remaining buffered entries from the line buffer.
Call this when the input stream ends (EOF or file rotation) to retrieve any accumulated entries that have not yet been flushed by a subsequent header boundary.
Returns a Vec because flushing a partial line that is itself
a log entry header can produce two entries: the previously
buffered entry (flushed by the new header) and the new header’s
own entry (flushed by the line buffer drain).
Sourcepub async fn run(
&mut self,
entry_tx: Sender<LogEntry>,
shutdown: Receiver<bool>,
) -> Result<(), TailerError>
pub async fn run( &mut self, entry_tx: Sender<LogEntry>, shutdown: Receiver<bool>, ) -> Result<(), TailerError>
Runs the polling loop, sending complete log entries to the provided channel.
This method runs indefinitely until the shutdown signal is
received. It polls the file at the configured interval and
sends each complete LogEntry to the entry_tx channel.
§Cancellation
The loop exits when shutdown resolves. Callers should use a
tokio::sync::watch or CancellationToken to signal shutdown.
§Errors
Returns TailerError::Io if a read operation fails. Callers
should decide whether to retry or propagate the error.
Sourcepub async fn run_once(&mut self) -> Result<Vec<LogEntry>, TailerError>
pub async fn run_once(&mut self) -> Result<Vec<LogEntry>, TailerError>
Reads the entire file and returns all complete log entries.
Polls until no new complete entries are returned (typically at
EOF), then flushes the line buffer to capture any trailing
entry. Unlike run, this method does not poll
indefinitely or require a shutdown signal.
Note: the entire file is buffered into a Vec<LogEntry> before
returning. This is suitable for batch processing (smoke tests,
replay analysis, Player-prev.log imports) but not for
memory-constrained streaming of very large files.
Works with any tailer opened from the start of a file via
open_from_start.
§Errors
Returns TailerError::Io if a read operation fails.