-
-
Notifications
You must be signed in to change notification settings - Fork 152
Description
I'm creating this issue to discuss a change before I try make the PR.
Context
BindToProvider takes a function in the form func(A, B, C, ...) (X, error)
(or without the error
return), where the arguments of the functions are dependencies of that provider, and the return value is the result.
For every dependency in the provider, if it's been bound with kong.Bind
or kong.BindTo
, the value is used as-is.
For values that come from other providers, those providers are invoked recursively, and the resulting value is used.
Problem
Based on API, I would expect that provided values are singletons. That is, if the value produced by a provider is requested from two other providers, the original provider is only invoked once.
In terms of code:
graph LR
NewA["func NewA(C) A"]
NewB["func NewB(C) B"]
NewA & NewB -->|call| NewC["func NewC() C"]
Reproduction:
package main
import (
"fmt"
"github.com/alecthomas/kong"
)
type (
Connection struct{}
ClientA struct{ conn *Connection }
ClientB struct{ conn *Connection }
)
func main() {
var cmd mainCmd
kctx := kong.Parse(&cmd,
kong.BindToProvider(func() *Connection {
fmt.Println("opening connection")
return &Connection{}
}),
kong.BindToProvider(func(conn *Connection) *ClientA { return &ClientA{conn: conn} }),
kong.BindToProvider(func(conn *Connection) *ClientB { return &ClientB{conn: conn} }),
)
kctx.FatalIfErrorf(kctx.Run())
}
type mainCmd struct{}
func (*mainCmd) Run(clientA *ClientA, clientB *ClientB) error {
return nil
}
The following output is expected:
❯ go run .
opening connection
But we get:
❯ go run .
opening connection
opening connection
There is no de-duplication.
The provider for Connection is requested by two providers, and is invoked twice.
Solution
I believe that this was just an oversight, and that these providers were not intended to be re-invoked like this.
In that case, this is just a bug and it should be straightforward to fix: I am happy to provide a fix.
However, if this was intended behavior, I'd like to propose an opt-in means of having these values treated as singletons. This could be a kong.BindOnce()
option.