goaop-symfony-bundle icon indicating copy to clipboard operation
goaop-symfony-bundle copied to clipboard

Detection of circular references which breaks weaving

Open TheCelavi opened this issue 8 years ago • 3 comments
trafficstars

I have spent 2 days trying to figure out an issue of Go Aop not being able to weave around some classes in project. It happened that I had a circular reference issue that involved aspects, so that broke everything, and issue was not so obvious as it is with, per example, Symfony service container.

We had a external service providers (4 of them) with OAuth protected external api. In order to handle them, for each, a Provider class is created, and each Provider is injected into Manager.

Each provider could expire a token. So, we have RefreshTokenAspect, which will, in general, try to re-issue a token on some method call if that method fails (per example, Provider->fetchData()).

This weaving was possible.

However, there was a third Entity, which has method getData(). For that method, aspect is used on which Manager is injected to lazy-load data from some of the Providers.

And that failed Aspect Container without any obvious error.

As I have figure out, first, a Symfony service container is created. Then AOP kernel, then aspects, and then other services. However, if aspect requires some service, then that service will be initialized prior to aspect. And if that service is weaved, or its some sub-dependency, then you get a circular reference.

This complex situation can be simply explained as a rule: "There can not be an aspect defined which uses service that is weaved, or depends on any other service that is weaved".

It would be very convenient to build some kind of introspection that would detect this situation and warn about circular reference.

Possible workarounds:

  • Bad: instead of injecting weaved service in aspect, inject service container
  • Not tested, promising: use lazy loading services, see: https://symfony.com/doc/current/service_container/lazy_services.html and https://github.com/symfony/symfony/tree/master/src/Symfony/Bridge/ProxyManager

TheCelavi avatar Jul 10 '17 00:07 TheCelavi

Lazy loaded services FTW.

TheCelavi avatar Jul 10 '17 01:07 TheCelavi

This looks promising: https://github.com/symfony/symfony/issues/20656#issuecomment-314110173

If implemented, it will ease up management with circular references.

Only thing which should be extremely useful is to track down dependencies and throw exception when circular dependency is detected.

TheCelavi avatar Jul 10 '17 14:07 TheCelavi

Only thing which should be extremely useful is to track down dependencies and throw exception when circular dependency is detected.

Yes, indeed, this will be nice guard.

lisachenko avatar Jul 11 '17 08:07 lisachenko