overview: one endpoint, live projections and a response cache (m36)
This commit is contained in:
+22
-10
@@ -30,6 +30,7 @@
|
||||
//! `writer_failed`, so the loss is visible rather than silent.
|
||||
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const db = @import("db.zig");
|
||||
@@ -555,13 +556,17 @@ pub const Logger = struct {
|
||||
/// group it cancels for exactly that reason.
|
||||
///
|
||||
/// `monitor` is the §11.6 gate. Null disables gating.
|
||||
///
|
||||
/// `gpa` belongs to the `BatchWriter` for that writer's whole life; it
|
||||
/// allocates the projection deltas of one batch and nothing else.
|
||||
pub fn runWriter(
|
||||
self: *Logger,
|
||||
io: std.Io,
|
||||
gpa: Allocator,
|
||||
database: *db.Db,
|
||||
monitor: ?*disk_monitor.Monitor,
|
||||
) std.Io.Cancelable!void {
|
||||
var writer = queries_repo.BatchWriter.init(database) catch |err| {
|
||||
var writer = queries_repo.BatchWriter.init(gpa, database) catch |err| {
|
||||
scope.warn("query logger: preparing the batch statements failed: {s}", .{@errorName(err)});
|
||||
// Without a writer there is no consumer, so leaving the queue open
|
||||
// would silently swallow every later entry.
|
||||
@@ -1134,7 +1139,7 @@ test "an entry with every provenance field set survives the queue, toRow, insert
|
||||
|
||||
var database = try openLog();
|
||||
defer database.close();
|
||||
var writer = try queries_repo.BatchWriter.init(&database);
|
||||
var writer = try queries_repo.BatchWriter.init(testing.allocator, &database);
|
||||
defer writer.deinit();
|
||||
|
||||
var buf: [4]Entry = undefined;
|
||||
@@ -1466,6 +1471,7 @@ test "shutdown writes the batch the writer holds and the rest of the queue" {
|
||||
var future = try io.concurrent(Logger.runWriter, .{
|
||||
&logger,
|
||||
io,
|
||||
testing.allocator,
|
||||
&database,
|
||||
@as(?*disk_monitor.Monitor, null),
|
||||
});
|
||||
@@ -1502,7 +1508,7 @@ test "entries that arrive inside one window reach the database in one batch" {
|
||||
|
||||
var database = try openLog();
|
||||
defer database.close();
|
||||
var writer = try queries_repo.BatchWriter.init(&database);
|
||||
var writer = try queries_repo.BatchWriter.init(testing.allocator, &database);
|
||||
defer writer.deinit();
|
||||
|
||||
var buf: [16]Entry = undefined;
|
||||
@@ -1559,6 +1565,7 @@ test "the writer holds an entry for the length of the flush interval" {
|
||||
var future = try io.concurrent(Logger.runWriter, .{
|
||||
&logger,
|
||||
io,
|
||||
testing.allocator,
|
||||
&database,
|
||||
@as(?*disk_monitor.Monitor, null),
|
||||
});
|
||||
@@ -1611,6 +1618,7 @@ test "a full batch flushes without waiting for the interval" {
|
||||
var future = try io.concurrent(Logger.runWriter, .{
|
||||
&logger,
|
||||
io,
|
||||
testing.allocator,
|
||||
&database,
|
||||
@as(?*disk_monitor.Monitor, null),
|
||||
});
|
||||
@@ -1658,6 +1666,7 @@ test "the writer's next cycle uses the interval set since its last one" {
|
||||
var future = try io.concurrent(Logger.runWriter, .{
|
||||
&logger,
|
||||
io,
|
||||
testing.allocator,
|
||||
&database,
|
||||
@as(?*disk_monitor.Monitor, null),
|
||||
});
|
||||
@@ -1700,7 +1709,7 @@ test "a gated flush holds the batch until the disk recovers" {
|
||||
|
||||
var database = try openLog();
|
||||
defer database.close();
|
||||
var writer = try queries_repo.BatchWriter.init(&database);
|
||||
var writer = try queries_repo.BatchWriter.init(testing.allocator, &database);
|
||||
defer writer.deinit();
|
||||
|
||||
var buf: [4]Entry = undefined;
|
||||
@@ -1754,7 +1763,7 @@ test "a failing batch is dropped whole and the writer stays usable" {
|
||||
\\BEGIN SELECT RAISE(ABORT, 'refused'); END;
|
||||
);
|
||||
|
||||
var writer = try queries_repo.BatchWriter.init(&database);
|
||||
var writer = try queries_repo.BatchWriter.init(testing.allocator, &database);
|
||||
defer writer.deinit();
|
||||
|
||||
var buf: [4]Entry = undefined;
|
||||
@@ -1789,7 +1798,7 @@ test "a writer that cannot prepare closes the queue and counts every entry" {
|
||||
|
||||
for (0..3) |i| logger.log(io, sampleEntry(@intCast(i), "early.example"));
|
||||
|
||||
try logger.runWriter(io, &database, null);
|
||||
try logger.runWriter(io, testing.allocator, &database, null);
|
||||
|
||||
try testing.expect(logger.writer_failed.load(.acquire));
|
||||
try testing.expectEqual(@as(u64, 3), logger.queries_dropped.load(.monotonic));
|
||||
@@ -1842,6 +1851,7 @@ test "the gating episode opens on the gate, turns losing on a drop, and clears o
|
||||
var future = try io.concurrent(Logger.runWriter, .{
|
||||
&logger,
|
||||
io,
|
||||
testing.allocator,
|
||||
&database,
|
||||
@as(?*disk_monitor.Monitor, &monitor),
|
||||
});
|
||||
@@ -2023,6 +2033,7 @@ test "a canceled writer counts the batch it was holding" {
|
||||
var future = try io.concurrent(Logger.runWriter, .{
|
||||
&logger,
|
||||
io,
|
||||
testing.allocator,
|
||||
&database,
|
||||
@as(?*disk_monitor.Monitor, &monitor),
|
||||
});
|
||||
@@ -2072,6 +2083,7 @@ test "a disk-gated writer drops what it holds at shutdown instead of hanging" {
|
||||
var future = try io.concurrent(Logger.runWriter, .{
|
||||
&logger,
|
||||
io,
|
||||
testing.allocator,
|
||||
&database,
|
||||
@as(?*disk_monitor.Monitor, &monitor),
|
||||
});
|
||||
@@ -2121,7 +2133,7 @@ test "an empty batch touches neither the database nor the counters" {
|
||||
|
||||
var database = try openLog();
|
||||
defer database.close();
|
||||
var writer = try queries_repo.BatchWriter.init(&database);
|
||||
var writer = try queries_repo.BatchWriter.init(testing.allocator, &database);
|
||||
defer writer.deinit();
|
||||
|
||||
var buf: [4]Entry = undefined;
|
||||
@@ -2155,7 +2167,7 @@ test "a dropped batch opens an error episode the next good batch closes" {
|
||||
try fx.init(io, 1000);
|
||||
defer fx.deinit();
|
||||
|
||||
var writer = try queries_repo.BatchWriter.init(&database);
|
||||
var writer = try queries_repo.BatchWriter.init(testing.allocator, &database);
|
||||
defer writer.deinit();
|
||||
|
||||
var buf: [4]Entry = undefined;
|
||||
@@ -2198,7 +2210,7 @@ test "a writer that cannot prepare leaves an episode no recovery path claims" {
|
||||
var logger: Logger = .init(.{}, &buf);
|
||||
logger.diagnostics = &fx.store;
|
||||
|
||||
try logger.runWriter(io, &database, null);
|
||||
try logger.runWriter(io, testing.allocator, &database, null);
|
||||
|
||||
try testing.expectEqualStrings("writer", try fx.text(
|
||||
"SELECT subject_key FROM operational_events WHERE resolved_at IS NULL",
|
||||
@@ -2209,7 +2221,7 @@ test "a writer that cannot prepare leaves an episode no recovery path claims" {
|
||||
|
||||
// The writer returned, so nothing can ever close this. A second run finds
|
||||
// the queue closed and adds no second episode.
|
||||
try logger.runWriter(io, &database, null);
|
||||
try logger.runWriter(io, testing.allocator, &database, null);
|
||||
try testing.expectEqual(
|
||||
@as(i64, 1),
|
||||
try fx.count("SELECT count(*) FROM operational_events WHERE resolved_at IS NULL"),
|
||||
|
||||
Reference in New Issue
Block a user