public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null)
{
if ($this->scheduler !== null) {
$scheduler = $this->scheduler;
}
if ($scheduler === null) {
throw new \Exception("You must use a scheduler that support non-zero delay.");
}
/** @var AnonymousObservable $observable */
$disp = $observable->materialize()->timestamp()->map(function (Timestamped $x) {
return new Timestamped($x->getTimestampMillis() + $this->delayTime, $x->getValue());
})->subscribe(new CallbackObserver(function (Timestamped $x) use($scheduler, $observer) {
if ($x->getValue() instanceof Notification\OnErrorNotification) {
$x->getValue()->accept($observer);
return;
}
$this->queue->enqueue($x);
if ($this->schedulerDisposable === null) {
$doScheduledStuff = function () use($observer, $scheduler, &$doScheduledStuff) {
while (!$this->queue->isEmpty() && $scheduler->now() >= $this->queue->bottom()->getTimestampMillis()) {
/** @var Timestamped $item */
$item = $this->queue->dequeue();
/** @var Notification $materializedValue */
$materializedValue = $item->getValue();
$materializedValue->accept($observer);
}
if ($this->queue->isEmpty()) {
$this->schedulerDisposable = null;
return;
}
$this->schedulerDisposable = $scheduler->schedule($doScheduledStuff, $this->queue->bottom()->getTimestampMillis() - $scheduler->now());
};
$doScheduledStuff();
}
}, [$observer, 'onError']), $scheduler);
return new CallbackDisposable(function () use($disp) {
if ($this->schedulerDisposable) {
$this->schedulerDisposable->dispose();
}
$disp->dispose();
});
}