-
Notifications
You must be signed in to change notification settings - Fork 0
/
store.go
145 lines (128 loc) · 3.09 KB
/
store.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package main
import (
"encoding/json"
"fmt"
"strings"
"github.com/tidwall/buntdb"
)
func getString(db *buntdb.DB, key string) (string, error) {
var result string
err := db.View(func(tx *buntdb.Tx) error {
val, err := tx.Get(key)
if err != nil {
return err
}
result = val
return nil
})
return result, err
}
func getObject(db *buntdb.DB, key string, out interface{}) error {
return db.View(func(tx *buntdb.Tx) error {
val, err := tx.Get(key)
if err != nil {
return err
}
return json.Unmarshal([]byte(val), out)
})
}
func findUserByLogin(db *buntdb.DB, login string) (*User, error) {
key := makeLoginKey(login)
user := &User{}
err := db.View(func(tx *buntdb.Tx) error {
id, err := tx.Get(key)
if err == nil {
val, err := tx.Get(makeResourceKey("user", id))
if err != nil {
return err
}
return json.Unmarshal([]byte(val), user)
}
// TODO try to do the full scan
// scan(tx, "user", func(key, val string) bool {
// err := json.Unmarshal([]byte(val), user)
// if err != nil {
// return true
// }
// if strings.ToLower(user.Login) == strings.ToLower(login) {
// return false
// }
// return true
// })
// if strings.ToLower(user.Login) == strings.ToLower(login) {
// return nil
// }
return err
})
if err != nil {
fmt.Printf("find user failed: %v", err)
return nil, err
}
return user, nil
}
func findUserByID(db *buntdb.DB, id string) (*User, error) {
user := &User{}
err := db.View(func(tx *buntdb.Tx) error {
val, err := tx.Get(fmt.Sprintf("user/%s", id))
if err != nil {
return err
}
return json.Unmarshal([]byte(val), user)
})
if err != nil {
fmt.Printf("find user failed: %v", err)
return nil, err
}
return user, nil
}
func scan(tx *buntdb.Tx, resource string, handler func(key, val string) bool) error {
// TODO ascend by prefix
err := tx.Ascend("", func(key, val string) bool {
if !strings.HasPrefix(key, resource+"/") {
return true
}
return handler(key, val)
})
return err
}
func makeResourceKey(resource, id string) string {
return fmt.Sprintf("%s/%s", resource, id)
}
func insert(db *buntdb.DB, entity IEntity) error {
bytes, err := json.Marshal(entity)
if err != nil {
return err
}
rtype := entity.GetResourceInfo().Type
key := makeResourceKey(rtype, entity.GetID())
return db.Update(func(tx *buntdb.Tx) error {
_, _, err := tx.Set(key, string(bytes), nil)
user, ok := entity.(*User)
if ok {
onUserInserted(tx, user)
}
spec, ok := entity.(*Spectacle)
if ok {
onSpectacleInserted(tx, spec)
}
return err
})
}
func onUserInserted(tx *buntdb.Tx, user *User) error {
// map login to userID
key := makeLoginKey(user.Login)
_, _, err := tx.Set(key, user.ID, nil)
fmt.Printf("map user %s = %s\n", user.Login, user.ID)
return err
}
func onSpectacleInserted(tx *buntdb.Tx, spec *Spectacle) error {
key := makeSpectacleKey(spec.Title)
_, _, err := tx.Set(key, spec.ID, nil)
return err
}
func makeLoginKey(login string) string {
return fmt.Sprintf("user:%s", strings.ToLower(login))
}
func makeSpectacleKey(title string) string {
return fmt.Sprintf("spectacle:%s", title)
}