2017-08-14 23:36:22 +05:30
|
|
|
package db
|
2017-06-30 21:10:25 +05:30
|
|
|
|
|
|
|
import (
|
2017-08-10 05:44:28 +05:30
|
|
|
"bytes"
|
|
|
|
"compress/zlib"
|
2017-06-30 21:10:25 +05:30
|
|
|
"encoding/json"
|
2017-08-14 23:36:22 +05:30
|
|
|
"fmt"
|
2017-08-10 05:44:28 +05:30
|
|
|
"io"
|
2017-06-30 21:10:25 +05:30
|
|
|
"log"
|
2017-08-10 05:44:28 +05:30
|
|
|
"strings"
|
2017-06-30 21:10:25 +05:30
|
|
|
|
2017-08-10 05:44:28 +05:30
|
|
|
"github.com/mediocregopher/radix.v2/pool"
|
2017-06-30 21:10:25 +05:30
|
|
|
"github.com/mediocregopher/radix.v2/redis"
|
|
|
|
"github.com/mediocregopher/radix.v2/util"
|
2017-08-10 05:44:28 +05:30
|
|
|
|
|
|
|
"elyby/minecraft-skinsystem/model"
|
|
|
|
"elyby/minecraft-skinsystem/repositories"
|
2017-06-30 21:10:25 +05:30
|
|
|
)
|
|
|
|
|
2017-08-14 23:36:22 +05:30
|
|
|
type RedisFactory struct {
|
|
|
|
Host string
|
|
|
|
Port int
|
|
|
|
PoolSize int
|
|
|
|
connection util.Cmder
|
2017-08-10 05:44:28 +05:30
|
|
|
}
|
|
|
|
|
2017-08-14 23:36:22 +05:30
|
|
|
func (f RedisFactory) CreateSkinsRepository() (repositories.SkinsRepository, error) {
|
|
|
|
connection, err := f.getConnection()
|
2017-08-10 05:44:28 +05:30
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-08-14 23:36:22 +05:30
|
|
|
return &redisDb{connection}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f RedisFactory) CreateCapesRepository() (repositories.CapesRepository, error) {
|
|
|
|
panic("capes repository not supported for this storage type")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f RedisFactory) getConnection() (util.Cmder, error) {
|
|
|
|
if f.connection == nil {
|
|
|
|
if f.Host == "" {
|
|
|
|
return nil, &ParamRequired{"host"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if f.Port == 0 {
|
|
|
|
return nil, &ParamRequired{"port"}
|
|
|
|
}
|
|
|
|
|
|
|
|
var conn util.Cmder
|
|
|
|
var err error
|
|
|
|
addr := fmt.Sprintf("%s:%d", f.Host, f.Port)
|
|
|
|
if f.PoolSize > 1 {
|
|
|
|
conn, err = pool.New("tcp", addr, f.PoolSize)
|
|
|
|
} else {
|
|
|
|
conn, err = redis.Dial("tcp", addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.connection = conn
|
|
|
|
}
|
2017-08-10 05:44:28 +05:30
|
|
|
|
2017-08-14 23:36:22 +05:30
|
|
|
return f.connection, nil
|
2017-08-10 05:44:28 +05:30
|
|
|
}
|
|
|
|
|
2017-06-30 21:10:25 +05:30
|
|
|
type redisDb struct {
|
|
|
|
conn util.Cmder
|
|
|
|
}
|
|
|
|
|
|
|
|
const accountIdToUsernameKey string = "hash:username-to-account-id"
|
|
|
|
|
|
|
|
func (db *redisDb) FindByUsername(username string) (model.Skin, error) {
|
|
|
|
var record model.Skin
|
2017-08-09 21:41:53 +05:30
|
|
|
if username == "" {
|
2017-08-10 05:30:02 +05:30
|
|
|
return record, &SkinNotFoundError{username}
|
2017-08-09 21:41:53 +05:30
|
|
|
}
|
|
|
|
|
2017-06-30 21:10:25 +05:30
|
|
|
redisKey := buildKey(username)
|
|
|
|
response := db.conn.Cmd("GET", redisKey)
|
|
|
|
if response.IsType(redis.Nil) {
|
2017-08-10 05:30:02 +05:30
|
|
|
return record, &SkinNotFoundError{username}
|
2017-06-30 21:10:25 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
encodedResult, err := response.Bytes()
|
|
|
|
if err == nil {
|
|
|
|
result, err := zlibDecode(encodedResult)
|
|
|
|
if err != nil {
|
2017-08-14 23:36:22 +05:30
|
|
|
log.Println("Cannot uncompress zlib for key " + redisKey) // TODO: replace with valid error
|
2017-08-10 05:30:02 +05:30
|
|
|
return record, err
|
2017-06-30 21:10:25 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
err = json.Unmarshal(result, &record)
|
|
|
|
if err != nil {
|
2017-08-14 23:36:22 +05:30
|
|
|
log.Println("Cannot decode record data for key" + redisKey) // TODO: replace with valid error
|
2017-08-10 05:30:02 +05:30
|
|
|
return record, nil
|
2017-06-30 21:10:25 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
record.OldUsername = record.Username
|
|
|
|
}
|
|
|
|
|
2017-08-10 05:30:02 +05:30
|
|
|
return record, nil
|
2017-06-30 21:10:25 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
func (db *redisDb) FindByUserId(id int) (model.Skin, error) {
|
|
|
|
response := db.conn.Cmd("HGET", accountIdToUsernameKey, id)
|
|
|
|
if response.IsType(redis.Nil) {
|
2017-07-02 06:05:38 +05:30
|
|
|
return model.Skin{}, SkinNotFoundError{"unknown"}
|
2017-06-30 21:10:25 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
username, _ := response.Str()
|
|
|
|
|
|
|
|
return db.FindByUsername(username)
|
|
|
|
}
|
2017-08-10 05:44:28 +05:30
|
|
|
|
|
|
|
func buildKey(username string) string {
|
|
|
|
return "username:" + strings.ToLower(username)
|
|
|
|
}
|
|
|
|
|
|
|
|
//noinspection GoUnusedFunction
|
|
|
|
func zlibEncode(str []byte) []byte {
|
|
|
|
var buff bytes.Buffer
|
|
|
|
writer := zlib.NewWriter(&buff)
|
|
|
|
writer.Write(str)
|
|
|
|
writer.Close()
|
|
|
|
|
|
|
|
return buff.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
func zlibDecode(bts []byte) ([]byte, error) {
|
|
|
|
buff := bytes.NewReader(bts)
|
|
|
|
reader, readError := zlib.NewReader(buff)
|
|
|
|
if readError != nil {
|
|
|
|
return nil, readError
|
|
|
|
}
|
|
|
|
|
|
|
|
resultBuffer := new(bytes.Buffer)
|
|
|
|
io.Copy(resultBuffer, reader)
|
|
|
|
reader.Close()
|
|
|
|
|
|
|
|
return resultBuffer.Bytes(), nil
|
|
|
|
}
|