Esempio n. 1
0
func TestScript(t *testing.T) {
	c, err := redistest.Dial()
	if err != nil {
		t.Fatalf("error connection to database, %v", err)
	}
	defer c.Close()

	// To test fall back in Do, we make script unique by adding comment with current time.
	script := fmt.Sprintf("--%d\nreturn {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", time.Now().UnixNano())
	s := redis.NewScript(2, script)
	reply := []interface{}{[]byte("key1"), []byte("key2"), []byte("arg1"), []byte("arg2")}

	v, err := s.Do(c, "key1", "key2", "arg1", "arg2")
	if err != nil {
		t.Errorf("s.Do(c, ...) returned %v", err)
	}

	if !reflect.DeepEqual(v, reply) {
		t.Errorf("s.Do(c, ..); = %v, want %v", v, reply)
	}

	err = s.Load(c)
	if err != nil {
		t.Errorf("s.Load(c) returned %v", err)
	}

	err = s.SendHash(c, "key1", "key2", "arg1", "arg2")
	if err != nil {
		t.Errorf("s.SendHash(c, ...) returned %v", err)
	}

	err = c.Flush()
	if err != nil {
		t.Errorf("c.Flush() returned %v", err)
	}

	v, err = c.Receive()
	if !reflect.DeepEqual(v, reply) {
		t.Errorf("s.SendHash(c, ..); c.Receive() = %v, want %v", v, reply)
	}

	err = s.Send(c, "key1", "key2", "arg1", "arg2")
	if err != nil {
		t.Errorf("s.Send(c, ...) returned %v", err)
	}

	err = c.Flush()
	if err != nil {
		t.Errorf("c.Flush() returned %v", err)
	}

	v, err = c.Receive()
	if !reflect.DeepEqual(v, reply) {
		t.Errorf("s.Send(c, ..); c.Receive() = %v, want %v", v, reply)
	}

}
Esempio n. 2
0
func ExampleScript(c redis.Conn, reply interface{}, err error) {
	// Initialize a package-level variable with a script.
	var getScript = redis.NewScript(1, `return redis.call('get', KEYS[1])`)

	// In a function, use the script Do method to evaluate the script. The Do
	// method optimistically uses the EVALSHA command. If the script is not
	// loaded, then the Do method falls back to the EVAL command.
	reply, err = getScript.Do(c, "foo")
}
Esempio n. 3
0
// NewRedisEngine initializes Redis Engine.
func NewRedisEngine(app *Application, conf *RedisEngineConfig) *RedisEngine {
	host := conf.Host
	port := conf.Port
	password := conf.Password

	db := "0"
	if conf.DB != "" {
		db = conf.DB
	}

	// If URL set then prefer it over other parameters.
	if conf.URL != "" {
		u, err := url.Parse(conf.URL)
		if err != nil {
			logger.FATAL.Fatalln(err)
		}
		if u.User != nil {
			var ok bool
			password, ok = u.User.Password()
			if !ok {
				password = ""
			}
		}
		host, port, err = net.SplitHostPort(u.Host)
		if err != nil {
			logger.FATAL.Fatalln(err)
		}
		path := u.Path
		if path != "" {
			db = path[1:]
		}
	}

	server := host + ":" + port

	pool := newPool(server, password, db, conf.PoolSize)

	// pubScriptSource contains lua script we register in Redis to call when publishing
	// client message. It publishes message into channel and adds message to history
	// list maintaining history size and expiration time. This is an optimization to make
	// 1 round trip to Redis instead of 2.
	// KEYS[1] - history list key
	// ARGV[1] - channel to publish message to
	// ARGV[2] - message payload
	// ARGV[3] - history message payload
	// ARGV[4] - history size
	// ARGV[5] - history lifetime
	// ARGV[6] - history drop inactive flag - "0" or "1"
	pubScriptSource := `
local n = redis.call("publish", ARGV[1], ARGV[2])
local m = 0
if ARGV[6] == "1" and n == 0 then
  m = redis.call("lpushx", KEYS[1], ARGV[3])
else
  m = redis.call("lpush", KEYS[1], ARGV[3])
end
if m > 0 then
  redis.call("ltrim", KEYS[1], 0, ARGV[4])
  redis.call("expire", KEYS[1], ARGV[5])
end
return n
	`

	e := &RedisEngine{
		app:          app,
		pool:         pool,
		api:          conf.API,
		numApiShards: conf.NumAPIShards,
		pubScript:    redis.NewScript(1, pubScriptSource),
	}
	usingPassword := yesno(password != "")
	apiEnabled := yesno(conf.API)
	var shardsSuffix string
	if conf.API {
		shardsSuffix = fmt.Sprintf(", num shard queues: %d", conf.NumAPIShards)
	}
	logger.INFO.Printf("Redis engine: %s/%s, pool: %d, using password: %s, API enabled: %s%s\n", server, db, conf.PoolSize, usingPassword, apiEnabled, shardsSuffix)
	e.subCh = make(chan subRequest, RedisSubscribeChannelSize)
	e.unSubCh = make(chan subRequest, RedisSubscribeChannelSize)
	return e
}
Esempio n. 4
0
		}

		if queued != nil {
			result = members[0]
			break
		}
	}

	return result, nil
}

// zpopScript pops a value from a ZSET.
var zpopScript = redis.NewScript(1, `
    local r = redis.call('ZRANGE', KEYS[1], 0, 0)
    if r ~= nil then
        r = r[1]
        redis.call('ZREM', KEYS[1], r)
    end
    return r
`)

// This example implements ZPOP as described at
// http://redis.io/topics/transactions using WATCH/MULTI/EXEC and scripting.
func Example_zpop() {
	c, err := dial()
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Close()

	// Add test data using a pipeline.