Пример #1
0
// NewClient creates a sentinel client. Connects to the given sentinel instance,
// pulls the information for the masters of the given names, and creates an
// intial pool of connections for each master. The client will automatically
// replace the pool for any master should sentinel decide to fail the master
// over. The returned error is a *ClientError.
func NewClient(
	network, address string, poolSize int, names ...string,
) (
	*Client, error,
) {

	// We use this to fetch initial details about masters before we upgrade it
	// to a pubsub client
	client, err := redis.Dial(network, address)
	if err != nil {
		return nil, &ClientError{err: err}
	}

	masterPools := map[string]*pool.Pool{}
	for _, name := range names {
		r := client.Cmd("SENTINEL", "MASTER", name)
		l, err := r.List()
		if err != nil {
			return nil, &ClientError{err: err, SentinelErr: true}
		}
		addr := l[3] + ":" + l[5]
		pool, err := pool.New("tcp", addr, poolSize)
		if err != nil {
			return nil, &ClientError{err: err}
		}
		masterPools[name] = pool
	}

	subClient := pubsub.NewSubClient(client)
	subSendErr := subClient.Subscribe("+switch-master")
	if subSendErr != nil {
		return nil, &ClientError{err: subSendErr, SentinelErr: true}
	}
	r := client.ReadResp()
	if r.Err != nil {
		return nil, &ClientError{err: r.Err, SentinelErr: true}
	}

	c := &Client{
		poolSize:       poolSize,
		masterPools:    masterPools,
		subClient:      subClient,
		getCh:          make(chan *getReq),
		putCh:          make(chan *putReq),
		closeCh:        make(chan struct{}),
		alwaysErrCh:    make(chan *ClientError),
		switchMasterCh: make(chan *switchMaster),
	}

	go c.subSpin()
	go c.spin()
	return c, nil
}
Пример #2
0
// Similar to TestScan, but scans over a set instead of the whole key space
func TestSScan(t *T) {
	client, err := redis.Dial("tcp", "127.0.0.1:6379")
	require.Nil(t, err)

	key := "scanTestSet"

	fullMap := map[string]bool{}
	for i := 0; i < 100; i++ {
		elem := strconv.Itoa(i)
		fullMap[elem] = true
		require.Nil(t, client.Cmd("SADD", key, elem).Err)
	}

	// make sure we get all results when scanning with an existing prefix
	ch := make(chan string)
	go func() {
		err = Scan(client, ch, "SSCAN", key, "*")
	}()
	testMap := map[string]bool{}
	for elem := range ch {
		testMap[elem] = true
	}
	require.Nil(t, err)
	assert.Equal(t, fullMap, testMap)

	// make sure we don't get any results when scanning with a non-existing
	// prefix
	ch = make(chan string)
	go func() {
		err = Scan(client, ch, "SSCAN", key+"DNE", "*")
	}()
	testMap = map[string]bool{}
	for elem := range ch {
		testMap[elem] = true
	}
	require.Nil(t, err)
	assert.Equal(t, map[string]bool{}, testMap)
}
Пример #3
0
func TestScan(t *T) {
	client, err := redis.Dial("tcp", "127.0.0.1:6379")
	require.Nil(t, err)

	prefix := "scanTestPrefix"

	fullMap := map[string]bool{}
	for i := 0; i < 100; i++ {
		key := prefix + ":" + strconv.Itoa(i)
		fullMap[key] = true
		require.Nil(t, client.Cmd("SET", key, "1").Err)
	}

	// make sure we get all results when scanning with an existing prefix
	ch := make(chan string)
	go func() {
		err = Scan(client, ch, "SCAN", "", prefix+":*")
	}()
	testMap := map[string]bool{}
	for key := range ch {
		testMap[key] = true
	}
	require.Nil(t, err)
	assert.Equal(t, fullMap, testMap)

	// make sure we don't get any results when scanning with a non-existing
	// prefix
	ch = make(chan string)
	go func() {
		err = Scan(client, ch, "SCAN", "", prefix+"DNE:*")
	}()
	testMap = map[string]bool{}
	for key := range ch {
		testMap[key] = true
	}
	require.Nil(t, err)
	assert.Equal(t, map[string]bool{}, testMap)
}