diff --git a/core/composer.json b/core/composer.json index 87e60b4..742c900 100644 --- a/core/composer.json +++ b/core/composer.json @@ -14,6 +14,7 @@ "twig/twig": "1.*@stable", "doctrine/common": "2.3.*@stable", "guzzle/http": "*", + "guzzle/plugin-async": "*", "kriswallsmith/assetic": "1.1.*@alpha" }, "minimum-stability": "dev" diff --git a/core/composer.lock b/core/composer.lock index 1894ab3..1f22641 100644 --- a/core/composer.lock +++ b/core/composer.lock @@ -1,5 +1,5 @@ { - "hash": "5d17aee0bd24c24563c2c864600fc5bd", + "hash": "8ab4946c8c768e6a4a5a7fb2277def24", "packages": [ { "name": "doctrine/common", @@ -202,6 +202,56 @@ ] }, { + "name": "guzzle/plugin-async", + "version": "dev-master", + "target-dir": "Guzzle/Plugin/Async", + "source": { + "type": "git", + "url": "https://github.com/guzzle/plugin-async", + "reference": "v3.0.6" + }, + "dist": { + "type": "zip", + "url": "https://github.com/guzzle/plugin-async/archive/v3.0.6.zip", + "reference": "v3.0.6", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "guzzle/http": "self.version" + }, + "time": "2012-12-07 16:45:11", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-0": { + "Guzzle\\Plugin\\Async": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle async request plugin", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "plugin", + "Guzzle" + ] + }, + { "name": "guzzle/stream", "version": "dev-master", "target-dir": "Guzzle/Stream", diff --git a/core/modules/system/system.module b/core/modules/system/system.module index eaaebc2..edbc312 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -3662,7 +3662,19 @@ function system_run_automated_cron() { if (($threshold = config('system.cron')->get('threshold.autorun')) > 0 && variable_get('install_task') == 'done') { $cron_last = state()->get('system.cron_last') ?: NULL; if (!isset($cron_last) || (REQUEST_TIME - $cron_last > $threshold)) { - drupal_cron_run(); + $client = drupal_container()->get('http_default_client'); + // Create and add the async plugin as a subscriber. + $async_plugin = new \Guzzle\Plugin\Async\AsyncPlugin(); + $client->addSubscriber($async_plugin); + + // Execute the asynchronous request. This will return immediately with a + // HTTP/1.1 200 OK and X-Guzzle-Async as the singe header. + $url = url('cron/' . state()->get('system.cron_key'), array('absolute' => TRUE)); + $client->get($url)->send(); + + // Remove th subscriber again so that other requests will be executed + // normally again. + $client->getEventDispatcher()->removeSubscriber($async_plugin); } } } diff --git a/core/vendor/autoload.php b/core/vendor/autoload.php index daa7ee7..0c78d80 100644 --- a/core/vendor/autoload.php +++ b/core/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592::getLoader(); +return ComposerAutoloaderInit1b1bfde48d1fdf9f47c829e275cb48f9::getLoader(); diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php index 9072401..80b1983 100644 --- a/core/vendor/composer/autoload_namespaces.php +++ b/core/vendor/composer/autoload_namespaces.php @@ -17,6 +17,7 @@ 'Symfony\\Component\\DependencyInjection\\' => $vendorDir . '/symfony/dependency-injection/', 'Symfony\\Component\\ClassLoader\\' => $vendorDir . '/symfony/class-loader/', 'Guzzle\\Stream' => $vendorDir . '/guzzle/stream/', + 'Guzzle\\Plugin\\Async' => $vendorDir . '/guzzle/plugin-async/', 'Guzzle\\Parser' => $vendorDir . '/guzzle/parser/', 'Guzzle\\Http' => $vendorDir . '/guzzle/http/', 'Guzzle\\Common' => $vendorDir . '/guzzle/common/', diff --git a/core/vendor/composer/autoload_real.php b/core/vendor/composer/autoload_real.php index dbe463c..81b229e 100644 --- a/core/vendor/composer/autoload_real.php +++ b/core/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php generated by Composer -class ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592 +class ComposerAutoloaderInit1b1bfde48d1fdf9f47c829e275cb48f9 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return static::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592', 'loadClassLoader')); + spl_autoload_register(array('ComposerAutoloaderInit1b1bfde48d1fdf9f47c829e275cb48f9', 'loadClassLoader')); static::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit295209ab8f7c3b45c210d28fa6db3592', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit1b1bfde48d1fdf9f47c829e275cb48f9', 'loadClassLoader')); $vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json index aaa926b..440392a 100644 --- a/core/vendor/composer/installed.json +++ b/core/vendor/composer/installed.json @@ -852,5 +852,56 @@ "client", "Guzzle" ] + }, + { + "name": "guzzle/plugin-async", + "version": "dev-master", + "version_normalized": "9999999-dev", + "target-dir": "Guzzle/Plugin/Async", + "source": { + "type": "git", + "url": "https://github.com/guzzle/plugin-async", + "reference": "v3.0.6" + }, + "dist": { + "type": "zip", + "url": "https://github.com/guzzle/plugin-async/archive/v3.0.6.zip", + "reference": "v3.0.6", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "guzzle/http": "self.version" + }, + "time": "2012-12-07 16:45:11", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-0": { + "Guzzle\\Plugin\\Async": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle async request plugin", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "plugin", + "Guzzle" + ] } ] diff --git a/core/vendor/guzzle/plugin-async/Guzzle/Plugin/Async/AsyncPlugin.php b/core/vendor/guzzle/plugin-async/Guzzle/Plugin/Async/AsyncPlugin.php new file mode 100644 index 0000000..7edc664 --- /dev/null +++ b/core/vendor/guzzle/plugin-async/Guzzle/Plugin/Async/AsyncPlugin.php @@ -0,0 +1,88 @@ + 'onBeforeSend', + 'request.exception' => 'onRequestTimeout', + 'request.sent' => 'onRequestSent', + 'curl.callback.progress' => 'onCurlProgress' + ); + } + + /** + * Event used to ensure that progress callback are emitted from the curl handle's request mediator. + * + * @param Event $event + */ + public function onBeforeSend(Event $event) + { + // Ensure that progress callbacks are dispatched + $event['request']->getCurlOptions()->set('progress', true); + } + + /** + * Event emitted when a curl progress function is called. When the amount of data uploaded == the amount of data to + * upload OR any bytes have been downloaded, then time the request out after 1ms because we're done with + * transmitting the request, and tell curl not download a body. + * + * @param Event $event + */ + public function onCurlProgress(Event $event) + { + if (!$event['handle']) { + return; + } + + if ($event['downloaded'] || ($event['uploaded'] || $event['upload_size'] === $event['uploaded'])) { + $event['handle']->getOptions() + ->set(CURLOPT_TIMEOUT_MS, 1) + ->set(CURLOPT_NOBODY, true); + // Timeout after 1ms + curl_setopt($event['handle']->getHandle(), CURLOPT_TIMEOUT_MS, 1); + // Even if the response is quick, tell curl not to download the body + curl_setopt($event['handle']->getHandle(), CURLOPT_NOBODY, true); + } + } + + /** + * Event emitted when a curl exception occurs. Ignore the exception and set a mock response. + * + * @param Event $event + */ + public function onRequestTimeout(Event $event) + { + if ($event['exception'] instanceof CurlException) { + $event['request']->setResponse(new Response(200, array( + 'X-Guzzle-Async' => 'Did not wait for the response' + ))); + } + } + + /** + * Event emitted when a request completes because it took less than 1ms. Add an X-Guzzle-Async header to notify the + * caller that there is no body in the message. + * + * @param Event $event + */ + public function onRequestSent(Event $event) + { + // Let the caller know this was meant to be async + $event['request']->getResponse()->setHeader('X-Guzzle-Async', 'Did not wait for the response'); + } +} diff --git a/core/vendor/guzzle/plugin-async/Guzzle/Plugin/Async/composer.json b/core/vendor/guzzle/plugin-async/Guzzle/Plugin/Async/composer.json new file mode 100644 index 0000000..12cd529 --- /dev/null +++ b/core/vendor/guzzle/plugin-async/Guzzle/Plugin/Async/composer.json @@ -0,0 +1,27 @@ +{ + "name": "guzzle/plugin-async", + "description": "Guzzle async request plugin", + "homepage": "http://guzzlephp.org/", + "keywords": ["plugin", "guzzle"], + "license": "MIT", + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "require": { + "php": ">=5.3.2", + "guzzle/http": "self.version" + }, + "autoload": { + "psr-0": { "Guzzle\\Plugin\\Async": "" } + }, + "target-dir": "Guzzle/Plugin/Async", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + } +}