Skip to content

feat(multidb): pipeline, tx pipeline and autopipeline support - #3951

Open
ndyakov wants to merge 20 commits into
feature/multidb/clientfrom
feature/multidb/autopipeline
Open

feat(multidb): pipeline, tx pipeline and autopipeline support#3951
ndyakov wants to merge 20 commits into
feature/multidb/clientfrom
feature/multidb/autopipeline

Conversation

@ndyakov

@ndyakov ndyakov commented Aug 5, 2026

Copy link
Copy Markdown
Member

Stacked on the MultiDBClient orchestration PR.

Makes MultiDBClient a full UniversalClient and wires batching through the
MultiDB core:

  • hooksMixin on MultiDBClient (MultiDB-level AddHook), satisfying the
    autopipeliner's backend interface — one AutoPipeliner instance survives
    failover; every flushed batch resolves the active database at exec time
  • processPipeline: batch attempt loop bounded by CommandRetries;
    per-command outcome recording (server error replies count as healthy);
    transport-failed batches are retried against the newly selected database
  • processTxPipeline: MULTI/EXEC executed at most once, never auto-retried
    (EXEC may have committed before the connection broke)
  • Pipeline/Pipelined, TxPipeline/TxPipelined, Do, Watch
    (active-bound, aborts on failover), SSubscribe, PoolStats
  • AutoPipeline/AsyncAutoPipeline (+WithOptions) with the same cached
    instance semantics as *Client; Close drains pipeliners before member
    clients shut down

Known trade-off: batches reaching a cluster member are split per node by the
member's own pipeline path (correct, not slot-shard-optimized).


Note

High Risk
Changes failover, circuit-breaker recording, and at-most-once semantics for pipelines and transactions across the MultiDB stack; incorrect batch retry or health recording could duplicate writes or mask outages.

Overview
Makes MultiDBClient a drop-in UniversalClient by adding MultiDB-level hooks, Do, Pipeline/Pipelined, TxPipeline/TxPipelined, Watch, SSubscribe, PoolStats, and cached AutoPipeline/AsyncAutoPipeline (with Close draining pipeliners first).

New multidb_pipeline core routes batches to the active member at exec time: processPipeline retries on transport failure (bounded by CommandRetries), records breaker/detector outcomes per command, and re-gates through half-open circuit admission; processTxPipeline and Watch gate similarly but execute MULTI/EXEC at most once. Tx paths mark every command setNoRetry so member-level retries cannot replay committed transactions.

baseCmd gains a noRetry flag (cloned with commands) so NoRetry() is data-driven—used for streaming writes and MultiDB tx batches. pipelineExecutedKey in context lets MultiDB distinguish hook-aborted batches from executed ones when recording health signals.

HIMPORT is rejected on batch paths (per-command in plain pipelines, whole tx rejected); errors are proto.RedisError so autopipeline coalescing does not abort unrelated commands. Cluster + autopipeline is refused at creation time; AddDatabase(cluster) is blocked while live autopipeliners exist.

Extensive integration tests cover failover retries, probe-slot accounting, hook-served batches, and escalation errors.

Reviewed by Cursor Bugbot for commit 18947f9. Bugbot is set up for automated code reviews on this repo. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends MultiDBClient to fully satisfy the UniversalClient surface and integrates pipelining and autopipelining into the MultiDB core, so batched operations resolve the active database at execution time and can fail over/retry as needed.

Changes:

  • Add hooksMixin support to MultiDBClient and wire MultiDB-level hooks into command, pipeline, and tx-pipeline processing.
  • Implement MultiDB-aware Pipeline/TxPipeline processing and cached AutoPipeline/AsyncAutoPipeline instances with lifecycle management on Close.
  • Add/extend tests to cover pipeline routing, failover retry behavior, per-command outcome recording, tx at-most-once behavior, and autopipeline caching/closure.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
multidb.go Embeds hooksMixin, adds cached autopipeliner fields, routes Process through hooks, and drains autopipeliners in Close.
multidb_test.go Extends the test hook to count pipeline batches and simulate pipeline-wide failures.
multidb_pipeline.go Introduces MultiDB pipeline/tx-pipeline execution, Do, Watch, SSubscribe, PoolStats, and AutoPipeline APIs.
multidb_autopipeline_test.go Adds coverage for pipeline and autopipeline routing, failover/retry, at-most-once tx behavior, and instance caching/closure.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go Outdated
@ndyakov
ndyakov force-pushed the feature/multidb/autopipeline branch 2 times, most recently from f926af2 to 34eeef4 Compare August 5, 2026 14:47
@ndyakov
ndyakov requested a lite review from Copilot August 5, 2026 14:55
@ndyakov

