-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow depinject interface types to be resolved using a key #11910
Comments
Haven't fully thought this through, but an alternative implementation could look like bank: type outputs struct {
depinject.Out
BankKeeper keeper.Keeper `bindings:"cosmos.nft.module.v1.ExpctedBankKeeper,cosmos.staking.module.v1.ExpectedBankKeeper"`
} nft: type inputs struct {
depinject.In
BankKeeper nft.ExpectedBankKeeper
} |
But what we want to avoid is bank needing to have knowledge of nft, staking, etc. |
The linear search option could also be valid, but we'd need a way to handle conflicts still. That could either be via a key and/or the approach described in #11911 |
Ok true. I'm used to seeing those kind of bindings described somewhere else, a composition root outside of the modules themselves. |
Here are the designs I've thought of that we could choose between at the depinject layer:
If we did just (1), I think (3) is necessary. If we did (2), we could postpone or even skip (3) Any other solutions anyone can think of? Any strong preferences on which strategy? |
Also note that we should probably do #11908 while we're doing this and that will help the dev UX |
(2) wasn't too bad of patch in #12103. I'm still interested in (1) as a fallback, though. |
Either way we should do ##11908 first |
Now that we're working with keys do we like this approach or should we also implement (1)? The immediate downside of (2) is what if the provider fails to use key, then the consumer is stuck. (1) together with (3) would alleviate that. Thoughts @kocubinski @facundomedica @blushi @JeancarloBarrios now that we're using this? |
There are some concerns around how (1) will work when there are potentially multiple implementations of an interface. This could happen if 2 or more separate provider functions in different modules have single interface implementations as outputs. @marbar3778 mentioned an Interchain security package is currently in this state. However I still like this feature from a usability perspective even if it doesn't address all cases; (1) with (3) will let the user know that The downsides of (2) still stand however. Possible remediation:
|
I'm thinking we should maybe take an approach where we don't auto-magically bind things as described in (1), but that an explicit app.yaml binding like you've described |
I like the idea of being quite explicit and expressing the binding in the |
From the SDK call, sounds like we're no going with (1) and (3). So we'd have automatic matching of interfaces if there is no conflict and conflict resolution if there is (depinject/appconfig should give you suggestions on how to address). At the depinject level, I think we want to add two config options:
and then in the app.yaml, we could do something like this: modules:
- name: bank
config: ...
golang_bindings:
github.com/cosmos/cosmos-sdk/x/bank/types.AccountKeeper: github.com/cosmos/cosmos-sdk/x/auth/keeper.AccountKeeper
The error from Does this approach sound right? |
I think we can close this now that #12169 is merged. Please reopen if you think otherwise |
This isn't supported in the app config yet so we should reopen |
@kocubinski we also need to make sure explicit and implicit interface bindings are properly reflected in the graphviz output. Can you take a look at that after #12367 ? |
Problem Definition
Currently depinject dependencies must be exact matches so the expected keepers paradigm will no longer work.
For example, say the bank module provides
bank.Keeper
and the nft module wants to requirenft.ExpectedBankKeeper
which is a sub-interface ofbank.Keeper
. Depinject can't resolve this dependency. In #11908, we propose that the keeper should suggestbank.Keeper
as a hint.We could extend this and do a linear search of all interfaces in the container to see if there is a match, but introducing a linear search into dependency resolution is probably unacceptable even if this is only done at app initialization.
Propose Solution
As an alternative, we propose an optional
key
parameter which can be provided when usingdepinject
anddepinject
structs.For example, the bank module could provide:
and the NFT module could require:
Modules would need to coordinate on the correct key names which are just strings chosen to be logical and unambiguous, but this is probably preferable to doing a linear search. It may also allow a way to provide different dependencies to different modules if needed (see #11911)
The text was updated successfully, but these errors were encountered: