summaryrefslogtreecommitdiff
path: root/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff')
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractBackoffStrategy.php91
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractErrorCodeBackoffStrategy.php40
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffLogger.php76
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffPlugin.php126
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffStrategyInterface.php30
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CallbackBackoffStrategy.php47
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ConstantBackoffStrategy.php34
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CurlBackoffStrategy.php28
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ExponentialBackoffStrategy.php25
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/HttpBackoffStrategy.php30
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/LinearBackoffStrategy.php36
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ReasonPhraseBackoffStrategy.php25
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/TruncatedBackoffStrategy.php36
-rw-r--r--vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/composer.json28
14 files changed, 652 insertions, 0 deletions
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractBackoffStrategy.php
new file mode 100644
index 0000000..0a85983
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractBackoffStrategy.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Abstract backoff strategy that allows for a chain of responsibility
+ */
+abstract class AbstractBackoffStrategy implements BackoffStrategyInterface
+{
+ /** @var AbstractBackoffStrategy Next strategy in the chain */
+ protected $next;
+
+ /** @param AbstractBackoffStrategy $next Next strategy in the chain */
+ public function setNext(AbstractBackoffStrategy $next)
+ {
+ $this->next = $next;
+ }
+
+ /**
+ * Get the next backoff strategy in the chain
+ *
+ * @return AbstractBackoffStrategy|null
+ */
+ public function getNext()
+ {
+ return $this->next;
+ }
+
+ public function getBackoffPeriod(
+ $retries,
+ RequestInterface $request,
+ Response $response = null,
+ HttpException $e = null
+ ) {
+ $delay = $this->getDelay($retries, $request, $response, $e);
+ if ($delay === false) {
+ // The strategy knows that this must not be retried
+ return false;
+ } elseif ($delay === null) {
+ // If the strategy is deferring a decision and the next strategy will not make a decision then return false
+ return !$this->next || !$this->next->makesDecision()
+ ? false
+ : $this->next->getBackoffPeriod($retries, $request, $response, $e);
+ } elseif ($delay === true) {
+ // if the strategy knows that it must retry but is deferring to the next to determine the delay
+ if (!$this->next) {
+ return 0;
+ } else {
+ $next = $this->next;
+ while ($next->makesDecision() && $next->getNext()) {
+ $next = $next->getNext();
+ }
+ return !$next->makesDecision() ? $next->getBackoffPeriod($retries, $request, $response, $e) : 0;
+ }
+ } else {
+ return $delay;
+ }
+ }
+
+ /**
+ * Check if the strategy does filtering and makes decisions on whether or not to retry.
+ *
+ * Strategies that return false will never retry if all of the previous strategies in a chain defer on a backoff
+ * decision.
+ *
+ * @return bool
+ */
+ abstract public function makesDecision();
+
+ /**
+ * Implement the concrete strategy
+ *
+ * @param int $retries Number of retries of the request
+ * @param RequestInterface $request Request that was sent
+ * @param Response $response Response that was received. Note that there may not be a response
+ * @param HttpException $e Exception that was encountered if any
+ *
+ * @return bool|int|null Returns false to not retry or the number of seconds to delay between retries. Return true
+ * or null to defer to the next strategy if available, and if not, return 0.
+ */
+ abstract protected function getDelay(
+ $retries,
+ RequestInterface $request,
+ Response $response = null,
+ HttpException $e = null
+ );
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractErrorCodeBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractErrorCodeBackoffStrategy.php
new file mode 100644
index 0000000..6ebee6c
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/AbstractErrorCodeBackoffStrategy.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+/**
+ * Strategy used to retry when certain error codes are encountered
+ */
+abstract class AbstractErrorCodeBackoffStrategy extends AbstractBackoffStrategy
+{
+ /** @var array Default cURL errors to retry */
+ protected static $defaultErrorCodes = array();
+
+ /** @var array Error codes that can be retried */
+ protected $errorCodes;
+
+ /**
+ * @param array $codes Array of codes that should be retried
+ * @param BackoffStrategyInterface $next The optional next strategy
+ */
+ public function __construct(array $codes = null, BackoffStrategyInterface $next = null)
+ {
+ $this->errorCodes = array_fill_keys($codes ?: static::$defaultErrorCodes, 1);
+ $this->next = $next;
+ }
+
+ /**
+ * Get the default failure codes to retry
+ *
+ * @return array
+ */
+ public static function getDefaultFailureCodes()
+ {
+ return static::$defaultErrorCodes;
+ }
+
+ public function makesDecision()
+ {
+ return true;
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffLogger.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffLogger.php
new file mode 100644
index 0000000..ec54c28
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffLogger.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Common\Event;
+use Guzzle\Log\LogAdapterInterface;
+use Guzzle\Log\MessageFormatter;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Logs backoff retries triggered from the BackoffPlugin
+ *
+ * Format your log messages using a template that can contain template substitutions found in {@see MessageFormatter}.
+ * In addition to the default template substitutions, there is also:
+ *
+ * - retries: The number of times the request has been retried
+ * - delay: The amount of time the request is being delayed
+ */
+class BackoffLogger implements EventSubscriberInterface
+{
+ /** @var string Default log message template */
+ const DEFAULT_FORMAT = '[{ts}] {method} {url} - {code} {phrase} - Retries: {retries}, Delay: {delay}, Time: {connect_time}, {total_time}, cURL: {curl_code} {curl_error}';
+
+ /** @var LogAdapterInterface Logger used to log retries */
+ protected $logger;
+
+ /** @var MessageFormatter Formatter used to format log messages */
+ protected $formatter;
+
+ /**
+ * @param LogAdapterInterface $logger Logger used to log the retries
+ * @param MessageFormatter $formatter Formatter used to format log messages
+ */
+ public function __construct(LogAdapterInterface $logger, MessageFormatter $formatter = null)
+ {
+ $this->logger = $logger;
+ $this->formatter = $formatter ?: new MessageFormatter(self::DEFAULT_FORMAT);
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(BackoffPlugin::RETRY_EVENT => 'onRequestRetry');
+ }
+
+ /**
+ * Set the template to use for logging
+ *
+ * @param string $template Log message template
+ *
+ * @return self
+ */
+ public function setTemplate($template)
+ {
+ $this->formatter->setTemplate($template);
+
+ return $this;
+ }
+
+ /**
+ * Called when a request is being retried
+ *
+ * @param Event $event Event emitted
+ */
+ public function onRequestRetry(Event $event)
+ {
+ $this->logger->log($this->formatter->format(
+ $event['request'],
+ $event['response'],
+ $event['handle'],
+ array(
+ 'retries' => $event['retries'],
+ 'delay' => $event['delay']
+ )
+ ));
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffPlugin.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffPlugin.php
new file mode 100644
index 0000000..99ace05
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffPlugin.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Common\Event;
+use Guzzle\Common\AbstractHasDispatcher;
+use Guzzle\Http\Message\EntityEnclosingRequestInterface;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Curl\CurlMultiInterface;
+use Guzzle\Http\Exception\CurlException;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Plugin to automatically retry failed HTTP requests using a backoff strategy
+ */
+class BackoffPlugin extends AbstractHasDispatcher implements EventSubscriberInterface
+{
+ const DELAY_PARAM = CurlMultiInterface::BLOCKING;
+ const RETRY_PARAM = 'plugins.backoff.retry_count';
+ const RETRY_EVENT = 'plugins.backoff.retry';
+
+ /** @var BackoffStrategyInterface Backoff strategy */
+ protected $strategy;
+
+ /**
+ * @param BackoffStrategyInterface $strategy The backoff strategy used to determine whether or not to retry and
+ * the amount of delay between retries.
+ */
+ public function __construct(BackoffStrategyInterface $strategy = null)
+ {
+ $this->strategy = $strategy;
+ }
+
+ /**
+ * Retrieve a basic truncated exponential backoff plugin that will retry HTTP errors and cURL errors
+ *
+ * @param int $maxRetries Maximum number of retries
+ * @param array $httpCodes HTTP response codes to retry
+ * @param array $curlCodes cURL error codes to retry
+ *
+ * @return self
+ */
+ public static function getExponentialBackoff(
+ $maxRetries = 3,
+ array $httpCodes = null,
+ array $curlCodes = null
+ ) {
+ return new self(new TruncatedBackoffStrategy($maxRetries,
+ new HttpBackoffStrategy($httpCodes,
+ new CurlBackoffStrategy($curlCodes,
+ new ExponentialBackoffStrategy()
+ )
+ )
+ ));
+ }
+
+ public static function getAllEvents()
+ {
+ return array(self::RETRY_EVENT);
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ 'request.sent' => 'onRequestSent',
+ 'request.exception' => 'onRequestSent',
+ CurlMultiInterface::POLLING_REQUEST => 'onRequestPoll'
+ );
+ }
+
+ /**
+ * Called when a request has been sent and isn't finished processing
+ *
+ * @param Event $event
+ */
+ public function onRequestSent(Event $event)
+ {
+ $request = $event['request'];
+ $response = $event['response'];
+ $exception = $event['exception'];
+
+ $params = $request->getParams();
+ $retries = (int) $params->get(self::RETRY_PARAM);
+ $delay = $this->strategy->getBackoffPeriod($retries, $request, $response, $exception);
+
+ if ($delay !== false) {
+ // Calculate how long to wait until the request should be retried
+ $params->set(self::RETRY_PARAM, ++$retries)
+ ->set(self::DELAY_PARAM, microtime(true) + $delay);
+ // Send the request again
+ $request->setState(RequestInterface::STATE_TRANSFER);
+ $this->dispatch(self::RETRY_EVENT, array(
+ 'request' => $request,
+ 'response' => $response,
+ 'handle' => ($exception && $exception instanceof CurlException) ? $exception->getCurlHandle() : null,
+ 'retries' => $retries,
+ 'delay' => $delay
+ ));
+ }
+ }
+
+ /**
+ * Called when a request is polling in the curl multi object
+ *
+ * @param Event $event
+ */
+ public function onRequestPoll(Event $event)
+ {
+ $request = $event['request'];
+ $delay = $request->getParams()->get(self::DELAY_PARAM);
+
+ // If the duration of the delay has passed, retry the request using the pool
+ if (null !== $delay && microtime(true) >= $delay) {
+ // Remove the request from the pool and then add it back again. This is required for cURL to know that we
+ // want to retry sending the easy handle.
+ $request->getParams()->remove(self::DELAY_PARAM);
+ // Rewind the request body if possible
+ if ($request instanceof EntityEnclosingRequestInterface && $request->getBody()) {
+ $request->getBody()->seek(0);
+ }
+ $multi = $event['curl_multi'];
+ $multi->remove($request);
+ $multi->add($request);
+ }
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffStrategyInterface.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffStrategyInterface.php
new file mode 100644
index 0000000..4e590db
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/BackoffStrategyInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Strategy to determine if a request should be retried and how long to delay between retries
+ */
+interface BackoffStrategyInterface
+{
+ /**
+ * Get the amount of time to delay in seconds before retrying a request
+ *
+ * @param int $retries Number of retries of the request
+ * @param RequestInterface $request Request that was sent
+ * @param Response $response Response that was received. Note that there may not be a response
+ * @param HttpException $e Exception that was encountered if any
+ *
+ * @return bool|int Returns false to not retry or the number of seconds to delay between retries
+ */
+ public function getBackoffPeriod(
+ $retries,
+ RequestInterface $request,
+ Response $response = null,
+ HttpException $e = null
+ );
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CallbackBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CallbackBackoffStrategy.php
new file mode 100644
index 0000000..b4f77c3
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CallbackBackoffStrategy.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Strategy that will invoke a closure to determine whether or not to retry with a delay
+ */
+class CallbackBackoffStrategy extends AbstractBackoffStrategy
+{
+ /** @var \Closure|array|mixed Callable method to invoke */
+ protected $callback;
+
+ /** @var bool Whether or not this strategy makes a retry decision */
+ protected $decision;
+
+ /**
+ * @param \Closure|array|mixed $callback Callable method to invoke
+ * @param bool $decision Set to true if this strategy makes a backoff decision
+ * @param BackoffStrategyInterface $next The optional next strategy
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct($callback, $decision, BackoffStrategyInterface $next = null)
+ {
+ if (!is_callable($callback)) {
+ throw new InvalidArgumentException('The callback must be callable');
+ }
+ $this->callback = $callback;
+ $this->decision = (bool) $decision;
+ $this->next = $next;
+ }
+
+ public function makesDecision()
+ {
+ return $this->decision;
+ }
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ return call_user_func($this->callback, $retries, $request, $response, $e);
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ConstantBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ConstantBackoffStrategy.php
new file mode 100644
index 0000000..061d2a4
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ConstantBackoffStrategy.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Will retry the request using the same amount of delay for each retry.
+ *
+ * Warning: If no decision making strategies precede this strategy in the the chain, then all requests will be retried
+ */
+class ConstantBackoffStrategy extends AbstractBackoffStrategy
+{
+ /** @var int Amount of time for each delay */
+ protected $delay;
+
+ /** @param int $delay Amount of time to delay between each additional backoff */
+ public function __construct($delay)
+ {
+ $this->delay = $delay;
+ }
+
+ public function makesDecision()
+ {
+ return false;
+ }
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ return $this->delay;
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CurlBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CurlBackoffStrategy.php
new file mode 100644
index 0000000..a584ed4
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/CurlBackoffStrategy.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+use Guzzle\Http\Exception\CurlException;
+
+/**
+ * Strategy used to retry when certain cURL error codes are encountered.
+ */
+class CurlBackoffStrategy extends AbstractErrorCodeBackoffStrategy
+{
+ /** @var array Default cURL errors to retry */
+ protected static $defaultErrorCodes = array(
+ CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_PARTIAL_FILE, CURLE_WRITE_ERROR, CURLE_READ_ERROR,
+ CURLE_OPERATION_TIMEOUTED, CURLE_SSL_CONNECT_ERROR, CURLE_HTTP_PORT_FAILED, CURLE_GOT_NOTHING,
+ CURLE_SEND_ERROR, CURLE_RECV_ERROR
+ );
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ if ($e && $e instanceof CurlException) {
+ return isset($this->errorCodes[$e->getErrorNo()]) ? true : null;
+ }
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ExponentialBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ExponentialBackoffStrategy.php
new file mode 100644
index 0000000..fb2912d
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ExponentialBackoffStrategy.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Implements an exponential backoff retry strategy.
+ *
+ * Warning: If no decision making strategies precede this strategy in the the chain, then all requests will be retried
+ */
+class ExponentialBackoffStrategy extends AbstractBackoffStrategy
+{
+ public function makesDecision()
+ {
+ return false;
+ }
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ return (int) pow(2, $retries);
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/HttpBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/HttpBackoffStrategy.php
new file mode 100644
index 0000000..9c63a14
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/HttpBackoffStrategy.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Strategy used to retry HTTP requests based on the response code.
+ *
+ * Retries 500 and 503 error by default.
+ */
+class HttpBackoffStrategy extends AbstractErrorCodeBackoffStrategy
+{
+ /** @var array Default cURL errors to retry */
+ protected static $defaultErrorCodes = array(500, 503);
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ if ($response) {
+ //Short circuit the rest of the checks if it was successful
+ if ($response->isSuccessful()) {
+ return false;
+ } else {
+ return isset($this->errorCodes[$response->getStatusCode()]) ? true : null;
+ }
+ }
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/LinearBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/LinearBackoffStrategy.php
new file mode 100644
index 0000000..b35e8a4
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/LinearBackoffStrategy.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Implements a linear backoff retry strategy.
+ *
+ * Warning: If no decision making strategies precede this strategy in the the chain, then all requests will be retried
+ */
+class LinearBackoffStrategy extends AbstractBackoffStrategy
+{
+ /** @var int Amount of time to progress each delay */
+ protected $step;
+
+ /**
+ * @param int $step Amount of time to increase the delay each additional backoff
+ */
+ public function __construct($step = 1)
+ {
+ $this->step = $step;
+ }
+
+ public function makesDecision()
+ {
+ return false;
+ }
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ return $retries * $this->step;
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ReasonPhraseBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ReasonPhraseBackoffStrategy.php
new file mode 100644
index 0000000..4fd73fe
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/ReasonPhraseBackoffStrategy.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Strategy used to retry HTTP requests when the response's reason phrase matches one of the registered phrases.
+ */
+class ReasonPhraseBackoffStrategy extends AbstractErrorCodeBackoffStrategy
+{
+ public function makesDecision()
+ {
+ return true;
+ }
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ if ($response) {
+ return isset($this->errorCodes[$response->getReasonPhrase()]) ? true : null;
+ }
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/TruncatedBackoffStrategy.php b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/TruncatedBackoffStrategy.php
new file mode 100644
index 0000000..3608f35
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/TruncatedBackoffStrategy.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Guzzle\Plugin\Backoff;
+
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
+use Guzzle\Http\Exception\HttpException;
+
+/**
+ * Strategy that will not retry more than a certain number of times.
+ */
+class TruncatedBackoffStrategy extends AbstractBackoffStrategy
+{
+ /** @var int Maximum number of retries per request */
+ protected $max;
+
+ /**
+ * @param int $maxRetries Maximum number of retries per request
+ * @param BackoffStrategyInterface $next The optional next strategy
+ */
+ public function __construct($maxRetries, BackoffStrategyInterface $next = null)
+ {
+ $this->max = $maxRetries;
+ $this->next = $next;
+ }
+
+ public function makesDecision()
+ {
+ return true;
+ }
+
+ protected function getDelay($retries, RequestInterface $request, Response $response = null, HttpException $e = null)
+ {
+ return $retries < $this->max ? null : false;
+ }
+}
diff --git a/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/composer.json b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/composer.json
new file mode 100644
index 0000000..91c122c
--- /dev/null
+++ b/vendor/guzzle/guzzle/src/Guzzle/Plugin/Backoff/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "guzzle/plugin-backoff",
+ "description": "Guzzle backoff retry plugins",
+ "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",
+ "guzzle/log": "self.version"
+ },
+ "autoload": {
+ "psr-0": { "Guzzle\\Plugin\\Backoff": "" }
+ },
+ "target-dir": "Guzzle/Plugin/Backoff",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.7-dev"
+ }
+ }
+}