FallbackExecutor.php 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. <?php
  2. namespace React\Dns\Query;
  3. use React\Promise\Promise;
  4. final class FallbackExecutor implements ExecutorInterface
  5. {
  6. private $executor;
  7. private $fallback;
  8. public function __construct(ExecutorInterface $executor, ExecutorInterface $fallback)
  9. {
  10. $this->executor = $executor;
  11. $this->fallback = $fallback;
  12. }
  13. public function query(Query $query)
  14. {
  15. $cancelled = false;
  16. $fallback = $this->fallback;
  17. $promise = $this->executor->query($query);
  18. return new Promise(function ($resolve, $reject) use (&$promise, $fallback, $query, &$cancelled) {
  19. $promise->then($resolve, function (\Exception $e1) use ($fallback, $query, $resolve, $reject, &$cancelled, &$promise) {
  20. // reject if primary resolution rejected due to cancellation
  21. if ($cancelled) {
  22. $reject($e1);
  23. return;
  24. }
  25. // start fallback query if primary query rejected
  26. $promise = $fallback->query($query)->then($resolve, function (\Exception $e2) use ($e1, $reject) {
  27. $append = $e2->getMessage();
  28. if (($pos = strpos($append, ':')) !== false) {
  29. $append = substr($append, $pos + 2);
  30. }
  31. // reject with combined error message if both queries fail
  32. $reject(new \RuntimeException($e1->getMessage() . '. ' . $append));
  33. });
  34. });
  35. }, function () use (&$promise, &$cancelled) {
  36. // cancel pending query (primary or fallback)
  37. $cancelled = true;
  38. $promise->cancel();
  39. });
  40. }
  41. }