Adds a Symfony-specific shutdown strategy. This replaces the default PhpShutdownStrategy (register_shutdown_function) with a Symfony event-subscriber that reacts to the Kernel::TERMINATE event.
This is motivated by two benefits:
No memory leaks when running tests: memory used by the Bugsnag\Client can be garbage collected (this is not possible when register_shutdown_function is used).
Better performance: Symfony uses fastcgi_finish_request(), so if PHP-FPM is being used, the flush() call takes place after the HTTP connection has closed.
Design
Avoiding the memory leak when testing was the primary motivation. Potentially we could have done this by implementing conditional registration of the shutdown strategy (i.e. only register it in batch mode – current behaviour is to always register it within the Client constructor). This would have allowed users to test without the memory leak by setting batch_sending = false for the test environment.
Whilst conditional registration of the shutdown strategy is still desirable (why register one if we are not batch sending?), a better solution is to take advantage of Symfony's KernelEvents::TERMINATE event. When using WebTest to perform functional tests, Symfony's kernel is rebooted between tests (i.e. KernelEvents::TERMINATE is fired after the test). This destroys the DI container and allows memory to be garbage collected by PHP.
Changeset
Added
BugsnagShutdown class (implements ShutdownStrategyInterface + EventSubscriberInterface)
Changed
ClientFactory now instantiates Bugsnag\Client with the new shutdown strategy
services.yml has a new definition for bugsnag.shutdown + injection into ClientFactory
Tests
Added unit tests for new changes
Discussion
Alternative Approaches
As above, I considered @ryancastle's suggestion of removing the call to register_shutdown_function from the constructor (and calling it only when batch_sending = true).
Outstanding Questions
I think we should consider conditionally registering (or deregistering) the shutdown strategy depending on whether we are batching or sending synchronously.
Linked issues
Fixes #77
Review
For the submitter, initial self-review:
[x] Commented on code changes inline explain the reasoning behind the approach
[x] Reviewed the test cases added for completeness and possible points for discussion
[ ] A changelog entry was added for the goal of this pull request
[x] Check the scope of the changeset - is everything in the diff required for the pull request?
This pull request is ready for:
[ ] Initial review of the intended approach, not yet feature complete
[x] Structural review of the classes, functions, and properties modified
[ ] Final review
For the pull request reviewer(s), this changeset has been reviewed for:
[ ] Consistency across platforms for structures or concepts added or modified
[ ] Consistency between the changeset and the goal stated above
[ ] Internal consistency with the rest of the library - is there any overlap between existing interfaces and any which have been added?
[ ] Usage friction - is the proposed change in usage cumbersome or complicated?
[ ] Performance and complexity - are there any cases of unexpected O(n^3) when iterating, recursing, flat mapping, etc?
[ ] Concurrency concerns - if components are accessed asynchronously, what issues will arise
[ ] Thoroughness of added tests and any missing edge cases
Goal
Adds a Symfony-specific shutdown strategy. This replaces the default PhpShutdownStrategy (
register_shutdown_function
) with a Symfony event-subscriber that reacts to theKernel::TERMINATE
event.This is motivated by two benefits:
No memory leaks when running tests: memory used by the
Bugsnag\Client
can be garbage collected (this is not possible whenregister_shutdown_function
is used).Better performance: Symfony uses
fastcgi_finish_request()
, so if PHP-FPM is being used, theflush()
call takes place after the HTTP connection has closed.Design
Avoiding the memory leak when testing was the primary motivation. Potentially we could have done this by implementing conditional registration of the shutdown strategy (i.e. only register it in batch mode – current behaviour is to always register it within the Client constructor). This would have allowed users to test without the memory leak by setting
batch_sending = false
for the test environment.Whilst conditional registration of the shutdown strategy is still desirable (why register one if we are not batch sending?), a better solution is to take advantage of Symfony's
KernelEvents::TERMINATE
event. When usingWebTest
to perform functional tests, Symfony's kernel is rebooted between tests (i.e.KernelEvents::TERMINATE
is fired after the test). This destroys the DI container and allows memory to be garbage collected by PHP.Changeset
Added
Changed
Tests
Discussion
Alternative Approaches
As above, I considered @ryancastle's suggestion of removing the call to
register_shutdown_function
from the constructor (and calling it only whenbatch_sending = true
).Outstanding Questions
I think we should consider conditionally registering (or deregistering) the shutdown strategy depending on whether we are batching or sending synchronously.
Linked issues
Fixes #77
Review
For the submitter, initial self-review:
For the pull request reviewer(s), this changeset has been reviewed for: