Skip to content

IncludePrimaryIfReplicaBanned does not retain the primary when it's the only candidate #1117

Description

@kzemek

In pgdog/src/backend/pool/lb/mod.rs:

let primary_reads = match self.rw_split {
    IncludePrimary => true,
    IncludePrimaryIfReplicaBanned => candidates.iter().any(|target| target.ban.banned()),
    // Under PreferPrimary, default queries already route to the primary as writes;
    // a read only reaches here when it explicitly opted into replicas, so honor it
    // like ExcludePrimary and fall back to the primary only if there are no replicas.
    ExcludePrimary | PreferPrimary => !candidates
        .iter()
        .any(|target| matches!(target.role(), Role::Replica | Role::Auto)),
};

if !primary_reads {
    candidates.retain(|target| matches!(target.role(), Role::Replica | Role::Auto));
}

when candidates = [primary] (i.e. there's no replicas), all options evaluate to primary_reads = true - except for IncludePrimaryIfReplicaBanned, that evaluates to false and then removes the primary from candidates.

I propose that all branches evaluate to true in that case, e.g. IncludePrimaryIfReplicaBanned => candidates.len() <= 1 || candidates.iter().any(|target| target.ban.banned()), or even let primary_reads = candidates.len() <= 1 || match self.rw_split {

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions