-
Notifications
You must be signed in to change notification settings - Fork 240
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
feat: improve DependencyGraph and error reporting #4628
base: main
Are you sure you want to change the base?
feat: improve DependencyGraph and error reporting #4628
Conversation
edf9d8b
to
8759869
Compare
e4a588e
to
e771686
Compare
adbd767
to
d5b7758
Compare
d5b7758
to
88bcfec
Compare
* @param serviceClass The extension class | ||
* @return A (potentially empty) list of injection points. | ||
*/ | ||
public List<InjectionPoint<ServiceExtension>> getDependenciesOf(Class<? extends ServiceExtension> serviceClass) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method is only used by tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, the idea was to make the DG into more like a graph, with methods to match. It would make the DG more usable, esp. in runtimes other than the BaseRuntime
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not in favor of that, this dependency graph is really something related to the BaseRuntime
implementation, if someone wants for any reason to customize it, they would need to provide their own logic, otherwise we'll be responsible to maintain logic that we don't really need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a version where the DependencyGraph
is an interface, and one implementation is using EDC-internal dependency injection. Other implementations could use other DI frameworks like Guice, which would make the DI independent from the runtime. I ultimately abandoned that, because it would have meant pulling the InjectionContainer
and InjectionPoint
classes into an SPI module, which seemed too much work and we don't really have a need for that now.
That said, these methods aren't needed by us at the moment, but since the BaseRuntime
is extensible, and the DependencyGraph
is exposed in protected methods, overriders may benefit from them.
* @param dependencyType The type of the injection point, for example the type of service that is injected. | ||
* @return a list of extension classes that declare a dependency onto the given injection point | ||
*/ | ||
public List<Class<? extends ServiceExtension>> getDependentExtensions(Class<?> dependencyType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
* @param dependencyType The type of the injection point, for example the type of service that is injected. | ||
* @return a list of {@link InjectionPoint} instances that represent the concrete dependency | ||
*/ | ||
public List<InjectionPoint<ServiceExtension>> getDependenciesFor(Class<?> dependencyType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
var message = String.format("The following @Require'd features were not provided: [%s]", String.join(", ", unsatisfiedRequirements)); | ||
throw new EdcException(message); | ||
} | ||
return new DependencyGraph(injectionContainers, unsatisfiedInjectionPoints, unsatisfiedRequirements); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
at this point the DependencyGraph
looks like some sort of Result
, with List<InjectionContainer>
as content type and a Failure
that contains the unsatisfied injection points and requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given the choice, I would much rather pass around a DependencyGraph
object than a List<InjectionPoint<ServiceExtension>>
. Personally, I find it easier to read and understand and easier to handle, and it doesn't leak the InjectionPoint
all over the code.
Also, it will hide the implementation better, so changes down the road would have less of an impact.
What this PR changes/adds
This PR improves the public API of the
DependencyGraph
object and makes it a bit more usable. In addition, error reporting of dependency injectionerrors is externalized and moved into the
BaseRuntime
class.After dependency resolution, all problems are collected and a single
EdcInjectionException
is thrown by theBaseRuntime
, for example:Why it does that
Dependency injection errors (services, config values and config objects) wasn't very elegant and needed improvement.
Linked Issue(s)
Contributes to #4610
Please be sure to take a look at the contributing guidelines and our etiquette for pull requests.