public function until(callable $invokable, $context = null) { if (!$context) { $context = new Context(); } try { $context->inc(); $ret = call_user_func($invokable, $context); } catch (\Exception $e) { } finally { if (!$context->isValid() && $context->getTimes() < $this->times) { $ret = $this->until($invokable, $context); } if ($context->getTimes() >= $this->times && isset($e)) { throw $e; } } return $ret; }