route/internal/database/redis.go

152 lines
2.8 KiB
Go

package database
import (
"encoding/json"
"time"
"github.com/Xe/uuid"
"github.com/brandur/simplebox"
"github.com/garyburd/redigo/redis"
"golang.org/x/net/context"
)
const (
redisCertPrefix = "routed:cert:"
redisRoutePrefix = "routed:route:"
redisTokenPrefix = "routed:token:"
)
type RedisStorage struct {
pool *redis.Pool
sb *simplebox.SimpleBox
cs *redisCertificateStorage
rs *redisRouteStorage
ts *redisTokenStorage
}
type redisCertificateStorage struct {
*RedisStorage
}
type redisRouteStorage struct {
*RedisStorage
}
func (r *redisRouteStorage) Get(ctx context.Context, id string) (Route, error) {
conn := r.pool.Get()
defer conn.Close()
data, err := redis.Bytes(conn.Do("GET", redisRoutePrefix+id))
if err != nil {
return Route{}, err
}
result := Route{}
err = json.Unmarshal(data, &result)
if err != nil {
return Route{}, err
}
return result, nil
}
func (r *redisRouteStorage) GetHost(ctx context.Context, host string) (Route, error) {
conn := r.pool.Get()
defer conn.Close()
key, err := redis.String(conn.Do("GET", redisRoutePrefix+"host:"+host))
if err != nil {
return Route{}, err
}
data, err := redis.Bytes(conn.Do("GET", key))
if err != nil {
return Route{}, err
}
result := Route{}
err = json.Unmarshal(data, &result)
if err != nil {
return Route{}, err
}
return result, nil
}
func (r *redisRouteStorage) GetAll(ctx context.Context) ([]Route, error) {
return nil, ErrNotImplemented
}
func (r *redisRouteStorage) Put(ctx context.Context, rr Route) (Route, error) {
if rr.ID == "" {
rr.ID = uuid.New()
rr.CreatedAt = time.Now()
rr.Active = true
}
rr.EditedAt = time.Now()
data, err := json.Marshal(&rr)
if err != nil {
return Route{}, err
}
conn := r.pool.Get()
defer conn.Close()
key := redisRoutePrefix + rr.ID
_, err = conn.Do("SET", key, data)
if err != nil {
return Route{}, err
}
_, err = conn.Do("SET", redisRoutePrefix+"host:"+rr.Hostname)
if err != nil {
return Route{}, err
}
return rr, nil
}
func (r *redisRouteStorage) Delete(ctx context.Context, rr Route) (Route, error) {
conn := r.pool.Get()
defer conn.Close()
key := redisRoutePrefix + rr.ID
dr, err := r.Get(ctx, rr.ID)
if err != nil {
return Route{}, err
}
_, err = conn.Do("DEL", key)
if err != nil {
return Route{}, err
}
_, err = conn.Do("DEL", redisRoutePrefix+"host:"+dr.Hostname)
if err != nil {
return Route{}, err
}
return dr, nil
}
type redisTokenStorage struct {
*RedisStorage
}
// Certs gets the certificate storage interface.
func (r *RedisStorage) Certs() Certs { return r.cs }
// Routes gets the route storage interface.
func (r *RedisStorage) Routes() Routes { return r.rs }
// Tokens gets the token storage interface.
func (r *RedisStorage) Tokens() Tokens { return r.ts }
// Close cleans up resources for this Storage.
func (r *RedisStorage) Close() error { return r.pool.Close() }