Skip to content

JDBC backend: the catalog connect duplicates the pool's retry loop, so the two carry one policy in two files #929

Description

@vharseko

Lands with #893, which is where the code below is: it is not on master yet.

Problem

JDBCStorage.newCatalogConnection() retries its connect the way CachedConnection.getConnection() retries a borrow, and it does so by repeating the loop rather than by sharing one. The two now carry the same policy in two files:

  • CachedConnection.getConnectTimeoutSeconds() / getPoolTimeoutSeconds() / deadlineOf() — shared already,
  • CachedConnection.attemptSeconds(connectTimeout, deadline) — the per-attempt clamp,
  • CachedConnection.isWorthRetrying(e, dialect) — which failures are waited out,
  • backoffMs = min(backoffMs == 0 ? 1 : backoffMs * 2, MAX_BACKOFF_MS) — written out in both,
  • a stall warning, a deadline check, and a timeout exception built from safeUrl() + redact().

connectCatalog() repeats the establish-and-set-up half of CachedConnection.connect() besides: a fresh Properties, dialect.bound(...), DriverManager.getConnection(...), setAutoCommit(false), TRANSACTION_READ_COMMITTED, close-on-failure, and the lift of the read bound.

Why it matters

The next change to the backoff schedule, to the set of states worth retrying, or to the redaction rules has to be found and repeated by hand, and the pool is the copy anyone will find first. Two differences are deliberate today and nothing marks them as such: the pool feeds its wait into poll() of the deque while the catalog sleeps, and the pool's timeout carries 08001 where the catalog carries the driver's own state on purpose (saysTheConnectionIsGone() reads class 08 as a dropped connection, which would put a healthy attempt into the replay).

What the fix looks like

A package-visible helper in CachedConnection taking the attempt as a callback — roughly

static Connection retryingConnect(String connectionString, ConnectDialect dialect, String what,
                                  LongFunction<Connection> attempt, Waiter waiter)

— with the deque poll as the pool's own step and the two intended differences as parameters rather than as drift. CachedConnection.getConnection() is the one path of this class least worth rewriting casually, which is why this was left out of #893 rather than folded into a round about the connection beside it.

Not a defect today

Both loops are covered: CachedConnectionTestCase for the pool, and CatalogConnectionTestCase (a refusal waited out, one that is not, the deadline, the read-bound path) for the catalog. This is about the two staying the same as they change.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions