@@ -19,8 +19,8 @@ type RedisDb struct {
19
19
// All keys in this db.
20
20
keys Keys
21
21
22
- // Keys with a timeout set .
23
- expiringKeys Keys
22
+ // Keys with expire timestamp .
23
+ expiringKeys ExpiringKeys
24
24
25
25
// TODO long long avg_ttl; /* Average TTL, just for stats */
26
26
@@ -36,6 +36,9 @@ type DatabaseId uint
36
36
// Key-Item map
37
37
type Keys map [string ]Item
38
38
39
+ // Keys with expire timestamp.
40
+ type ExpiringKeys map [string ]time.Time
41
+
39
42
// The item interface. An item is the value of a key.
40
43
type Item interface {
41
44
// The pointer to the value.
@@ -45,14 +48,9 @@ type Item interface {
45
48
// This need to be constant for the type because it is
46
49
// used when de-/serializing item from/to disk.
47
50
ValueType () uint64
48
- // The type of the Item as string.
51
+ // The type of the Item as readable string.
49
52
ValueTypeFancy () string
50
53
51
- // GetCommand timestamp when the item expires.
52
- Expiry () time.Time
53
- // Expiry is set.
54
- Expires () bool
55
-
56
54
// OnDelete is triggered before the key of the item is deleted.
57
55
// db is the affected database.
58
56
OnDelete (key * string , db * RedisDb )
@@ -64,7 +62,7 @@ func NewRedisDb(id DatabaseId, r *Redis) *RedisDb {
64
62
id : id ,
65
63
redis : r ,
66
64
keys : make (Keys , keysMapSize ),
67
- expiringKeys : make (Keys , keysMapSize ),
65
+ expiringKeys : make (ExpiringKeys , keysMapSize ),
68
66
}
69
67
}
70
68
@@ -98,6 +96,7 @@ func (r *Redis) RedisDb(dbId DatabaseId) *RedisDb {
98
96
return r .redisDbs [dbId ]
99
97
}
100
98
99
+ // RedisDbs gets all redis databases.
101
100
func (r * Redis ) RedisDbs () RedisDbs {
102
101
r .Mu ().RLock ()
103
102
defer r .Mu ().RUnlock ()
@@ -119,41 +118,13 @@ func (db *RedisDb) Id() DatabaseId {
119
118
return db .id
120
119
}
121
120
122
- // IsEmpty checks db is empty.
123
- func (db * RedisDb ) IsEmpty () bool {
124
- db .Mu ().RLock ()
125
- defer db .Mu ().RUnlock ()
126
- return len (db .keys ) == 0
127
- }
128
-
129
- // IsEmptyExpire checks db has any expiring keys.
130
- func (db * RedisDb ) IsEmptyExpire () bool {
131
- db .Mu ().RLock ()
132
- defer db .Mu ().RUnlock ()
133
- return len (db .expiringKeys ) == 0
134
- }
135
-
136
- // Keys gets all keys in this db.
137
- func (db * RedisDb ) Keys () Keys {
138
- db .Mu ().RLock ()
139
- defer db .Mu ().RUnlock ()
140
- return db .keys
141
- }
142
-
143
- // ExpiringKeys gets keys with an expiry set.
144
- func (db * RedisDb ) ExpiringKeys () Keys {
145
- db .Mu ().RLock ()
146
- defer db .Mu ().RUnlock ()
147
- return db .expiringKeys
148
- }
149
-
150
- // Sets a key with an item.
151
- func (db * RedisDb ) Set (key * string , i Item ) {
121
+ // Sets a key with an item which can have an expiration time.
122
+ func (db * RedisDb ) Set (key * string , i Item , expires bool , expiry time.Time ) {
152
123
db .Mu ().Lock ()
153
124
defer db .Mu ().Unlock ()
154
125
db .keys [* key ] = i
155
- if i . Expires () {
156
- db .expiringKeys [* key ] = i
126
+ if expires {
127
+ db .expiringKeys [* key ] = expiry
157
128
}
158
129
}
159
130
@@ -169,30 +140,79 @@ func (db *RedisDb) get(key *string) Item {
169
140
return i
170
141
}
171
142
172
- // Deletes a key, returns true if key existed.
173
- func (db * RedisDb ) Delete (keys ... * string ) int64 {
174
- // TODO if it makes a difference, check keys exists with RLock and then if exists RWLock
143
+ // Deletes a key, returns number of deleted keys.
144
+ func (db * RedisDb ) Delete (keys ... * string ) int {
175
145
db .Mu ().Lock ()
176
146
defer db .Mu ().Unlock ()
177
- var c int64
147
+ return db .delete (keys ... )
148
+ }
149
+
150
+ // If checkExists is false, then return bool is reprehensible.
151
+ func (db * RedisDb ) delete (keys ... * string ) int {
152
+ do := func (k * string ) bool {
153
+ if k == nil {
154
+ return false
155
+ }
156
+ i := db .get (k )
157
+ if i == nil {
158
+ return false
159
+ }
160
+ i .OnDelete (k , db )
161
+ delete (db .keys , * k )
162
+ delete (db .expiringKeys , * k )
163
+ return true
164
+ }
165
+
166
+ var c int
178
167
for _ , k := range keys {
179
- if k != nil && db . delete (k ) {
168
+ if do (k ) {
180
169
c ++
181
170
}
182
171
}
172
+
183
173
return c
184
174
}
185
175
186
- // If checkExists is false, then return bool is reprehensible.
187
- func (db * RedisDb ) delete (key * string ) bool {
188
- i := db .get (key )
189
- if i == nil {
190
- return false
176
+ func (db * RedisDb ) DeleteExpired (keys ... * string ) int {
177
+ var c int
178
+ for _ , k := range keys {
179
+ if k != nil && db .Expired (k ) && db .Delete (k ) > 0 {
180
+ c ++
181
+ }
182
+ }
183
+ return c
184
+ }
185
+
186
+ // GetOrExpire gets the item or nil if expired or not exists. If 'deleteIfExpired' is true the key will be deleted.
187
+ func (db * RedisDb ) GetOrExpire (key * string , deleteIfExpired bool ) Item {
188
+ // TODO mutex optimize this func so that a RLock is mainly first opened
189
+ db .Mu ().Lock ()
190
+ defer db .Mu ().Unlock ()
191
+ i , ok := db .keys [* key ]
192
+ if ! ok {
193
+ return nil
194
+ }
195
+ if db .expired (key ) {
196
+ if deleteIfExpired {
197
+ db .delete (key )
198
+ }
199
+ return nil
191
200
}
192
- i .OnDelete (key , db )
193
- delete (db .keys , * key )
194
- delete (db .expiringKeys , * key )
195
- return true
201
+ return i
202
+ }
203
+
204
+ // IsEmpty checks if db is empty.
205
+ func (db * RedisDb ) IsEmpty () bool {
206
+ db .Mu ().RLock ()
207
+ defer db .Mu ().RUnlock ()
208
+ return len (db .keys ) == 0
209
+ }
210
+
211
+ // HasExpiringKeys checks if db has any expiring keys.
212
+ func (db * RedisDb ) HasExpiringKeys () bool {
213
+ db .Mu ().RLock ()
214
+ defer db .Mu ().RUnlock ()
215
+ return len (db .expiringKeys ) != 0
196
216
}
197
217
198
218
// Check if key exists.
@@ -206,39 +226,53 @@ func (db *RedisDb) exists(key *string) bool {
206
226
return ok
207
227
}
208
228
209
- // Check if key can expire .
229
+ // Check if key has an expiry set .
210
230
func (db * RedisDb ) Expires (key * string ) bool {
211
231
db .Mu ().RLock ()
212
232
defer db .Mu ().RUnlock ()
233
+ return db .expires (key )
234
+ }
235
+ func (db * RedisDb ) expires (key * string ) bool {
213
236
_ , ok := db .expiringKeys [* key ]
214
237
return ok
215
238
}
216
239
217
- // GetOrExpire gets the item or nil if expired or not exists.
218
- func (db * RedisDb ) GetOrExpired (key * string , deleteIfExpired bool ) Item {
219
- // TODO mutex optimize this func so that a RLock is mainly first opened
240
+ // Expired only check if a key can and is expired.
241
+ func (db * RedisDb ) Expired (key * string ) bool {
242
+ db .Mu ().RLock ()
243
+ defer db .Mu ().RUnlock ()
244
+ return db .expired (key )
245
+ }
246
+ func (db * RedisDb ) expired (key * string ) bool {
247
+ return db .expires (key ) && TimeExpired (db .expiry (key ))
248
+ }
220
249
221
- db .Mu ().Lock ()
222
- defer db .Mu ().Unlock ()
223
- i , ok := db .keys [* key ]
224
- if ! ok {
225
- return nil
226
- }
227
- if ItemExpired (i ) {
228
- if deleteIfExpired {
229
- db .delete (key )
230
- }
231
- return nil
232
- }
233
- return i
250
+ // Expiry gets the expiry of the key has one.
251
+ func (db * RedisDb ) Expiry (key * string ) time.Time {
252
+ db .Mu ().RLock ()
253
+ defer db .Mu ().RUnlock ()
254
+ return db .expiry (key )
234
255
}
235
256
236
- // Expired check if a timestamp is expired.
237
- func Expired (expireAt time.Time ) bool {
238
- return time .Now ().After (expireAt )
257
+ func (db * RedisDb ) expiry (key * string ) time.Time {
258
+ return db .expiringKeys [* key ]
259
+ }
260
+
261
+ // Keys gets all keys in this db.
262
+ func (db * RedisDb ) Keys () Keys {
263
+ db .Mu ().RLock ()
264
+ defer db .Mu ().RUnlock ()
265
+ return db .keys
239
266
}
240
267
241
- // ItemExpired check if an item can and is expired
242
- func ItemExpired (i Item ) bool {
243
- return i .Expires () && Expired (i .Expiry ())
268
+ // ExpiringKeys gets keys with an expiry set and their timeout.
269
+ func (db * RedisDb ) ExpiringKeys () ExpiringKeys {
270
+ db .Mu ().RLock ()
271
+ defer db .Mu ().RUnlock ()
272
+ return db .expiringKeys
273
+ }
274
+
275
+ // TimeExpired check if a timestamp is older than now.
276
+ func TimeExpired (expireAt time.Time ) bool {
277
+ return time .Now ().After (expireAt )
244
278
}
0 commit comments