/** * Insert items into queue * @param PriorityItem[] $items * @return mixed */ public function enqueue(array $items) { //$t0 = the time that the next item currently in the queue will get expired (inf if nothing) //$best = the id corresponding to $t0 (0 if nothing) //$n = the number of items in $items array that are going to get expired sooner than $t0 $first = $this->redis->zrange($this->name, 0, 0, 'WITHSCORES'); if (count($first)) { $t0 = array_values($first)[0]; $best = array_keys($first)[0]; $n = 0; foreach ($items as $item) { if ($item->score < $t0) { $n++; } } } else { $t0 = INF; $best = 0; $n = count($items); } //zadd $items in the sorted set $this->queue->enqueue($items); //lpush $n flags into list "{$this->name}:$best" and make sure this list will expire soon if ($n) { $this->redis->lpush($this->name . ':' . $best, array_fill(0, $n, '')); $exp = $t0 != INF ? ceil($t0) : time() + 1; $this->redis->expireat($this->name . ':' . $best, $exp); } }
public function test_pop_multiple_elements_at_once() { $now = microtime(true); $input = [new PriorityItem('first', $now - 9), new PriorityItem('second', $now - 8), new PriorityItem('third', $now - 10), new PriorityItem('duplicate', $now), new PriorityItem('duplicate', $now)]; $this->queue->enqueue($input); $this->assertCount(5, $this->queue->dequeue(50)); }