1<?php
2
3/*
4 * This file is part of the Predis package.
5 *
6 * (c) Daniele Alessandri <suppakilla@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12require __DIR__.'/shared.php';
13
14// This is an implementation of an atomic client-side ZPOP using the support for
15// check-and-set (CAS) operations with MULTI/EXEC transactions, as described in
16// "WATCH explained" from http://redis.io/topics/transactions
17//
18// First, populate your database with a tiny sample data set:
19//
20// ./redis-cli
21// SELECT 15
22// ZADD zset 1 a 2 b 3 c
23//
24// Then execute this script four times and see its output.
25//
26
27function zpop($client, $key)
28{
29    $element = null;
30    $options = array(
31        'cas' => true,      // Initialize with support for CAS operations
32        'watch' => $key,    // Key that needs to be WATCHed to detect changes
33        'retry' => 3,       // Number of retries on aborted transactions, after
34                            // which the client bails out with an exception.
35    );
36
37    $client->transaction($options, function ($tx) use ($key, &$element) {
38        @list($element) = $tx->zrange($key, 0, 0);
39
40        if (isset($element)) {
41            $tx->multi();   // With CAS, MULTI *must* be explicitly invoked.
42            $tx->zrem($key, $element);
43        }
44    });
45
46    return $element;
47}
48
49$client = new Predis\Client($single_server);
50$zpopped = zpop($client, 'zset');
51
52echo isset($zpopped) ? "ZPOPed $zpopped" : 'Nothing to ZPOP!', PHP_EOL;
53