ndyakov commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread multidb_pipeline.go

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 34eeef4fc0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go
Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go Outdated
@ndyakov
ndyakov force-pushed the feature/multidb/autopipeline branch from 34eeef4 to 5360697 Compare August 5, 2026 15:36
@ndyakov
ndyakov requested a lite review from Copilot August 5, 2026 15:38
@ndyakov

ndyakov commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

multidb_pipeline.go:174

  • AutoPipeline/AsyncAutoPipeline refuse cluster member databases only at creation time. If a MultiDB client creates an AutoPipeliner and later a cluster member becomes active (e.g., added via AddDatabase or selected by failover), the existing autopipeliner will still dispatch batches to that cluster member, bypassing the intended refusal and the cluster-specific autopipeline safeguards mentioned in the comment above.

Consider adding an execution-time guard in the unhooked autopipeliner entry points (process/processPipeline) to fail fast when the active database is a cluster client, so an already-created autopipeliner can’t silently run in an unsupported mode after topology changes.

// process / processPipeline are the unhooked base entry points required by
// the autopipeliner's backend interface (cmdableClient); the hook-wrapped
// variants come from hooksMixin.
func (c *MultiDBClient) process(ctx context.Context, cmd Cmder) error {
	return c.core.process(ctx, cmd)
}

// hookCount reports one more hook than are installed on the MultiDBClient
// itself: member clients can carry their own hooks (AddDatabaseHook), which
// the autopipeliner cannot see, and its async dispatcher only arms the
// batch-executor self-deadlock guards when hookCount is non-zero. Always
// reporting at least one keeps those guards armed for member-level hooks
// that read command results.
func (c *MultiDBClient) hookCount() int {
	return c.hooksMixin.hookCount() + 1
}

