Files
nxdns/src/web/coverage.zig
T
mokhtar 6a0630c288
Gates / frontend (push) Successful in 2m6s
Gates / test (push) Successful in 2m57s
Gates / test-aarch64 (push) Successful in 8m31s
Gates / package (push) Successful in 4m19s
Gates / container (push) Failing after 2s
CI / gates (push) Failing after 26m21s
overview: one endpoint, live projections and a response cache (m36)
2026-08-27 17:48:20 +02:00

56 lines
2.1 KiB
Zig

//! How much of the window a client asked about the query log can still answer
//! for.
//!
//! Retention deletes old rows and advances a watermark in the same transaction
//! (`queries_repo.pruneOlderThan`), so the file knows the oldest instant it is
//! complete for. Without that fact on the wire a chart draws a pruned week as a
//! week of silence, which is the one reading that is certainly wrong.
//!
//! Two endpoints carry it — `/api/queries` and `/api/overview` — and they judge
//! it against their own effective lower bound: the client's `since` for the
//! query log, the period's aligned window start for the overview.
const std = @import("std");
const db = @import("../storage/db.zig");
const queries_repo = @import("../storage/repositories/queries_repo.zig");
pub const Coverage = struct {
/// True only when the whole requested window is inside what the file still
/// holds. A request with no lower bound at all asks about all of history,
/// which no file that has ever pruned can promise.
complete: bool,
/// The oldest instant the file is complete for, unix seconds.
available_since: i64,
};
pub fn of(available_since: i64, since: ?i64) Coverage {
return .{
.complete = if (since) |lower_bound| lower_bound >= available_since else false,
.available_since = available_since,
};
}
/// Reads the watermark for a request that is about to answer.
pub fn read(database: *db.Db, since: ?i64) db.Error!Coverage {
return of(try queries_repo.availableSince(database), since);
}
// ---------------------------------------------------------------------------
// tests
// ---------------------------------------------------------------------------
const testing = std.testing;
test "a window that starts at or after the watermark is complete" {
try testing.expect(of(1000, 1000).complete);
try testing.expect(of(1000, 1001).complete);
try testing.expect(!of(1000, 999).complete);
}
test "an unbounded window is never complete" {
const unbounded = of(1000, null);
try testing.expect(!unbounded.complete);
try testing.expectEqual(@as(i64, 1000), unbounded.available_since);
}