2017-02-15 19:06:19 +01:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/garyburd/redigo/redis"
|
Publish the new version :airplane: | Look description please!
# FAQ
### Looking for free support?
http://support.iris-go.com
https://kataras.rocket.chat/channel/iris
### Looking for previous versions?
https://github.com/kataras/iris#version
### Should I upgrade my Iris?
Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).
### About our new home page
http://iris-go.com
Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!
[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.
The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!
Read more at https://github.com/kataras/iris/blob/master/HISTORY.md
Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
2017-06-03 22:22:52 +02:00
|
|
|
"github.com/kataras/iris/core/errors"
|
2017-02-15 19:06:19 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// ErrRedisClosed an error with message 'Redis is already closed'
|
|
|
|
ErrRedisClosed = errors.New("Redis is already closed")
|
|
|
|
// ErrKeyNotFound an error with message 'Key $thekey doesn't found'
|
|
|
|
ErrKeyNotFound = errors.New("Key '%s' doesn't found")
|
|
|
|
)
|
|
|
|
|
|
|
|
// Service the Redis service, contains the config and the redis pool
|
|
|
|
type Service struct {
|
|
|
|
// Connected is true when the Service has already connected
|
|
|
|
Connected bool
|
|
|
|
// Config the redis config for this redis
|
|
|
|
Config *Config
|
|
|
|
pool *redis.Pool
|
|
|
|
}
|
|
|
|
|
|
|
|
// PingPong sends a ping and receives a pong, if no pong received then returns false and filled error
|
|
|
|
func (r *Service) PingPong() (bool, error) {
|
|
|
|
c := r.pool.Get()
|
|
|
|
defer c.Close()
|
|
|
|
msg, err := c.Do("PING")
|
|
|
|
if err != nil || msg == nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
return (msg == "PONG"), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CloseConnection closes the redis connection
|
|
|
|
func (r *Service) CloseConnection() error {
|
|
|
|
if r.pool != nil {
|
|
|
|
return r.pool.Close()
|
|
|
|
}
|
|
|
|
return ErrRedisClosed
|
|
|
|
}
|
|
|
|
|
2017-08-07 05:04:35 +02:00
|
|
|
// Set sets a key-value to the redis store.
|
|
|
|
// The expiration is setted by the MaxAgeSeconds.
|
2017-08-08 11:31:42 +02:00
|
|
|
func (r *Service) Set(key string, value interface{}, secondsLifetime int) (err error) {
|
2017-02-15 19:06:19 +01:00
|
|
|
c := r.pool.Get()
|
|
|
|
defer c.Close()
|
2017-08-07 05:04:35 +02:00
|
|
|
if c.Err() != nil {
|
|
|
|
return c.Err()
|
2017-02-15 19:06:19 +01:00
|
|
|
}
|
2017-08-07 05:04:35 +02:00
|
|
|
|
2017-08-08 11:31:42 +02:00
|
|
|
// if has expiration, then use the "EX" to delete the key automatically.
|
|
|
|
if secondsLifetime > 0 {
|
|
|
|
_, err = c.Do("SETEX", r.Config.Prefix+key, secondsLifetime, value)
|
|
|
|
} else {
|
|
|
|
_, err = c.Do("SET", r.Config.Prefix+key, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2017-02-15 19:06:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get returns value, err by its key
|
2017-08-07 05:04:35 +02:00
|
|
|
//returns nil and a filled error if something bad happened.
|
2017-02-15 19:06:19 +01:00
|
|
|
func (r *Service) Get(key string) (interface{}, error) {
|
|
|
|
c := r.pool.Get()
|
|
|
|
defer c.Close()
|
|
|
|
if err := c.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
redisVal, err := c.Do("GET", r.Config.Prefix+key)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if redisVal == nil {
|
|
|
|
return nil, ErrKeyNotFound.Format(key)
|
|
|
|
}
|
|
|
|
return redisVal, nil
|
|
|
|
}
|
|
|
|
|
2017-08-07 05:04:35 +02:00
|
|
|
// GetAll returns all redis entries using the "SCAN" command (2.8+).
|
|
|
|
func (r *Service) GetAll() (interface{}, error) {
|
2017-02-15 19:06:19 +01:00
|
|
|
c := r.pool.Get()
|
|
|
|
defer c.Close()
|
|
|
|
if err := c.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-08-07 05:04:35 +02:00
|
|
|
redisVal, err := c.Do("SCAN", 0) // 0 -> cursor
|
2017-02-15 19:06:19 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if redisVal == nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-08-07 05:04:35 +02:00
|
|
|
return redisVal, nil
|
2017-02-15 19:06:19 +01:00
|
|
|
}
|
|
|
|
|
2017-08-07 05:04:35 +02:00
|
|
|
// GetBytes returns value, err by its key
|
|
|
|
// you can use utils.Deserialize((.GetBytes("yourkey"),&theobject{})
|
|
|
|
//returns nil and a filled error if something wrong happens
|
|
|
|
func (r *Service) GetBytes(key string) ([]byte, error) {
|
2017-02-15 19:06:19 +01:00
|
|
|
c := r.pool.Get()
|
|
|
|
defer c.Close()
|
|
|
|
if err := c.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-08-07 05:04:35 +02:00
|
|
|
redisVal, err := c.Do("GET", r.Config.Prefix+key)
|
2017-02-15 19:06:19 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-08-07 05:04:35 +02:00
|
|
|
if redisVal == nil {
|
|
|
|
return nil, ErrKeyNotFound.Format(key)
|
2017-02-15 19:06:19 +01:00
|
|
|
}
|
|
|
|
|
2017-08-07 05:04:35 +02:00
|
|
|
return redis.Bytes(redisVal, err)
|
2017-02-15 19:06:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delete removes redis entry by specific key
|
|
|
|
func (r *Service) Delete(key string) error {
|
|
|
|
c := r.pool.Get()
|
|
|
|
defer c.Close()
|
|
|
|
if _, err := c.Do("DEL", r.Config.Prefix+key); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func dial(network string, addr string, pass string) (redis.Conn, error) {
|
|
|
|
if network == "" {
|
|
|
|
network = DefaultRedisNetwork
|
|
|
|
}
|
|
|
|
if addr == "" {
|
|
|
|
addr = DefaultRedisAddr
|
|
|
|
}
|
|
|
|
c, err := redis.Dial(network, addr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if pass != "" {
|
|
|
|
if _, err = c.Do("AUTH", pass); err != nil {
|
|
|
|
c.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect connects to the redis, called only once
|
|
|
|
func (r *Service) Connect() {
|
|
|
|
c := r.Config
|
|
|
|
|
|
|
|
if c.IdleTimeout <= 0 {
|
|
|
|
c.IdleTimeout = DefaultRedisIdleTimeout
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Network == "" {
|
|
|
|
c.Network = DefaultRedisNetwork
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Addr == "" {
|
|
|
|
c.Addr = DefaultRedisAddr
|
|
|
|
}
|
|
|
|
|
|
|
|
pool := &redis.Pool{IdleTimeout: DefaultRedisIdleTimeout, MaxIdle: c.MaxIdle, MaxActive: c.MaxActive}
|
|
|
|
pool.TestOnBorrow = func(c redis.Conn, t time.Time) error {
|
|
|
|
_, err := c.Do("PING")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Database != "" {
|
|
|
|
pool.Dial = func() (redis.Conn, error) {
|
|
|
|
red, err := dial(c.Network, c.Addr, c.Password)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if _, err = red.Do("SELECT", c.Database); err != nil {
|
|
|
|
red.Close()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return red, err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pool.Dial = func() (redis.Conn, error) {
|
|
|
|
return dial(c.Network, c.Addr, c.Password)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r.Connected = true
|
|
|
|
r.pool = pool
|
|
|
|
}
|
|
|
|
|
|
|
|
// New returns a Redis service filled by the passed config
|
2017-07-10 17:32:42 +02:00
|
|
|
// to connect call the .Connect().
|
2017-02-15 19:06:19 +01:00
|
|
|
func New(cfg ...Config) *Service {
|
2017-07-10 17:32:42 +02:00
|
|
|
c := DefaultConfig()
|
|
|
|
if len(cfg) > 0 {
|
|
|
|
c = cfg[0]
|
|
|
|
}
|
2017-02-15 19:06:19 +01:00
|
|
|
r := &Service{pool: &redis.Pool{}, Config: &c}
|
|
|
|
return r
|
|
|
|
}
|