func (c *MultiDBClient) processPipeline(ctx context.Context, cmds []Cmder) error {
	return c.core.processPipeline(ctx, cmds)
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53606975bc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go
@ndyakov
ndyakov force-pushed the feature/multidb/autopipeline branch from 5360697 to 0a47d9c Compare August 5, 2026 16:02
@ndyakov
ndyakov requested a lite review from Copilot August 5, 2026 16:04
@ndyakov

ndyakov commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (3)

multidb_pipeline.go:103

  • processPipeline uses the name transportFailures for the value returned by recordBatchOutcomes, but that count includes any outcomeFailure (including retryable server replies), not only transport errors. Consider renaming the local variable so the retry decision is clearly based on availability failures, matching classifyOutcome.
		err := db.processPipelineHook(ctx, cmds)
		transportFailures := c.recordBatchOutcomes(db, cmds)

		if transportFailures == 0 {
			// Only server replies (or clean success) — done, whatever the

multidb_pipeline.go:39

  • The counter variable in recordBatchOutcomes is named transportFailures, but it is incremented for any outcomeFailure (including retryable server replies via shouldRetry), not only transport-level errors. Renaming it to reflect "availability failures" will make the intent match classifyOutcome and avoid misleading future changes.
func (c *multidbCore) recordBatchOutcomes(db *multidbDatabase, cmds []Cmder) int {
	transportFailures := 0
	for _, cmd := range cmds {
		err := cmd.rawErr()
		switch classifyOutcome(err) {

multidb_pipeline.go:29

  • The comment says "error reply from the server ... counts as a success" and that the function returns the number of "transport-level failures", but the implementation uses classifyOutcome(err) and counts outcomeFailure, which also includes retryable server replies (shouldRetry), not just transport errors. Please update the comment to reflect that retryable server replies (e.g. LOADING/READONLY/CLUSTERDOWN) are treated as availability failures and included in the returned count.

This issue also appears in the following locations of the same file:

  • line 35
  • line 99
// mirroring the single-command path: an error reply from the server proves
// the database is reachable and counts as a success; transport-level errors
// count as failures; client-side errors (context cancellation, deterministic
// local rejections per shouldRetry) record nothing and do not trigger
// failover. It returns the number of transport-level failures.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a47d9caa6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread multidb.go Outdated
Comment thread multidb_pipeline.go Outdated
@ndyakov
ndyakov force-pushed the feature/multidb/client branch from aa40a1c to 00af763 Compare August 5, 2026 16:33
@ndyakov
ndyakov force-pushed the feature/multidb/autopipeline branch from 0a47d9c to 6ea2e43 Compare August 5, 2026 16:33
@ndyakov
ndyakov requested a lite review from Copilot August 5, 2026 16:35
@ndyakov

ndyakov commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

multidb_pipeline.go:30

  • The docstring says this function returns the number of "transport-level failures", but the implementation increments the counter for every outcomeFailure (which also includes retryable server replies per shouldRetry). This mismatch is easy to misread when reasoning about retries/failover semantics; please align the comment with classifyOutcome.
// recordBatchOutcomes records one breaker/detector outcome per command,
// mirroring the single-command path: an error reply from the server proves
// the database is reachable and counts as a success; transport-level errors
// count as failures; client-side errors (context cancellation, deterministic
// local rejections per shouldRetry) record nothing and do not trigger

Comment thread multidb_pipeline.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ea2e43f7c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread multidb.go
Comment thread multidb_pipeline.go
Comment thread multidb_pipeline.go
Comment thread multidb_pipeline.go Outdated
Comment thread multidb_pipeline.go Outdated
@ndyakov
ndyakov force-pushed the feature/multidb/client branch from 00af763 to 0221df0 Compare August 5, 2026 20:39

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73efb7721f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread multidb_pipeline.go
@ndyakov

ndyakov commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07cabd006e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread multidb.go
@ndyakov

ndyakov commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: acd79f51a3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

ndyakov added 20 commits August 7, 2026 15:12
MultiDBClient now satisfies UniversalClient and the autopipeliner backend
interface: batches resolve the active database at exec time, feed the
circuit breaker and failure detector per command, and are retried against
the newly selected database after a failover. MULTI/EXEC pipelines are
executed at most once and never retried automatically.
Batches containing a non-retryable command (RawWriteToCmd and friends)
execute at most once, and the Watch documentation now states that a
transaction stays bound to the member that was active at call time.
- batch outcome recording reads rawErr (never Err) so the async
  autopipeline dispatcher cannot await the batch it is completing
- client-side errors in batches record nothing and disable the retry,
  matching the single-command path
- tx pipeline outcome recording excludes the synthetic MULTI/EXEC
  envelope commands
- AutoPipeline/AsyncAutoPipeline refuse cluster member databases (the
  cluster-specific autopipeline wiring would be bypassed)
- Watch attempts a failover first when the active member is unhealthy,
  and its docs spell out the member binding and hook behavior
- hookCount reports one extra hook so the async batch-executor guards
  stay armed for member-level hooks
- batch outcome recording uses the shared classifier: retryable server
  replies count as failures, ErrCrossSlot and other local errors are
  neutral
- availability errors from exhausted failover attempts overwrite stale
  per-command transport errors (setCmdsErr fills only empty slots)
- AddDatabase refuses cluster members while an autopipeliner instance
  exists, closing the gap around the creation-time cluster check
- a closed autopipeliner no longer blocks AddDatabase(cluster) forever
  (the cached slot is checked for liveness, matching getOrCreate)
- the cluster-member check moved inside the pipeliner build function and
  AddDatabase holds autopipelinerMu across check+add, so creation and
  cluster additions are fully serialized
- neutral-only batches release the half-open probe slot reserved by the
  breaker gate
- pipeline and tx-pipeline paths reject work with ErrClosed after Close,
  matching the single-command path
- WATCH gates on the non-reserving circuit read (it never records or
  releases half-open slots) and returns ErrClosed after Close
- the AddDatabase/AutoPipeliner.Close drain race window is documented
Suppress the member client's own pipeline retry loop for MultiDB
transactions by marking the synthetic MULTI as NoRetry (EXEC may have
committed before a transport error; at-most-once must hold for the
whole stack), re-enter the breaker admission gate after a batch/tx
failover so a half-open member's bounded probe slots are respected,
and return context errors before the failover gate in TxPipeline and
Watch so doomed operations cannot advance failover state.
Mark every command of a MultiDB transaction NoRetry (cluster members
trim the MULTI/EXEC envelope before their retry check, so a marker on
the synthetic MULTI alone is lost there), check the failure detector
before the breaker admission gate in the batch and tx paths so a
detector-routed failover cannot leak a half-open probe slot, overwrite
stale transport errors with the context error when a retried batch is
canceled between attempts, and classify the batch-level error for
unstamped commands so a hook-aborted batch records nothing instead of
phantom successes.
Fall back to the batch-level error only when NO command was stamped
(an executed batch always stamps at least the failing command), fixing
the round-eight substitution that could turn a successful prefix into
phantom transport failures and replay it; stamp that error onto the
unstamped commands so per-command inspection and exhausted-retry
returns see it; and mark batch successes as recovery traffic for the
failover escalation chain, matching the single-command path.
Record batch failures before successes so a half-open member's failed
recovery batch cannot close the circuit off its own successful prefix,
and replace the stamped-commands inference with an execution marker
(flipped by the standalone and cluster execution paths the moment a
batch may reach the wire): a post-exec hook error on an executed batch
no longer fabricates transport failures and replays applied writes,
while pre-exec hook aborts still surface on every command.
Treat hook-served batches (nil without execution) as neutral — the
caller keeps its results, but nothing reached Redis, so no breaker or
detector signal is recorded and the gate's probe slot is released;
stamp the batch error onto every command an aborting hook left
unstamped so partially-stamped aborts cannot fabricate successes; and
bound consecutive gate rejections in the batch retry loop, mirroring
the single-command path, so all-members-half-open-and-full surfaces
ErrTemporarilyNotAvailable instead of busy-looping failovers.
Reject the HIMPORT command family in the batch paths too (pipeline
builders dispatch through their own cmdable and bypass the direct
overrides), skip success recording entirely for unexecuted batches so
hook-fabricated replies cannot close a half-open circuit, and apply
failure-first outcome ordering only to half-open recovery probes —
in the closed state the arrival order stands, or a stale sub-threshold
failure could combine with a batch failure and open a healthy member.
Reject only the HIMPORT commands themselves in plain pipelines (an
autopipeliner flush coalesces unrelated callers, and poisoning the
whole batch failed innocent commands), keep whole-batch rejection for
transactions (atomic by definition), and turn the TxPipeline gate into
the same bounded failover loop the other paths use — a denied probe
slot now retries another member instead of rejecting the transaction,
which is safe because no MULTI/EXEC has been sent while gating.
Classify batch outcomes with the per-command blocking-timeout rule
(cmd.readTimeout) instead of a blanket retryTimeout=true, surface the
HIMPORT rejection as the Exec error when the kept commands all succeed,
and make errMultiDBHImport a RedisError so the autopipeliner's
sequential dispatch treats it as a per-command verdict rather than a
fatal abort that poisons the sub-batches queued behind it.
SSubscribe rejects a Close race through the MultiDB PubSub path (which
fails dials with terminal ErrClosed) and registers the requested shard
channels on the no-active fallback like Subscribe/PSubscribe do, and a
mixed pipeline with a rejected HIMPORT reports the positionally first
failed command as its Exec error.
Mirrors the single-command retry loop: a Close landing mid-retry
reports ErrClosed instead of escalating through the drained
membership.
The batch guards match HIMPORT by command name too (raw Do/NewCmd
submissions build plain *Cmd values the marker interface misses), and
the Watch gate reserves a half-open probe slot via IsAllowed —
released after the call, since WATCH outcomes never record — so
MaxHalfOpenRequests bounds concurrent transactions against a
recovering member.
A half-open candidate with its probe budget exhausted failed Watch with
ErrTemporarilyNotAvailable after a single failover attempt while a
healthy member was still selectable. The gate now loops like the
pipeline and tx-pipeline gates (bounded by the rejection cap); no WATCH
is sent while the gate is still choosing, so at-most-once holds.
A Watch admitted while the breaker was closed reserved no probe slot,
but its deferred release ran anyway — a transaction outliving a later
open -> half-open transition freed a slot a real recovery probe held,
letting MaxHalfOpenRequests be exceeded. The gate now uses Allow and
releases only reserved admissions.

Early pipeline exits (Close, context, availability) returned the
stamped error even when a rejected HIMPORT preceded the stamped
commands positionally; every exit now reports the positionally first
error over the original slice, like the executed path.
Batch gates admitted closed-state work via IsAllowed, then settled
through unconditional ReleaseHalfOpen (hook-served and all-neutral
batches) and RecordSuccess — a batch outliving a later open ->
half-open transition freed probe slots it never reserved. Both gates
use Allow now and recordBatchOutcomes settles by the reservation:
unreserved successes count via RecordExternalSuccess, unreserved
releases are skipped.
@ndyakov

ndyakov commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (1)

multidb_pipeline.go:32

  • The doc comment for recordBatchOutcomes says any server error reply counts as success and that the return value is "transport-level failures", but the implementation uses classifyOutcome (which treats retryable server replies like LOADING/READONLY/CLUSTERDOWN as failures) and increments the counter for any outcomeFailure, not only transport errors. This mismatch can mislead future changes around retry/failover semantics.
// mirroring the single-command path: an error reply from the server proves
// the database is reachable and counts as a success; transport-level errors
// count as failures; client-side errors (context cancellation, deterministic
// local rejections per shouldRetry) record nothing and do not trigger
// failover. It returns the number of transport-level failures.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 18947f9123

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants