Skip to content

Commit 662436c

Browse files
committed
expiration filter
1 parent 087190b commit 662436c

File tree

6 files changed

+290
-5
lines changed

6 files changed

+290
-5
lines changed

README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ Options:
5959
-sep separator for flamegraph, rdb will separate key by it, default value is ":".
6060
supporting multi separators: -sep sep1 -sep sep2
6161
-regex using regex expression filter keys
62+
-expire filter keys by its expiration time
63+
1. '>1751731200' '>now' get keys with expiration time greater than given time
64+
2. '<1751731200' '<now' get keys with expiration time less than given time
65+
3. '1751731200~1751817600' '1751731200~now' get keys with expiration time in range
66+
4. 'noexpire' get keys without expiration time
67+
5. 'anyexpire' get all keys with expiration time
6268
-no-expired reserve expired keys
6369
-concurrent The number of concurrent json converters. (CpuNum -1 by default, reserve a core for decoder)
6470
@@ -411,6 +417,49 @@ Example:
411417
rdb -c json -o regex.json -regex '^l.*' cases/memory.rdb
412418
```
413419

420+
# Expiration Filter
421+
422+
The `-expire` parameter can be configured to filter based on the expiration time.
423+
424+
Keys with expiration times between 2025-07-06 00:00:00 and 2025-07-07 00:00:00:
425+
```bash
426+
# toTimestamp(2025-07-06 00:00:00) == 1751731200
427+
# toTimestamp(2025-07-07 00:00:00) == 1751817600
428+
rdb -c json -o dump.json -expire 1751731200~1751817600 cases/expiration.rdb
429+
```
430+
431+
```bash
432+
# Keys with expiration times earlier than 2025-07-07 00:00:00
433+
rdb -c json -o dump.json -expire 0~1751817600 cases/expiration.rdb
434+
```
435+
436+
The magic variable `inf` represents infinity:
437+
```bash
438+
rdb -c json -o dump.json -expire 1751731200~inf cases/expiration.rdb
439+
```
440+
441+
The magic variable `now` represents the current time:
442+
443+
```bash
444+
# Keys with expiration times earlier than now
445+
rdb -c json -o dump.json -expire 0~now cases/expiration.rdb
446+
```
447+
448+
```bash
449+
# Keys with expiration times later than now
450+
rdb -c json -o dump.json -expire now~inf cases/expiration.rdb
451+
```
452+
453+
All keys with expiration times set:
454+
```bash
455+
rdb -c json -o dump.json -expire anyexpire cases/expiration.rdb
456+
```
457+
458+
All keys without expiration times set:
459+
```bash
460+
rdb -c json -o dump.json -expire noexpire cases/expiration.rdb
461+
```
462+
414463
# Customize data usage
415464

416465
```go

README_CN.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ Options:
4646
-sep separator for flamegraph, rdb will separate key by it, default value is ":".
4747
supporting multi separators: -sep sep1 -sep sep2
4848
-regex using regex expression filter keys
49+
-expire filter keys by its expiration time
50+
1. '>1751731200' '>now' get keys with expiration time greater than given time
51+
2. '<1751731200' '<now' get keys with expiration time less than given time
52+
3. '1751731200~1751817600' '1751731200~now' get keys with expiration time in range
53+
4. 'noexpire' get keys without expiration time
54+
5. 'anyexpire' get all keys with expiration time
4955
-no-expired filter expired keys
5056
-concurrent The number of concurrent json converters. (Cpu number by default)
5157
@@ -390,14 +396,57 @@ aaaaaaa
390396

391397
# 正则过滤器
392398

393-
本工具支持使用正则表达式过滤自己关心的键值对
399+
支持使用正则表达式过滤自己关心的键值对
394400

395401
示例:
396402

397403
```bash
398404
rdb -c json -o regex.json -regex '^l.*' cases/memory.rdb
399405
```
400406

407+
# Expiration 过滤器
408+
409+
`-expire` 参数可以配置根据过期时间过滤.
410+
411+
过期时间在 2025-07-06 00:00:00 与 2025-07-07 00:00:00之间的 key:
412+
```bash
413+
# toTimestamp(2025-07-06 00:00:00) == 1751731200
414+
# toTimestamp(2025-07-07 00:00:00) == 1751817600
415+
rdb -c json -o dump.json -expire 1751731200~1751817600 cases/expiration.rdb
416+
```
417+
418+
```bash
419+
# 过期时间早于 2025-07-07 00:00:00 的 key
420+
rdb -c json -o dump.json -expire 0~1751817600 cases/expiration.rdb
421+
```
422+
423+
魔法变量 `inf` 表示无穷大:
424+
```bash
425+
rdb -c json -o dump.json -expire 1751731200~inf cases/expiration.rdb
426+
```
427+
428+
魔法变量 `now` 表示当前时间:
429+
430+
```bash
431+
# 过期时间早于现在的 key
432+
rdb -c json -o dump.json -expire 0~now cases/expiration.rdb
433+
```
434+
435+
```bash
436+
# 过期时间晚于现在的 key
437+
rdb -c json -o dump.json -expire now~inf cases/expiration.rdb
438+
```
439+
440+
所有设置了过期时间的key:
441+
```bash
442+
rdb -c json -o dump.json -expire anyexpire cases/expiration.rdb
443+
```
444+
445+
所有未设置过期时间的key:
446+
```bash
447+
rdb -c json -o dump.json -expire noexpire cases/expiration.rdb
448+
```
449+
401450
# 自定义用途
402451

403452
除了命令行工具之外,您可以在自己的项目中引入 hdt3213/rdb/parser 包,自行决定如何处理 RDB 中的数据。

cases/expiration.rdb

125 Bytes
Binary file not shown.

cmd.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ Options:
1919
-sep separator for flamegraph, rdb will separate key by it, default value is ":".
2020
supporting multi separators: -sep sep1 -sep sep2
2121
-regex using regex expression filter keys
22-
-no-expired filter expired keys
22+
-expire filter keys by its expiration time
23+
1. '1751731200~1751817600' get keys with expiration time in range [1751731200, 1751817600]
24+
2. '1751731200~now' 'now~1751731200' magic variable 'now' represents the current timestamp
25+
3. '1751731200~inf' 'now~inf' magic variable 'inf' represents the Infinity
26+
4. 'noexpire' get keys without expiration time
27+
5. 'anyexpire' get all keys with expiration time
28+
-no-expired filter expired keys(deprecated, please use 'expire' option)
2329
-concurrent The number of concurrent json converters. 4 by default.
2430
2531
Examples:
@@ -58,6 +64,7 @@ func main() {
5864
var seps separators
5965
var regexExpr string
6066
var noExpired bool
67+
var expirationExpr string
6168
var maxDepth int
6269
var concurrent int
6370
var err error
@@ -69,7 +76,8 @@ func main() {
6976
flagSet.IntVar(&concurrent, "concurrent", 0, "concurrent number for json converter")
7077
flagSet.Var(&seps, "sep", "separator for flame graph")
7178
flagSet.StringVar(&regexExpr, "regex", "", "regex expression")
72-
flagSet.BoolVar(&noExpired, "no-expired", false, "filter expired keys")
79+
flagSet.StringVar(&expirationExpr, "expire", "", "expiration filter expression")
80+
flagSet.BoolVar(&noExpired, "no-expired", false, "filter expired keys(deprecated, please use expire)")
7381
_ = flagSet.Parse(os.Args[1:]) // ExitOnError
7482
src := flagSet.Arg(0)
7583

@@ -92,6 +100,9 @@ func main() {
92100
if concurrent != 0 {
93101
options = append(options, helper.WithConcurrent(concurrent))
94102
}
103+
if expirationExpr != "" {
104+
options = append(options, helper.WithExpirationOption(expirationExpr))
105+
}
95106

96107
var outputFile *os.File
97108
if output == "" {

helper/converter_test.go

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package helper
22

33
import (
44
"bufio"
5-
"github.com/bytedance/sonic"
65
"os"
76
"path/filepath"
87
"testing"
98
"time"
9+
10+
"github.com/bytedance/sonic"
11+
"github.com/hdt3213/rdb/model"
12+
"github.com/hdt3213/rdb/parser"
1013
)
1114

1215
func compareFileByLine(t *testing.T, fn1, fn2 string) (bool, error) {
@@ -237,3 +240,78 @@ func TestToAofWithRegex(t *testing.T) {
237240
t.Error("expect error")
238241
}
239242
}
243+
244+
func TestExpiration(t *testing.T) {
245+
newDecoder := func(expr string) decoder {
246+
rdbFile, err := os.Open("../cases/expiration.rdb")
247+
if err != nil {
248+
panic(err)
249+
}
250+
var dec decoder = parser.NewDecoder(rdbFile)
251+
dec, err = wrapDecoder(dec, WithExpirationOption(expr))
252+
if err != nil {
253+
panic(err)
254+
}
255+
return dec
256+
}
257+
258+
dec := newDecoder("0~1751817600")
259+
count := 0
260+
dec.Parse(func(object model.RedisObject) bool {
261+
count++
262+
return true
263+
})
264+
if count != 1 {
265+
t.Errorf("expect 1 got %d", count)
266+
}
267+
268+
dec = newDecoder("1751817600~inf")
269+
count = 0
270+
dec.Parse(func(object model.RedisObject) bool {
271+
count++
272+
return true
273+
})
274+
if count != 0 {
275+
t.Errorf("expect 0 got %d", count)
276+
}
277+
278+
dec = newDecoder("1751731200~1751817600")
279+
count = 0
280+
dec.Parse(func(object model.RedisObject) bool {
281+
count++
282+
return true
283+
})
284+
if count != 1 {
285+
t.Errorf("expect 1 got %d", count)
286+
}
287+
288+
dec = newDecoder("1751817600~now")
289+
count = 0
290+
dec.Parse(func(object model.RedisObject) bool {
291+
count++
292+
return true
293+
})
294+
if count != 0 {
295+
t.Errorf("expect 0 got %d", count)
296+
}
297+
298+
dec = newDecoder("noexpire")
299+
count = 0
300+
dec.Parse(func(object model.RedisObject) bool {
301+
count++
302+
return true
303+
})
304+
if count != 1 {
305+
t.Errorf("expect 1 got %d", count)
306+
}
307+
308+
dec = newDecoder("anyexpire")
309+
count = 0
310+
dec.Parse(func(object model.RedisObject) bool {
311+
count++
312+
return true
313+
})
314+
if count != 1 {
315+
t.Errorf("expect 1 got %d", count)
316+
}
317+
}

0 commit comments

Comments
 (0)