You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
However, as a result of this, NewStore has a hard transitive dependency on the Redis client, even if the Redis store won't be used.
flowchart LR
MemoryStore
RedisStore -->|NewRedisStore| RedisClient[*redis.Client]
Store -->|NewStore| Config & MemoryStore & RedisStore
Store -.-> RedisClient
Loading
Ideally, NewStore should be able to specify which dependency set it wants to use after looking at the configuration.
Describe the solution you'd like
I'd like to propose adding a new intrinsic operation to the Fx model to accompany the existing intrinsics: Provide, Invoke, and Decorate.
package fx
funcEvaluate(...any) fx.Option
The new operation, tentatively named fx.Evaluate, will represent an unevaluated part of the graph.
Functions passed to fx.Evaluate will always be evaluated. They will feed new information to the graph in the form of fx.Option return values.
These new operations may form connections that previously did not exist.
With this operation, the scenario described above would be solved like so:
funcNewStore(cfgConfig) fx.Option {
ifcfg.Development {
returnfx.Provide(func(s*MemoryStore) Store { returns })
}
returnfx.Provide(func(s*RedisStore) Store { returns })
}
// Or alternatively:funcNewStore(cfgConfig) fx.Option {
ifcfg.Development {
returnfx.Provide(
fx.Annotate(NewMemoryStore, fx.As(new(Store))),
)
}
returnfx.Provide(
fx.Annotate(NewRedisStore, fx.As(new(Store))),
)
}
// In main:fx.New(
// ...fx.Evaluate(NewStore),
)
Describe alternatives you've considered
fx.Replace was considered but is insufficient for this functionality.
It cannot conditionally severe the dependency between NewStore and *redis.Client.
See this comment.
Is this a breaking change?
No, this is not a breaking change.
Additional context
This functionality has been brought up before and has been referred to with names such as: monadic graph, dynamic provides, late provides.
There was a prior attempt to implement this in #699 (tracked in #698). This attempt was rejected because of the following reasons per this comment.
There was risk of UX confusion by overloading fx.Provide. This is not an issue if we introduce a new intrinsic.
The internals of the library were actively being reworked for fx.Decorate. This is done now.
There were concerns about how "late provides" would interact with lifecycles. Again, this is not an issue with a new intrinsic because new expectations can be established: Evaluate always runs, so lifecycle events there always run.
Feature request
Is your feature request related to a problem? Please describe.
This scenario was previously described in #1131. It's reproduced below to save a click.
Suppose a program has a
Store
interface with two implementations: a memory-backed version and a Redis-backed version.The memory store has no dependencies, while the Redis store depends on a Redis client.
The application wants to pick between the two implementations based on a configuration parameter.
Imagine:
However, as a result of this,
NewStore
has a hard transitive dependency on the Redis client, even if the Redis store won't be used.Ideally,
NewStore
should be able to specify which dependency set it wants to use after looking at the configuration.Describe the solution you'd like
I'd like to propose adding a new intrinsic operation to the Fx model to accompany the existing intrinsics: Provide, Invoke, and Decorate.
The new operation, tentatively named
fx.Evaluate
, will represent an unevaluated part of the graph.Functions passed to
fx.Evaluate
will always be evaluated. They will feed new information to the graph in the form offx.Option
return values.These new operations may form connections that previously did not exist.
With this operation, the scenario described above would be solved like so:
Describe alternatives you've considered
fx.Replace
was considered but is insufficient for this functionality.It cannot conditionally severe the dependency between
NewStore
and*redis.Client
.See this comment.
Is this a breaking change?
No, this is not a breaking change.
Additional context
This functionality has been brought up before and has been referred to with names such as: monadic graph, dynamic provides, late provides.
There was a prior attempt to implement this in #699 (tracked in #698). This attempt was rejected because of the following reasons per this comment.
fx.Provide
. This is not an issue if we introduce a new intrinsic.fx.Decorate
. This is done now.Fx startup roughly takes the following shape:
With the new intrinsic, this could effectively become:
The text was updated successfully, but these errors were encountered: