Commit efd3757d authored by Slavi Pantaleev's avatar Slavi Pantaleev

Avoid Swift Mailer initialization if possible

The finish() filter flushing spool messages after each request
caused Swift Mailer to be initialized and all services in this
provider to be instantiated.

Doing all this work takes time and is potentially unnecessary,
since only a small number of all requests queue messages for sending.

The time it takes to initialize swiftmailer and all services is between
1 and 2ms on the 2 machines I tested on.
This seems like a big price to pay for just including a provider
that does nothing for most requests.
parent 0ae6c1e9
......@@ -21,11 +21,16 @@ use Silex\ServiceProviderInterface;
*/
class SwiftmailerServiceProvider implements ServiceProviderInterface
{
private $mailerFactory;
private $mailerCreated;
public function register(Application $app)
{
$app['swiftmailer.options'] = array();
$app['mailer'] = $app->share(function () use ($app) {
$self = $this;
$app['mailer'] = $this->mailerFactory = $app->share(function () use ($app, $self) {
$self->mailerCreated = true;
return new \Swift_Mailer($app['swiftmailer.spooltransport']);
});
......@@ -87,7 +92,13 @@ class SwiftmailerServiceProvider implements ServiceProviderInterface
throw new \RuntimeException('You have provided the swiftmailer.class_path parameter. The autoloader has been removed from Silex. It is recommended that you use Composer to manage your dependencies and handle your autoloading. If you are already using Composer, you can remove the parameter. See http://getcomposer.org for more information.');
}
$app->finish(function () use ($app) {
$self = $this;
$app->finish(function () use ($app, $self) {
//To speed things up (by avoiding Swift Mailer initialization), flush messages only if
//our mailer has been "used" or got replaced by another service we have no knowledge off.
if ($app->raw('mailer') === $self->mailerFactory && !$self->mailerCreated) {
return;
}
$app['swiftmailer.spooltransport']->getSpool()->flushQueue($app['swiftmailer.transport']);
});
}
......
......@@ -14,6 +14,7 @@ namespace Silex\Tests\Provider;
class SpoolStub implements \Swift_Spool
{
private $messages = array();
public $hasFlushed = false;
public function getMessages()
{
......@@ -40,6 +41,7 @@ class SpoolStub implements \Swift_Spool
public function flushQueue(\Swift_Transport $transport, &$failedRecipients = null)
{
$this->hasFlushed = true;
$this->messages = array();
}
}
......@@ -58,6 +58,78 @@ class SwiftmailerServiceProviderTest extends \PHPUnit_Framework_TestCase
$this->assertCount(1, $app['swiftmailer.spool']->getMessages());
$app->terminate($request, $response);
$this->assertTrue($app['swiftmailer.spool']->hasFlushed);
$this->assertCount(0, $app['swiftmailer.spool']->getMessages());
}
public function testSwiftMailerAvoidsFlushesIfPossible()
{
$app = new Application();
$app->register(new SwiftmailerServiceProvider());
$app->boot();
$app['swiftmailer.spool'] = $app->share(function () {
return new SpoolStub();
});
$app->get('/', function() use ($app) { });
$request = Request::create('/');
$response = $app->handle($request);
$this->assertCount(0, $app['swiftmailer.spool']->getMessages());
$app->terminate($request, $response);
$this->assertFalse($app['swiftmailer.spool']->hasFlushed);
}
public function testSwiftMailerWillAlwaysFlushIfServiceChanges()
{
$app = new Application();
$app->register(new SwiftmailerServiceProvider());
$app->boot();
$app['swiftmailer.spool'] = $app->share(function () {
return new SpoolStub();
});
$app['mailer'] = $app->share(function () {
return null; //No need to actually return a mailer instance
});
$app->get('/', function() use ($app) { });
$request = Request::create('/');
$response = $app->handle($request);
$this->assertCount(0, $app['swiftmailer.spool']->getMessages());
$app->terminate($request, $response);
$this->assertTrue($app['swiftmailer.spool']->hasFlushed);
}
public function testSwiftMailerWillAlwaysFlushIfServiceIsExtended()
{
$app = new Application();
$app->register(new SwiftmailerServiceProvider());
$app->boot();
$app['swiftmailer.spool'] = $app->share(function () {
return new SpoolStub();
});
$app->extend('mailer', function ($mailer) {
return $mailer;
});
$app->get('/', function() use ($app) { });
$request = Request::create('/');
$response = $app->handle($request);
$this->assertCount(0, $app['swiftmailer.spool']->getMessages());
$app->terminate($request, $response);
$this->assertTrue($app['swiftmailer.spool']->hasFlushed);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment