#!/usr/bin/env perl
# Stress test: pgbench hammers the ring buffer with many concurrent clients
# Verifies no events are lost under high load

use strict;
use warnings;
use lib 't';

use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;

use psch;

# Initialize node with adequate buffer capacity
my $node = psch_init_node('stress',
    queue_capacity    => 65536,
    flush_interval_ms => 100  # Fast flush so events get exported
);

# Reset stats before test
psch_reset_stats($node);

# Note: We don't check for zero enqueued because the reset call itself
# or internal queries might capture an event. We'll measure the delta instead.
my $stats_before = psch_get_stats($node);
is($stats_before->{dropped}, 0, 'Starts with zero dropped events');

# Run pgbench: 8 clients, 1000 transactions each = 8000 queries minimum
# Each transaction does BEGIN + SELECT + COMMIT = more events
my $nclients = 8;
my $ntxns = 1000;
my $expected_min_queries = $nclients * $ntxns;

$node->pgbench(
    "--client=$nclients --transactions=$ntxns --no-vacuum",
    0,                                # expected exit code
    [qr/processed: \d+\/\d+/],        # stdout pattern
    [qr/^$/],                         # stderr pattern (empty)
    'ring buffer stress test',
    { 'simple' => 'SELECT 1' }        # custom script
);

# Get final stats
my $stats = psch_get_stats($node);

# Calculate new events since start
my $new_events = $stats->{enqueued} - $stats_before->{enqueued};

# Verify accounting: new events should be at least the queries we ran
cmp_ok($new_events, '>=', $expected_min_queries,
    "All queries accounted for (got $new_events new events, expected >= $expected_min_queries)");

# With 65536 capacity, we shouldn't drop anything
is($stats->{dropped}, 0,
    'No events dropped with adequate capacity');

# Capacity should match what we configured
is($stats->{capacity}, 65536, 'Queue capacity matches configuration');

# Note: We don't test queue draining since there's no ClickHouse to export to.
# The queue_size will be non-zero and that's expected behavior.

# Log some diagnostic info
diag("Stress test results:");
diag("  Enqueued (total): $stats->{enqueued}");
diag("  Enqueued (new):   $new_events");
diag("  Dropped:  $stats->{dropped}");
diag("  Queue size: $stats->{queue_size}");
diag("  Usage %: $stats->{usage_pct}");

$node->stop();
done_testing();
