Skip to content

Commit e4dfcb4

Browse files
author
SqlRush
committed
test(cluster): spec-5.19 MG-B — t/328 M3 two-node report-only diag (native/two-node TPS + tax + unavailable reason)
Output-visibility hardening for the MG-B report-only leg (the M1 single-node gate already diag()s its median): - M3 now diag()s the native single-node median tps, the two-node peer-online node0 median tps, and the two-node write tax % — captured in the CI log even on PASS / non-verbose prove, so the report-only numbers are never a silent black box. - When the 2-node measurement is unavailable, M3 prints the SPECIFIC reason (ClusterPair boot failed + error / peers not connected+in_quorum within timeout / pgbench init failed / no valid rounds / native baseline missing) instead of a generic "unavailable". - Still strictly REPORT ONLY: M3 never asserts a threshold and never fails the single-node hard gate. No behavior change to the M1 single-node ≤10% hard gate.
1 parent 4808601 commit e4dfcb4

1 file changed

Lines changed: 54 additions & 18 deletions

File tree

src/test/cluster_tap/t/328_stage5_multinode_write_perf.pl

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ sub poll_sql_eq
229229
my @two_node_tps;
230230
my $two_node_started = 0;
231231
my $two_node_ready = 0;
232+
my $two_init_ok = 0;
233+
my $two_err;
232234
eval {
233235
my @pair_perf_conf = map { my $line = $_; chomp $line; $line } @perf_conf;
234236
my $pair = PostgreSQL::Test::ClusterPair->new_pair(
@@ -249,21 +251,25 @@ sub poll_sql_eq
249251
&& poll_sql_eq($pair->node0, 'SELECT in_quorum FROM pg_cluster_quorum_state', 't', 20)
250252
&& poll_sql_eq($pair->node1, 'SELECT in_quorum FROM pg_cluster_quorum_state', 't', 20);
251253

252-
if ($two_node_ready && pgbench_init($pair->node0))
254+
if ($two_node_ready)
253255
{
254-
for my $r (1 .. $TWO_NODE_ROUNDS)
256+
$two_init_ok = pgbench_init($pair->node0) ? 1 : 0;
257+
if ($two_init_ok)
255258
{
256-
my $t = pgbench_one($pair->node0);
257-
next unless defined $t && $t > 0;
258-
push @two_node_tps, $t;
259-
note(sprintf(" two-node round %d: node0 tps=%.0f", $r, $t));
259+
for my $r (1 .. $TWO_NODE_ROUNDS)
260+
{
261+
my $t = pgbench_one($pair->node0);
262+
next unless defined $t && $t > 0;
263+
push @two_node_tps, $t;
264+
note(sprintf(" two-node round %d: node0 tps=%.0f", $r, $t));
265+
}
260266
}
261267
}
262268
$pair->stop_pair;
263269
1;
264270
} or do {
265-
my $err = $@ || 'unknown error';
266-
diag("M3 two-node report-only measurement failed before completion: $err");
271+
$two_err = $@ || 'unknown error';
272+
diag("M3 two-node report-only measurement failed before completion: $two_err");
267273
};
268274

269275
my $two_have = ($two_node_started && $two_node_ready && scalar(@two_node_tps) > 0
@@ -273,29 +279,59 @@ sub poll_sql_eq
273279
? 100.0 * (1.0 - $two_tps / $tps_native) : undef;
274280
my $two_tax_s = defined $two_tax ? sprintf('%.2f', $two_tax) : 'n/a';
275281

276-
note("MG-B two-node peer-online write-path REPORT-ONLY measurement:");
277-
note(" native single-node TPC-B median tps = "
278-
. (defined $tps_native ? sprintf('%.0f', $tps_native) : 'n/a'));
279-
note(" two-node peer-online node0 TPC-B median tps = "
280-
. (defined $two_tps ? sprintf('%.0f', $two_tps) : 'n/a'));
281-
note(" two-node write tax % (report-only) = $two_tax_s");
282+
my $native_s = defined $tps_native ? sprintf('%.0f', $tps_native) : 'n/a';
283+
my $two_tps_s = defined $two_tps ? sprintf('%.0f', $two_tps) : 'n/a';
284+
285+
# Specific unavailable reason (reported even on PASS so the report-only leg is
286+
# never a silent black box).
287+
my $two_reason;
288+
if (!$two_node_started)
289+
{
290+
$two_reason = "ClusterPair failed to boot/start"
291+
. (defined $two_err ? ": $two_err" : "");
292+
}
293+
elsif (!$two_node_ready)
294+
{
295+
$two_reason = "peers did not reach connected + in_quorum within timeout";
296+
}
297+
elsif (!$two_init_ok)
298+
{
299+
$two_reason = "pgbench init on node0 failed";
300+
}
301+
elsif (!scalar(@two_node_tps))
302+
{
303+
$two_reason = "pgbench produced no valid (>0 tps) rounds";
304+
}
305+
elsif (!(defined $tps_native && $tps_native > 0))
306+
{
307+
$two_reason = "native single-node baseline tps missing";
308+
}
309+
310+
# diag() reaches the captured CI log even on PASS / non-verbose prove, so the
311+
# 2-node report-only numbers are always visible alongside the M1 single-node
312+
# gate -- not just when run with -v.
313+
diag("MG-B two-node peer-online write-path REPORT-ONLY measurement:");
314+
diag(" native single-node TPC-B median tps = $native_s");
315+
diag(" two-node peer-online node0 TPC-B median tps = $two_tps_s");
316+
diag(" two-node write tax % (report-only) = $two_tax_s"
317+
. (defined $two_reason ? " (unavailable: $two_reason)" : ""));
282318

283319
# REPORT ONLY: this leg must never fail the single-node hard gate. If the
284320
# 2-node ClusterPair could not boot / reach quorum / produce a number this run
285321
# (transient runner shmem pressure, etc.), pass with an explicit unavailable
286322
# note rather than failing -- the HARD gate is the single-node M1 tax only.
287323
if ($two_have)
288324
{
289-
diag("MG-B two-node peer-online write tax (report-only) = ${two_tax_s}%");
290325
ok(1,
291326
"M3 two-node peer-online single-writer write tax measured: ${two_tax_s}% "
292-
. "(REPORT ONLY; no threshold asserted)");
327+
. "(native=$native_s two-node=$two_tps_s tps; REPORT ONLY; no threshold asserted)");
293328
}
294329
else
295330
{
296331
ok(1,
297-
"M3 two-node peer-online write tax unavailable this run "
298-
. "(REPORT ONLY; never fails the single-node hard gate)");
332+
"M3 two-node peer-online write tax unavailable this run: "
333+
. ($two_reason // 'unknown reason')
334+
. " (REPORT ONLY; never fails the single-node hard gate)");
299335
}
300336
$report->record_multinode_write_value(2, 'tpcb-peer-online-single-writer',
301337
tps_native => (defined $tps_native ? $tps_native : 0),

0 commit comments

Comments
 (0)