-
Notifications
You must be signed in to change notification settings - Fork 0
Limit manager as a service #2
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
base: feature/extract-rate-limit-manager
Are you sure you want to change the base?
Limit manager as a service #2
Conversation
f30fd09 to
dddd936
Compare
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 have highlighted the main changes, did not update the tests yet, if you are ok with it I can do that too.
| * @param EventDispatcherInterface $eventDispatcher | ||
| * @param RateLimitService $rateLimitService | ||
| * @param PathLimitProcessor $pathLimitProcessor | ||
| * @param LimitProcessorInterface $limitProcessor |
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 class now depends only on the interface, not on implementations anymore
| return; | ||
| } | ||
|
|
||
| // Find the best match |
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 logic has been moved in the AnnotationLimitProcessor as it is the one responsible for annotations
| use Noxlogic\RateLimitBundle\LimitProcessorInterface; | ||
| use Symfony\Component\HttpFoundation\Request; | ||
|
|
||
| class AnnotationLimitProcessor implements LimitProcessorInterface |
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 class is a service now, it is instantiated only once by the symfony DI. If the annotations package is not available, disabling it will not require changes in the code, only changing the noxlogic_rate_limit.processor alias
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.
Main reason to move it into the service - to create object only once via DI?
Disabling class in DI good approach. Maybe I wrong, but it doesn't bring big value, cause if annotation package is not available we need to disable rate_limit_annotation_listener. And without events usage, annotation class will not be used as well.
Before that changes, Util/AnnotationLimitProcessor.php were tightly coupled with symfony framework, cause its use symfony related attributes.
So in general, I agree, that it can be service class, cause in any case it right now symfony specific.
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.
Having stateless services is always a good idea, in the previous implementation AnnotationLimitProcessor had to be instantiated in the request process, while now is instantiated via DI (with all the possible optimizations that symfony will be able to do as the upcoming preloading in 7.4).
Did not know that the aim of this bundle is to be framework agnostic.Wiring it into laravel might be possible, but not sure is the main goal.
| * @return string | ||
| */ | ||
| public function getRateLimitAlias(Request $request); | ||
| public function getRateLimitAlias(Request $request, callable $controller); |
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.
only thing that I did not manager to solve in an elegant way is the $controller callable
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.
Will think about that case.
Cause original intention were to make Rate Limit framework agnostic.
With controller argument we are in situation, when interface is dictated by DI and symfony logic, that request and current controller can differ.
| private $controller; | ||
|
|
||
| public function __construct(array $annotations, callable $controller) | ||
| public function __construct(LimitProcessorInterface $fallback) |
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.
Here using the chain of responsibility pattern
amanto
left a comment
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.
@goetas added some ideas. Will think about common interface.
| * @return string | ||
| */ | ||
| public function getRateLimitAlias(Request $request); | ||
| public function getRateLimitAlias(Request $request, callable $controller); |
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.
Will think about that case.
Cause original intention were to make Rate Limit framework agnostic.
With controller argument we are in situation, when interface is dictated by DI and symfony logic, that request and current controller can differ.
| use Noxlogic\RateLimitBundle\LimitProcessorInterface; | ||
| use Symfony\Component\HttpFoundation\Request; | ||
|
|
||
| class AnnotationLimitProcessor implements LimitProcessorInterface |
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.
Main reason to move it into the service - to create object only once via DI?
Disabling class in DI good approach. Maybe I wrong, but it doesn't bring big value, cause if annotation package is not available we need to disable rate_limit_annotation_listener. And without events usage, annotation class will not be used as well.
Before that changes, Util/AnnotationLimitProcessor.php were tightly coupled with symfony framework, cause its use symfony related attributes.
So in general, I agree, that it can be service class, cause in any case it right now symfony specific.
| public function getRateLimitAlias(Request $request) | ||
| public function getRateLimitAlias(Request $request, callable $controller) | ||
| { | ||
| $annotations = $request->attributes->get('_x-rate-limit', array()); |
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.
We are repeating this part in each of method.
I think, that its related to the fact, that current implementation with events implies very dynamic way to work with annotations. From my point of view, that fact push do not use service or need to rebuild service each time as new object.
Best option as I see - to load all annotation ahead, so we can really use fallback logic with chain of responsibility. Not sure if its possible in symfony, will try to find out. One worry, that it can be breacking change.
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.
Instantiating a new object is more expensive in therms of CPU than calling a method (but I think is too soon to consider this kind of optimizations).
Currently symfony does not allow to have dependency-injection containers per url/path, so this kind of if checks are inevitable. The same if was done here in the previous implementation.
But then based on that if condition was changing the underlying services, by swapping the rate limit processor with AnnotationLimitProcessor... that to me sounds a dirty trick. While the proposed implementation used the well known chain-of-responsibility pattern.
| } | ||
|
|
||
| public function getRateLimitAlias(Request $request) | ||
| public function getRateLimitAlias(Request $request, callable $controller) |
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.
Can't we use $request->attributes->get('_controller') as $controller ?
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.
That's definitely an option! That would be great
Hi, I have created this PR with the code changes I was suggesting.
Going to comment in the code the main changes