Critical:
- Add --shutdown-time, --max-attempts, --max-workers CLI flags; alias
--duration as --time so ydb-slo-action invocations don't drop the flag
- Reject unknown CLI options so typos in the action invocation fail loudly
instead of silently falling back to defaults
- Take an atomic snapshot of latency histograms (copy + reset) so concurrent
recordValue can't tear p50/p95/p99 percentile readings
- Align query workload's hash to the same client-side SplitMix64 used by the
JDBC and Spring implementations so tables are byte-compatible across all
workloads
- Plumb retry counts through OpOutcome for the Spring workloads via a
thread-local counter incremented inside @YdbTransactional methods, so
sdk_retry_attempts_total isn't perpetually flat for those implementations
- Size Hikari pool to 130 (2 × default --max-workers) so Spring workloads
measure the JDBC driver, not pool contention; override with
SLO_HIKARI_POOL_SIZE when raising --max-workers
- Use Hibernate FlushMode.COMMIT and READ_ONLY hint on JPA reads, and
EntityManager.clear() after each upsert, so the persistence context stops
inflating read latencies and leaking memory
Important:
- Abort setup() if more than half the prefill rows fail or if every prefill
worker fails to open a session, so reads never silently target an empty
key-space
- Decide retryable errors via YdbStatusable.getStatus().getCode().isRetryable
on idempotent operations; fall back to the JDBC marker types only when
the status isn't available
- Treat SQLNonTransientConnectionException as a connection-level error so
dead connections are reopened before the next attempt
- Bound rate limiter acquire by the run deadline (tryAcquire with the
remaining nanos) so a chaos stall during shutdown doesn't issue one extra
operation past the deadline
- Break the JDBC retry loop on interrupt instead of looping back into a
failing executeQuery, so graceful shutdown doesn't inflate sdk_errors_total
- Walk the cause chain in Spring classifyError looking for SQLState so
Hikari pool exhaustion etc. surface as distinct error_kind labels instead
of collapsing into "cannotgetjdbcconnectionexception"
- DROP TABLE IF EXISTS in all workloads so a failed createTable doesn't
produce a misleading teardown warning
- Refactor Spring KvClient.forTable to return a fresh KvClient bound to the
table path instead of mutating a singleton field
- Add Span.finishAbortedIfOpen() safety net so pendingOperations never leaks
if an unexpected throwable escapes the operation closure; volatile +
AtomicIntegerFieldUpdater so double-finish can't double-decrement
- Sanitize leading digits and cap length in Launcher.tablePathFor so YDB
table-name constraints never reject the workload path
Hygiene:
- Extract DDL/DML templates into core.kv.KvSchema so the four implementations
can't drift
- Remove the unused JdbcTemplate bean from the JPA configuration
- Update READMEs to match the new layout and document the new flags and the
cross-implementation hash compatibility
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Test plan
Merge order
Merge this PR first. The ydb-java-sdk and ydb-jdbc-driver workflow PRs depend on these paths existing on master.
Made with Cursor