first commit
This commit is contained in:
@@ -0,0 +1,403 @@
|
||||
package boltdb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/cdle/sillyplus/core/logs"
|
||||
"github.com/cdle/sillyplus/core/storage"
|
||||
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
)
|
||||
|
||||
type Bucket struct {
|
||||
name string
|
||||
}
|
||||
|
||||
var db *bolt.DB
|
||||
|
||||
func (b Bucket) String() string {
|
||||
return b.name
|
||||
}
|
||||
|
||||
var expirationA = Bucket{
|
||||
name: "timeouts",
|
||||
}
|
||||
|
||||
type Expire struct {
|
||||
Value string `json:"value"`
|
||||
Time time.Time `json:"deadline"`
|
||||
}
|
||||
|
||||
func Set(key string, value string, expiration time.Duration) error {
|
||||
_, err := expirationA.Set(key, utils.JsonMarshal(&Expire{
|
||||
Value: value,
|
||||
Time: time.Now().Add(expiration),
|
||||
}))
|
||||
return err
|
||||
}
|
||||
|
||||
func Get(key string) string {
|
||||
e := Expire{}
|
||||
data := expirationA.GetBytes(key)
|
||||
json.Unmarshal(data, &e)
|
||||
if e.Time.Before(time.Now()) {
|
||||
return ""
|
||||
}
|
||||
return e.Value
|
||||
}
|
||||
|
||||
var Buckets = []Bucket{}
|
||||
|
||||
func Initsillyplus() storage.Bucket {
|
||||
var err error
|
||||
if runtime.GOOS == "darwin" {
|
||||
db, err = bolt.Open("./sillyGirl.db", 0600, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
bd := utils.GetDataHome() + "sillyGirl.db"
|
||||
_, err := os.Stat(bd)
|
||||
if err != nil {
|
||||
f, err := os.Create(bd)
|
||||
if err != nil {
|
||||
logs.Info("傻妞无法创建数据文件 %s ,请手动创建。", bd)
|
||||
os.Exit(0)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
db, err = bolt.Open(bd, 0600, nil)
|
||||
if err != nil {
|
||||
logs.Info("傻妞无法创建数据文件 %s ,请手动创建。", bd)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
v := &Bucket{
|
||||
name: "sillyplus",
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetName() string {
|
||||
return bucket.name
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Copy(name string) storage.Bucket {
|
||||
return &Bucket{name: name}
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Type() string {
|
||||
return "boltdb"
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Buckets() []string {
|
||||
var r []string
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
tx.ForEach(func(name []byte, _ *bolt.Bucket) error {
|
||||
r = append(r, string(name))
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Delete() error {
|
||||
err := db.Update(func(tx *bolt.Tx) error {
|
||||
k := fmt.Sprint(bucket.name)
|
||||
e := tx.DeleteBucket([]byte(k))
|
||||
if e == bolt.ErrBucketNotFound {
|
||||
return nil
|
||||
}
|
||||
return e
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) {
|
||||
new := ""
|
||||
msg := ""
|
||||
k := fmt.Sprint(key)
|
||||
switch value := value.(type) {
|
||||
case []byte:
|
||||
new = string(value)
|
||||
case string:
|
||||
new = value
|
||||
case nil:
|
||||
default:
|
||||
new = fmt.Sprint(value)
|
||||
}
|
||||
var handles []func(string, string, string) *storage.Final
|
||||
for _, listen := range storage.Listens {
|
||||
if listen.Name == bucket.name && (listen.Key == key || listen.Key == "*") {
|
||||
handles = append(handles, listen.Handle)
|
||||
}
|
||||
}
|
||||
if len(handles) > 0 {
|
||||
old := bucket.GetString(key)
|
||||
for _, handle := range handles {
|
||||
fin := handle(old, new, k)
|
||||
if fin != nil {
|
||||
if fin.Message != "" {
|
||||
msg = fin.Message
|
||||
}
|
||||
if fin.Error != nil {
|
||||
return msg, fin.Error
|
||||
}
|
||||
if fin.Now != "" {
|
||||
new = fin.Now
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return msg, db.Update(func(tx *bolt.Tx) error {
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(bucket.name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if new == "" {
|
||||
if err := b.Delete([]byte(k)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := b.Put([]byte(k), []byte(new)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetString(kv ...interface{}) string {
|
||||
// logs.Info(kv)
|
||||
var key, value string
|
||||
for i := range kv {
|
||||
if i == 0 {
|
||||
key = fmt.Sprint(kv[0])
|
||||
} else {
|
||||
value = fmt.Sprint(kv[1])
|
||||
}
|
||||
}
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
if v := string(b.Get([]byte(key))); v != "" {
|
||||
value = v
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return value
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetBytes(key string) []byte {
|
||||
var value []byte
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
if v := b.Get([]byte(key)); v != nil {
|
||||
value = v
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return value
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetInt(key string, vs ...int) int {
|
||||
var value int
|
||||
if len(vs) != 0 {
|
||||
value = vs[0]
|
||||
}
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
v := utils.Int(string(b.Get([]byte(fmt.Sprint(key)))))
|
||||
if v != 0 {
|
||||
value = v
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return value
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetBool(key string, vs ...bool) bool {
|
||||
var value bool
|
||||
if len(vs) != 0 {
|
||||
value = vs[0]
|
||||
}
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
v := string(b.Get([]byte(fmt.Sprint(key))))
|
||||
if v == "true" {
|
||||
value = true
|
||||
} else if v == "false" {
|
||||
value = false
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return value
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Foreach(f func(k, v []byte) error) {
|
||||
var bs = [][][]byte{}
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b != nil {
|
||||
err := b.ForEach(func(k, v []byte) error {
|
||||
bs = append(bs, [][]byte{k, v})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
for i := range bs {
|
||||
f(bs[i][0], bs[i][1])
|
||||
}
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Keys() ([]string, error) {
|
||||
var bs = []string{}
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b != nil {
|
||||
err := b.ForEach(func(k, _ []byte) error {
|
||||
if string(k) == "plugins" {
|
||||
return nil
|
||||
}
|
||||
bs = append(bs, string(k))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return bs, err
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Create(i interface{}) error {
|
||||
// logs.Info("-", i)
|
||||
s := reflect.ValueOf(i).Elem()
|
||||
id := s.FieldByName("ID")
|
||||
sequence := s.FieldByName("Sequence")
|
||||
return db.Update(func(tx *bolt.Tx) error {
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(bucket.name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := id.Interface().(int); ok {
|
||||
key := id.Int()
|
||||
sq, err := b.NextSequence()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if key == 0 {
|
||||
key = int64(sq)
|
||||
id.SetInt(key)
|
||||
}
|
||||
if sequence != reflect.ValueOf(nil) {
|
||||
sequence.SetInt(int64(sq))
|
||||
}
|
||||
buf, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.Put(utils.Itob(uint64(key)), buf)
|
||||
} else {
|
||||
key := id.String()
|
||||
sq, err := b.NextSequence()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if key == "" {
|
||||
key = fmt.Sprint(sq)
|
||||
id.SetString(key)
|
||||
}
|
||||
if sequence != reflect.ValueOf(nil) {
|
||||
sequence.SetInt(int64(sq))
|
||||
}
|
||||
buf, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.Put([]byte(key), buf)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (bucket *Bucket) First(i interface{}) error {
|
||||
var err error
|
||||
s := reflect.ValueOf(i).Elem()
|
||||
id := s.FieldByName("ID")
|
||||
if v, ok := id.Interface().(int); ok {
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b == nil {
|
||||
err = errors.New("bucket not find")
|
||||
return nil
|
||||
}
|
||||
data := b.Get([]byte(fmt.Sprint(v)))
|
||||
if len(data) == 0 {
|
||||
err = errors.New("record not find")
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(data, i)
|
||||
})
|
||||
} else {
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b == nil {
|
||||
err = errors.New("bucket not find")
|
||||
return nil
|
||||
}
|
||||
data := b.Get([]byte(id.Interface().(string)))
|
||||
if len(data) == 0 {
|
||||
err = errors.New("record not find")
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(data, i)
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Size() (int64, error) {
|
||||
var r int64
|
||||
bucket.Foreach(func(k, v []byte) error {
|
||||
r++
|
||||
return nil
|
||||
})
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (bucket *Bucket) IsEmpty() (bool, error) {
|
||||
r := true
|
||||
db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket.name))
|
||||
if b != nil {
|
||||
o, _ := b.Cursor().First()
|
||||
r = o == nil
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return r, nil
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package storage
|
||||
|
||||
type Listen struct {
|
||||
UUID string
|
||||
Name string
|
||||
Key string
|
||||
Handle func(old string, new string, key string) *Final
|
||||
}
|
||||
|
||||
var Listens []Listen
|
||||
|
||||
var DisableHandle = func(uuid string) {
|
||||
for i := range Listens {
|
||||
if Listens[i].UUID == uuid {
|
||||
Listens[i].Handle = func(old, new, key string) *Final {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Bucket interface {
|
||||
Set(interface{}, interface{}) (string, error)
|
||||
Copy(string) Bucket
|
||||
IsEmpty() (bool, error)
|
||||
Size() (int64, error)
|
||||
Delete() error
|
||||
Type() string
|
||||
Buckets() []string
|
||||
GetString(...interface{}) string
|
||||
GetBytes(string) []byte
|
||||
GetInt(string, ...int) int
|
||||
GetBool(string, ...bool) bool
|
||||
Foreach(func([]byte, []byte) error)
|
||||
Create(interface{}) error
|
||||
First(interface{}) error
|
||||
String() string
|
||||
GetName() string
|
||||
Keys() ([]string, error)
|
||||
}
|
||||
|
||||
type Final struct {
|
||||
Now string
|
||||
Message string
|
||||
Error error
|
||||
}
|
||||
|
||||
func Watch(bucket Bucket, key interface{}, handle func(old string, new string, key string) *Final, uuid ...string) {
|
||||
k := "*"
|
||||
if key != nil {
|
||||
k = key.(string)
|
||||
}
|
||||
listen := Listen{
|
||||
Name: bucket.GetName(),
|
||||
Key: k,
|
||||
Handle: handle,
|
||||
}
|
||||
if len(uuid) != 0 {
|
||||
listen.UUID = uuid[0]
|
||||
}
|
||||
Listens = append(Listens, listen)
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/v2/client/httplib"
|
||||
"github.com/buger/jsonparser"
|
||||
"github.com/cdle/sillyplus/core/storage"
|
||||
"github.com/cdle/sillyplus/utils"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
var master = ""
|
||||
|
||||
var sillyplus *Bucket
|
||||
|
||||
type Bucket struct {
|
||||
name string
|
||||
}
|
||||
|
||||
var toMaster = func(bucket, key, value string) (string, error) {
|
||||
req := httplib.Put(master + "/api/storage")
|
||||
web_token := sillyplus.GetString("web_token")
|
||||
if web_token == "" {
|
||||
return "", errors.New("请先在本体可视化登录!")
|
||||
}
|
||||
token := strings.Split(web_token, "&")[0]
|
||||
req.SetCookie(&http.Cookie{
|
||||
Name: "token",
|
||||
Value: token,
|
||||
})
|
||||
key = fmt.Sprintf("%s.%s", bucket, key)
|
||||
req.JSONBody(map[string]interface{}{
|
||||
key: value,
|
||||
})
|
||||
data, err := req.Bytes()
|
||||
if err != nil {
|
||||
return "", errors.New("啊,与本体失联了~")
|
||||
}
|
||||
var message string
|
||||
message, _ = jsonparser.GetString(data, "messages", key)
|
||||
errStr, _ := jsonparser.GetString(data, "errors", key)
|
||||
if errStr != "" {
|
||||
err = errors.New(errStr)
|
||||
}
|
||||
return message, err
|
||||
}
|
||||
|
||||
var db *redis.Client
|
||||
|
||||
func (b *Bucket) String() string {
|
||||
return b.name
|
||||
}
|
||||
|
||||
var Buckets = []Bucket{}
|
||||
|
||||
func (bucket *Bucket) Type() string {
|
||||
return "redis"
|
||||
}
|
||||
|
||||
func Initsillyplus(RedisAddr, RedisPassword string) storage.Bucket {
|
||||
db = redis.NewClient(&redis.Options{
|
||||
Addr: RedisAddr,
|
||||
Password: RedisPassword, // no password set
|
||||
DB: 0, // use default DB
|
||||
})
|
||||
if db == nil {
|
||||
panic("redis is not ok")
|
||||
}
|
||||
sillyplus = &Bucket{
|
||||
name: "sillyplus",
|
||||
}
|
||||
port := sillyplus.GetString("port", "8080")
|
||||
if utils.SlaveMode {
|
||||
is, _ := db.ConfigGet(ctx, "slaveof").Result()
|
||||
db.ConfigSet(ctx, "notify-keyspace-events", "KEh")
|
||||
if len(is) > 1 {
|
||||
ip := strings.Split(fmt.Sprint(is[1]), " ")[0]
|
||||
master = fmt.Sprintf("http://%s:%s", ip, port)
|
||||
}
|
||||
go func() {
|
||||
again:
|
||||
subscriber := db.Subscribe(ctx, "__keyevent@0__:hset")
|
||||
for {
|
||||
msg, err := subscriber.ReceiveMessage(ctx)
|
||||
if err != nil {
|
||||
time.Sleep(time.Second)
|
||||
goto again
|
||||
}
|
||||
bk := msg.Payload
|
||||
|
||||
// logs.Info(bk, msg.Pattern, msg.Channel, msg.Payload)
|
||||
if bk := strings.Split(bk, "."); len(bk) == 2 {
|
||||
bucket, key := bk[0], bk[1]
|
||||
for _, listen := range storage.Listens {
|
||||
if listen.Name == bucket && (listen.Key == key || listen.Key == "*") {
|
||||
str, err := db.HGet(ctx, bucket, key).Result()
|
||||
if err == nil {
|
||||
listen.Handle("", str, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return sillyplus
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Copy(name string) storage.Bucket {
|
||||
return &Bucket{name: name}
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Buckets() []string {
|
||||
var r []string
|
||||
r, _ = db.Keys(ctx, "*").Result()
|
||||
var e []string
|
||||
for _, v := range r {
|
||||
if strings.HasSuffix(v, "_Sequence") {
|
||||
continue
|
||||
}
|
||||
if regexp.MustCompile(`^\d+@\d+$`).FindString(v) != "" {
|
||||
continue
|
||||
}
|
||||
e = append(e, v)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Delete() error {
|
||||
db.Del(ctx, bucket.name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetName() string {
|
||||
return bucket.name
|
||||
}
|
||||
|
||||
func Set(key string, value string, expiration time.Duration) error {
|
||||
db.Set(ctx, key, value, expiration)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Get(key string) string {
|
||||
v, _ := db.Get(ctx, key).Result()
|
||||
return v
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Set(key interface{}, value interface{}) (string, error) {
|
||||
new := ""
|
||||
msg := ""
|
||||
k := fmt.Sprint(key)
|
||||
switch value := value.(type) {
|
||||
case []byte:
|
||||
new = string(value)
|
||||
case string:
|
||||
new = value
|
||||
case nil:
|
||||
default:
|
||||
new = fmt.Sprint(value)
|
||||
}
|
||||
if !utils.SlaveMode {
|
||||
var handles []func(string, string, string) *storage.Final
|
||||
for _, listen := range storage.Listens {
|
||||
if listen.Name == bucket.name && (listen.Key == key || listen.Key == "*") {
|
||||
handles = append(handles, listen.Handle)
|
||||
}
|
||||
}
|
||||
if len(handles) > 0 {
|
||||
old := bucket.GetString(key)
|
||||
if old == new {
|
||||
return msg, nil
|
||||
}
|
||||
for _, handle := range handles {
|
||||
fin := handle(old, new, k)
|
||||
if fin != nil {
|
||||
if fin.Message != "" {
|
||||
msg = fin.Message
|
||||
}
|
||||
if fin.Error != nil {
|
||||
return msg, fin.Error
|
||||
}
|
||||
if fin.Now != "" {
|
||||
new = fin.Now
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if new == "" {
|
||||
return msg, db.HDel(ctx, bucket.name, k).Err()
|
||||
} else {
|
||||
return msg, db.HSet(ctx, bucket.name, k, new).Err()
|
||||
}
|
||||
} else {
|
||||
return toMaster(bucket.name, k, new)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetString(kv ...interface{}) string {
|
||||
var key, value string
|
||||
for i := range kv {
|
||||
if i == 0 {
|
||||
key = fmt.Sprint(kv[0])
|
||||
} else {
|
||||
value = fmt.Sprint(kv[1])
|
||||
}
|
||||
}
|
||||
cs := db.HGet(ctx, bucket.name, key)
|
||||
if cs != nil {
|
||||
v, _ := cs.Result()
|
||||
if v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (bucket *Bucket) GetBytes(key string) (v []byte) {
|
||||
cs := db.HGet(ctx, bucket.name, key)
|
||||
if cs != nil {
|
||||
v, _ = cs.Bytes()
|
||||
if len(v) != 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (bucket Bucket) GetInt(key string, vs ...int) int {
|
||||
var value int
|
||||
if len(vs) != 0 {
|
||||
value = vs[0]
|
||||
}
|
||||
cs := db.HGet(ctx, bucket.name, key)
|
||||
if cs != nil {
|
||||
v, _ := cs.Result()
|
||||
if v != "" {
|
||||
return utils.Int(v)
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (bucket Bucket) GetBool(key string, vs ...bool) bool {
|
||||
var value bool
|
||||
if len(vs) != 0 {
|
||||
value = vs[0]
|
||||
}
|
||||
cs := db.HGet(ctx, bucket.name, key)
|
||||
if cs != nil {
|
||||
v, _ := cs.Result()
|
||||
if v == "true" {
|
||||
value = true
|
||||
} else if v == "false" {
|
||||
value = false
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (bucket Bucket) Foreach(f func(k, v []byte) error) {
|
||||
vs, _ := db.HGetAll(ctx, bucket.name).Result()
|
||||
for key, value := range vs {
|
||||
f([]byte(key), []byte(value))
|
||||
}
|
||||
}
|
||||
func (bucket Bucket) Create(i interface{}) error {
|
||||
sq, err := db.Incr(ctx, bucket.name+"_Sequence").Uint64()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
s := reflect.ValueOf(i).Elem()
|
||||
id := s.FieldByName("ID")
|
||||
sequence := s.FieldByName("Sequence")
|
||||
if _, ok := id.Interface().(int); ok {
|
||||
key := id.Int()
|
||||
if key == 0 {
|
||||
key = int64(sq)
|
||||
id.SetInt(key)
|
||||
}
|
||||
if sequence != reflect.ValueOf(nil) {
|
||||
sequence.SetInt(int64(sq))
|
||||
}
|
||||
buf, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.HSet(ctx, bucket.name, key, buf).Err()
|
||||
} else {
|
||||
key := id.String()
|
||||
if key == "" {
|
||||
key = fmt.Sprint(sq)
|
||||
id.SetString(key)
|
||||
}
|
||||
if sequence != reflect.ValueOf(nil) {
|
||||
sequence.SetInt(int64(sq))
|
||||
}
|
||||
buf, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.HSet(ctx, bucket.name, key, buf).Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (bucket Bucket) First(i interface{}) error {
|
||||
var err error
|
||||
s := reflect.ValueOf(i).Elem()
|
||||
id := s.FieldByName("ID")
|
||||
if v, ok := id.Interface().(int); ok {
|
||||
data, _ := db.HGet(ctx, bucket.name, fmt.Sprint(v)).Bytes()
|
||||
if len(data) == 0 {
|
||||
err = errors.New("record not find")
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, i)
|
||||
} else {
|
||||
data, _ := db.HGet(ctx, bucket.name, id.Interface().(string)).Bytes()
|
||||
if len(data) == 0 {
|
||||
err = errors.New("record not find")
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, i)
|
||||
}
|
||||
}
|
||||
|
||||
func (bucket Bucket) Size() (size int64, err error) {
|
||||
var ks []string
|
||||
ks, err = db.HKeys(ctx, bucket.name).Result()
|
||||
return int64(len(ks)), err
|
||||
}
|
||||
|
||||
func (bucket Bucket) IsEmpty() (empty bool, err error) {
|
||||
var ks []string
|
||||
ks, err = db.HKeys(ctx, bucket.name).Result()
|
||||
return len(ks) == 0, err
|
||||
}
|
||||
|
||||
func (bucket *Bucket) Keys() ([]string, error) {
|
||||
return db.HKeys(ctx, bucket.name).Result()
|
||||
}
|
||||
Reference in New Issue
Block a user