/**
     * Remove and return items from the queue
     *
     * @param int $n maximum number of items to be popped
     * @param int $timeout maximum time (in seconds) to wait for new items when the queue is empty
     * @return PriorityItem[] array of at most $n items popped from the queue
     */
    public function dequeue($n = 1, $timeout = 0)
    {
        //do a non-blocking dequeue, return on success
        $result = $this->queue->dequeue($n, 0);
        if (count($result) || $timeout < 1) {
            return $result;
        }
        $start = microtime(true);
        //if nothing popped: while timeout is not reached do the following:
        while (($loopStart = microtime(true)) < $start + $timeout + 1) {
            $result = $this->queue->dequeue($n, 0);
            if (count($result)) {
                return $result;
            }
            //find $t0 and $best as declared in $this->enqueue()
            $first = $this->redis->zrange($this->name, 0, 0, 'WITHSCORES');
            if (count($first)) {
                $t0 = array_values($first)[0];
                $best = array_keys($first)[0];
            } else {
                $t0 = $start + $timeout;
                $best = 0;
            }
            //$x = blpop "{$this->name}:$best", $t0
            //if $x: dequeue, if something is dequeued return
            $timeToWait = max(1, ceil(min($timeout - $loopStart + $start, $t0 - $loopStart)));
            $items = $this->redis->blpop([$this->name . ':' . $best], $timeToWait);
            if (is_null($items)) {
                continue;
            }
            $items = [$items[1]];
            if ($n > 1) {
                $lua = <<<LUA
                local values = redis.call('lrange', KEYS[1], 0, KEYS[2] - 1)
                redis.call('ltrim', KEYS[1], KEYS[2], - 1)
                return values
LUA;
                $remainingItems = $this->redis->eval($lua, 2, $this->name . ':' . $best, $n - 1);
                $items = array_merge($items, $remainingItems);
            }
            $result = $this->queue->dequeue(count($items));
            if (count($result)) {
                return $result;
            }
        }
        return [];
    }
 public function test_blocking_pop_from_empty_queue()
 {
     $start = time();
     $this->assertEquals([], $this->queue->dequeue(1, 1));
     $this->assertGreaterThan($start, time());
 }