fx icon indicating copy to clipboard operation
fx copied to clipboard

Private Provides

Open sywhang opened this issue 2 years ago • 3 comments

With the addition of fx.Module, it is possible to add a ProvideOption that scopes a provided constructor to take the scope of a single fx.Module.

Dig already supports this, because by default, providing to a dig.Scope limits the scope to a single Scope. Fx is currently providing using the dig.Export(true) to provide every dependency to the global dig.Container by default, so this option should be fairly easy to add.

sywhang avatar Mar 04 '22 19:03 sywhang

Hey, I can take this addition. Here is what I propose it should look like:

fx.PrivateProvide(providerFunction)

Here are some rules that we should stick with (if I'm not mistaken, this is what's happening right now when we create a provide without exporting it in dig).

  1. In essence, private provides should have the same capabilities as current global provides.
  2. A module should use the closest provided object in the path to the container.
  3. PrivateProvides can coexists (whitout erroring) with global provides and also with other private provides, given that they're not in the same scope/Module.
  4. PrivateProvides will be decorated with all decorators from the scope it's used until the container.

In terms of implementation, I expect it to be really similar to Provide, just don't calling it with dig.Export(true) (as mentioned in the issue).

What do you think? :smile:

hbdf avatar Jul 20 '22 20:07 hbdf

Sync'd offline with @hbdf.

Provide doesn't take in a functional option today which is why the proposed design above was under an entirely new API. Instead of this I am proposing we use fx.Annotate to expose this:

fx.Module("myModule",
  fx.Provide(
    fx.Annotate(
    NewTypeA,
      fx.Private(true), // name TBD
    ),
)

makes the output types of NewTypeA only be provided to "myModule".

sywhang avatar Aug 01 '22 16:08 sywhang

Actually, the signature of Provide is an interface{}.

@hbdf You could add this using a functional option then.

fx.Module("myModule",
  fx.Provide(
    NewTypeA,
    fx.Private(true),
  ),
)

where:

func Private(isPrivate bool) provideOption {
  return provideOption{
    Private: isPrivate
  }
}

and you can change the implementation of Provide to check whether the provided ctor is a type of provideOption before injecting it to the container.

If it's a type of provideOption you can mark all the ctors in that variadic parameter as private provide.

sywhang avatar Aug 01 '22 16:08 sywhang

Internal Ref: GO-1736

tchung1118 avatar Nov 16 '22 19:11 tchung1118

private provides are now available with v1.19.0 or later releases

sywhang avatar Jan 22 '23 01:01 sywhang