milestone 24: persist and surface the unsupported-line count

This commit is contained in:
2026-08-13 20:44:27 +02:00
parent 21571e448e
commit 1bce81eea0
18 changed files with 799 additions and 20 deletions
+19 -2
View File
@@ -822,12 +822,21 @@ pub const Manager = struct {
if (std.mem.eql(u8, stored, &compiled.result.checksum) and
self.diskBodiesMatch(io, dir, row.id, stored))
{
// The three written counts come from the row: the checksum
// covers the three bodies, so an unchanged checksum means an
// unchanged number of entries in each. The two skip counts do
// not: a skipped line lands in no body, so a list that changed
// only its regex or browser-syntax lines arrives here with a
// stale row and a fresh compile. Taking them from the row would
// show the operator one number and restore another after a
// restart.
try sources_repo.updateSourceStats(self.database, row.id, .{
.last_updated = now,
.domain_count = row.domain_count,
.wildcard_count = row.wildcard_count,
.exception_count = row.exception_count,
.skipped_regex_count = row.skipped_regex_count,
.skipped_regex_count = compiled.result.counts.skipped_regex,
.skipped_unsupported_count = compiled.result.counts.skipped_unsupported,
.checksum = stored,
});
status.succeed(now, compiled.result.counts);
@@ -857,6 +866,7 @@ pub const Manager = struct {
.wildcard_count = compiled.result.counts.wildcards,
.exception_count = compiled.result.counts.exceptions,
.skipped_regex_count = compiled.result.counts.skipped_regex,
.skipped_unsupported_count = compiled.result.counts.skipped_unsupported,
.checksum = &compiled.result.checksum,
});
status.succeed(now, compiled.result.counts);
@@ -1537,7 +1547,7 @@ fn applyLoadOutcomes(
entry.loaded = true;
// Two states survive a successful load. `.ok`, because a
// refresh in this process already filled the counters the
// compile produced and the three database columns are a subset
// compile produced and the five database columns are a subset
// of them. And any refresh failure, because the files that just
// loaded are exactly the ones the failed refresh could not
// replace, so the operator must still see why.
@@ -1547,6 +1557,7 @@ fn applyLoadOutcomes(
.wildcards = countOf(row.wildcard_count),
.exceptions = countOf(row.exception_count),
.skipped_regex = countOf(row.skipped_regex_count),
.skipped_unsupported = countOf(row.skipped_unsupported_count),
});
},
.failed => |reason| {
@@ -1926,6 +1937,7 @@ test "a canceled compiled-file read cancels the reload instead of recording it"
.domain_count = 1,
.wildcard_count = 0,
.skipped_regex_count = 0,
.skipped_unsupported_count = 0,
.exception_count = 0,
.checksum = &bodyChecksum(list_body, wild_body, allow_body),
});
@@ -2049,6 +2061,7 @@ test "the log label names a source without printing what its url carries" {
.domain_count = 0,
.wildcard_count = 0,
.skipped_regex_count = 0,
.skipped_unsupported_count = 0,
.checksum = null,
};
const printed = try std.fmt.bufPrint(&buf, "blocklist {f}: download failed: {s}", .{
@@ -2223,6 +2236,7 @@ fn testRow(id: i64, enabled: bool) sources_repo.SourceRow {
.wildcard_count = 4,
.exception_count = 2,
.skipped_regex_count = 1,
.skipped_unsupported_count = 5,
.checksum = "0" ** 64,
};
}
@@ -2333,6 +2347,9 @@ test "a load of a source this process never refreshed takes the row counters" {
try testing.expectEqual(@as(u32, 9), statuses[0].counts.domains);
try testing.expectEqual(@as(u32, 4), statuses[0].counts.wildcards);
try testing.expectEqual(@as(u32, 1), statuses[0].counts.skipped_regex);
// Rehydration: a restart reads this from the row and nowhere else, because
// no path reparses a compiled file's header.
try testing.expectEqual(@as(u32, 5), statuses[0].counts.skipped_unsupported);
}
test "a status borrows nothing, so a copy outlives the table it came from" {