Documentation
¶
Overview ¶
Package conncatchup is what a toolkit does when it is asked about a connection it does not serve.
A deployment runs several replicas over one database, and a connection saved through one of them reaches the others twice: in the connection store before the save returns, and as an announcement on the reload bus some time after. A replica that answers only from what the bus has delivered tells a caller the connection does not exist for as long as the announcement is in flight — a wrong answer about a connection that is saved, and one nothing distinguishes from a genuine misconfiguration (#1714 for the graphql kind, #1746 for api).
What is here is the one resolution of that miss: on a name the toolkit does not hold, read the connection store, put what it holds in service, and answer as the saving replica answers. A connection the toolkit already holds never reaches this package, so the store is touched only on the miss that is otherwise a wrong answer.
It holds no toolkit types. A kind supplies a Server over its own connection map and a Store over its own records, which is what keeps two kinds from growing two of these. It sits beside pkg/connreconcile, which owns the other half of the same job — applying a connection change to the live toolkits — rather than inside it: that package reaches the toolkits through pkg/registry, which every toolkit is registered in, so a toolkit cannot import it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Locks ¶
type Locks struct {
// contains filtered or unexported fields
}
Locks serializes, per connection name, everything that replaces a served connection or changes what it holds: a save, a peer's announcement of one, a connection taken on from the store, a deletion, a re-read, an upload. Without it a connection prepared for service could replace one an upload had just changed, and serve the version the upload replaced. Distinct connections do not wait on each other.
The zero value is ready to use.
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver resolves a miss against the connection store. One belongs to one toolkit, beside the Locks that toolkit serializes its connection changes with: the catch-up takes the same lock a save takes, so a connection taken on from the store cannot land on top of one a save is installing.
func New ¶
New returns a Resolver for one kind. kind names the toolkit in the log messages a failed catch-up writes, and notFound is the sentinel its Store reports an absent connection with.
func (*Resolver) Resolve ¶
Resolve takes on the connection the store holds under name, reporting whether the toolkit serves it afterwards. It is called on the miss alone: a connection the toolkit holds is answered without it.
Requests that arrive for one name while a read is in flight share that read, because the read parses whatever the connection is built from and a burst of calls for a connection this instance does not serve would otherwise each pay for it.
A nil store is a deployment that keeps connections in memory only, where there is nothing to catch up to.
type Server ¶
type Server interface {
HasConnection(name string) bool
Install(ctx context.Context, name string, config map[string]any) error
Withdraw(name string)
}
Server is the toolkit's own view of what it serves, as the catch-up needs it: whether a name is held, how a stored connection is put in service, and how one is taken back out. Install is called under the name's lock with the toolkit known not to hold it, so it materializes and serves rather than refusing a duplicate.
type Store ¶
Store is the connection store a miss is resolved against: the records the admin write path commits before it returns. A name the store does not hold is reported with an error satisfying the kind's not-found sentinel, which is what separates "no such connection" from "the store could not answer".