Documentation
¶
Overview ¶
Package multi routes N named instances of the same type behind a single .Using(name) dispatcher. The canonical case is multiple databases:
dbs := multi.New[*gorm.DB]().
Register("main", mainDB, multi.AsDefault()).
Register("questions", qbDB).
Register("uaa", uaaDB)
// Inside a resolver / handler:
dbs.Using("main").Find(&rows) // explicit
dbs.Using("").Find(&rows) // "" = default ("main" here)
dbs.Using("questions").Find(&rows)
The package is transport-agnostic: T can be *gorm.DB, *sql.DB, an HTTP client, a Redis client — anything you'd route by name. nexus uses it in examples/graphapp and you can pair it with resource.NewDatabase to show every instance on the dashboard:
dbs.Each(func(name string, db *gorm.DB) {
app.Register(resource.NewDatabase(name, "Postgres", nil,
func() bool { sql, _ := db.DB(); return sql.Ping() == nil }))
})
Index ¶
- type Option
- type Registry
- func (r *Registry[T]) Default() T
- func (r *Registry[T]) DefaultName() string
- func (r *Registry[T]) Each(fn func(name string, v T))
- func (r *Registry[T]) Has(name string) bool
- func (r *Registry[T]) Len() int
- func (r *Registry[T]) Names() []string
- func (r *Registry[T]) OnUse(h func(ctx context.Context, name string))
- func (r *Registry[T]) Register(name string, v T, opts ...Option[T]) *Registry[T]
- func (r *Registry[T]) SetDefault(name string) *Registry[T]
- func (r *Registry[T]) Using(name string) T
- func (r *Registry[T]) UsingCtx(ctx context.Context, name string) T
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Registry ¶
type Registry[T any] struct { // contains filtered or unexported fields }
Registry is the dispatcher. Thread-safe for concurrent Register and Using.
func (*Registry[T]) DefaultName ¶
DefaultName returns the name currently marked default, or "" if empty.
func (*Registry[T]) Each ¶
Each invokes fn(name, instance) for every registered entry, in lexical order. fn must not call back into the Registry's mutating methods — doing so deadlocks. For registration-side work, copy the names via Names() first.
func (*Registry[T]) Has ¶
Has reports whether an instance is registered under name. Empty string checks for a default.
func (*Registry[T]) Names ¶
Names returns the registered names in lexical order. Useful for iterating to register each instance as a nexus.Resource or for health dashboards.
func (*Registry[T]) OnUse ¶
OnUse installs a callback fired every time UsingCtx is called. nexus uses this to auto-attach service→resource edges on the dashboard — the hook receives the caller's context.Context, and whatever the integrator reads out of it (e.g. trace.SpanFromCtx → service name) decides attribution.
Setting the hook is idempotent — a second OnUse call replaces the first. Returns no value so the method satisfies a structural interface for the hook-installer side (nexus.UseReporter), at the cost of not chaining.
func (*Registry[T]) Register ¶
Register stores v under name. Calling Register with an existing name overwrites the entry. Returns the Registry so calls chain.
func (*Registry[T]) SetDefault ¶
SetDefault explicitly marks an already-registered name as the default. Panics if the name isn't registered — that's a programmer bug.
func (*Registry[T]) Using ¶
Using returns the instance registered under name. An empty string resolves to the default. Returns the zero value of T when the name isn't known — rather than panicking — so optional lookups can chain .Has() first.
func (*Registry[T]) UsingCtx ¶
UsingCtx is Using with a context. When a hook is installed via OnUse, it fires before the lookup; otherwise this is exactly Using(name). Context-aware code paths (GraphQL resolvers, HTTP handlers) should prefer UsingCtx so dashboards can correlate lookups with the current request.