...

Source file src/github.com/gomodule/redigo/redis/zpop_example_test.go

Documentation: github.com/gomodule/redigo/redis

     1  // Copyright 2013 Gary Burd
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package redis_test
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"github.com/gomodule/redigo/redis"
    21  )
    22  
    23  // zpop pops a value from the ZSET key using WATCH/MULTI/EXEC commands.
    24  func zpop(c redis.Conn, key string) (result string, err error) {
    25  
    26  	defer func() {
    27  		// Return connection to normal state on error.
    28  		if err != nil {
    29  			c.Do("DISCARD")
    30  		}
    31  	}()
    32  
    33  	// Loop until transaction is successful.
    34  	for {
    35  		if _, err := c.Do("WATCH", key); err != nil {
    36  			return "", err
    37  		}
    38  
    39  		members, err := redis.Strings(c.Do("ZRANGE", key, 0, 0))
    40  		if err != nil {
    41  			return "", err
    42  		}
    43  		if len(members) != 1 {
    44  			return "", redis.ErrNil
    45  		}
    46  
    47  		c.Send("MULTI")
    48  		c.Send("ZREM", key, members[0])
    49  		queued, err := c.Do("EXEC")
    50  		if err != nil {
    51  			return "", err
    52  		}
    53  
    54  		if queued != nil {
    55  			result = members[0]
    56  			break
    57  		}
    58  	}
    59  
    60  	return result, nil
    61  }
    62  
    63  // zpopScript pops a value from a ZSET.
    64  var zpopScript = redis.NewScript(1, `
    65      local r = redis.call('ZRANGE', KEYS[1], 0, 0)
    66      if r ~= nil then
    67          r = r[1]
    68          redis.call('ZREM', KEYS[1], r)
    69      end
    70      return r
    71  `)
    72  
    73  // This example implements ZPOP as described at
    74  // http://redis.io/topics/transactions using WATCH/MULTI/EXEC and scripting.
    75  func Example_zpop() {
    76  	c, err := dial()
    77  	if err != nil {
    78  		fmt.Println(err)
    79  		return
    80  	}
    81  	defer c.Close()
    82  
    83  	// Add test data using a pipeline.
    84  
    85  	for i, member := range []string{"red", "blue", "green"} {
    86  		c.Send("ZADD", "zset", i, member)
    87  	}
    88  	if _, err := c.Do(""); err != nil {
    89  		fmt.Println(err)
    90  		return
    91  	}
    92  
    93  	// Pop using WATCH/MULTI/EXEC
    94  
    95  	v, err := zpop(c, "zset")
    96  	if err != nil {
    97  		fmt.Println(err)
    98  		return
    99  	}
   100  	fmt.Println(v)
   101  
   102  	// Pop using a script.
   103  
   104  	v, err = redis.String(zpopScript.Do(c, "zset"))
   105  	if err != nil {
   106  		fmt.Println(err)
   107  		return
   108  	}
   109  	fmt.Println(v)
   110  
   111  	// Output:
   112  	// red
   113  	// blue
   114  }
   115  

View as plain text