diff --git a/README.md b/README.md index 357803a..8665183 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ # Nodis + ![GitHub top language](https://img.shields.io/github/languages/top/diiyw/nodis) ![GitHub Release](https://img.shields.io/github/v/release/diiyw/nodis) +
- English | [简体中文](https://github.com/diiyw/nodis/blob/main/README_zh-cn.md) Nodis is a Redis implementation using the Golang programming language. This implementation provides a simple way to embed Redis functionality directly into your application or run it as a standalone server. The supported commands are compatible with the original Redis protocol, allowing you to use existing Redis clients like goredis for testing and integration. @@ -21,6 +22,7 @@ Nodis is a Redis implementation using the Golang programming language. This impl - Sorted Set ## Key Features + - **Fast and Embeddable**: The Golang-based implementation is designed to be fast and easily embeddable within your applications. - **Low Memory Usage**: The system only stores hot data in memory, minimizing the overall memory footprint. - **Snapshot and WAL for Data Storage**: This Redis implementation supports snapshot and write-ahead logging (WAL) mechanisms for reliable data storage. @@ -30,33 +32,39 @@ Nodis is a Redis implementation using the Golang programming language. This impl - **Redis Protocol Compatibility**: As of version 1.5.0, this Redis implementation fully supports the original Redis protocol, ensuring seamless integration with existing Redis clients. ## Supported Commands + | **Client Handling** | **Configuration** | **Key Commands** | **String Commands** | **Set Commands** | **Hash Commands** | **List Commands** | **Sorted Set Commands** | -|---------------------|-----------------|-----------------|---------------------|-----------------|-----------------|------------------|----------------| -| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD | -| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD | -| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK | -| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK | -| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE | -| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY | -| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE | -| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE | -| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE | -| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE | -| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM | -| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK | -| | | | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE | -| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR | -| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS | -| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE | -| | | | SETRANGE | | | | ZINTERSTORE | +| ------------------- | ----------------- | ---------------- | ------------------- | ---------------- | ----------------- | ----------------- | ----------------------- | +| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD | +| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD | +| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK | +| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK | +| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE | +| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY | +| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE | +| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE | +| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE | +| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE | +| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM | +| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK | +| | | PTTL | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE | +| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR | +| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS | +| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE | +| | | | SETRANGE | | | | ZINTERSTORE | + ## Get Started + ```bash go get github.com/diiyw/nodis@latest ``` + Or use test version + ```bash go get github.com/diiyw/nodis@main ``` + ```go package main @@ -68,16 +76,18 @@ func main() { n := nodis.Open(opt) defer n.Close() // Set a key-value pair - n.Set("key", []byte("value")) + n.Set("key", []byte("value"),false) n.LPush("list", []byte("value1")) } ``` + ## Examples
Watch changes -Server: +Server: + ```go package main @@ -108,11 +118,13 @@ func main() { } } ``` + - Browser client built with WebAssembly ```bash GOOS=js GOARCH=wasm go build -o test.wasm ``` + ```go package main @@ -139,11 +151,12 @@ func main() { select {} } ``` +
Simple Redis Server -```go +```go package main import ( @@ -161,6 +174,7 @@ func main() { } } ``` + You can use redis-cli to connect to the server. ```bash @@ -171,6 +185,7 @@ redis-cli -p 6380
## Benchmark +
Embed benchmark @@ -197,7 +212,7 @@ Linux VM: 4C/8GB ```bash goos: linux goarch: amd64 -pkg: github.com/diiyw/nodis/bench +pkg: github.com/diiyw/nodis/bench BenchmarkSet-4 806912 1658 ns/op 543 B/op 7 allocs/op BenchmarkGet-4 5941904 190.6 ns/op 7 B/op 0 allocs/op BenchmarkLPush-4 852932 1757 ns/op 615 B/op 9 allocs/op @@ -215,7 +230,7 @@ BenchmarkHGet-4 4442625 243.4 ns/op 7 B/op 0 allocs Redis benchmark tool ```bash -redis-benchmark -p 6380 -t set,get,lpush,lpop,sadd,smembers,zadd,zrank,hset,hget -n 100000 -q +redis-benchmark -p 6380 -t set,get,lpush,lpop,sadd,smembers,zadd,zrank,hset,hget -n 100000 -q ``` ``` @@ -226,7 +241,9 @@ LPOP: 92165.90 requests per second SADD: 91911.76 requests per second HSET: 93023.25 requests per second ``` +
## Note + If you want to persist data, please make sure to call the `Close()` method when your application exits. diff --git a/README_zh-cn.md b/README_zh-cn.md index 34e1162..b323107 100644 --- a/README_zh-cn.md +++ b/README_zh-cn.md @@ -1,60 +1,70 @@ # Nodis + ![GitHub top language](https://img.shields.io/github/languages/top/diiyw/nodis) ![GitHub Release](https://img.shields.io/github/v/release/diiyw/nodis) +
- English | [简体中文](https://github.com/diiyw/nodis/blob/main/README_zh-cn.md) Nodis 是一个使用 Golang 编程语言实现的 Redis。这个实现提供了一种将 Redis 功能直接嵌入到应用程序中或作为独立服务器运行的简单方法。支持的命令与原始 Redis 协议兼容,允许您使用现有的 Redis 客户端(如 goredis)进行测试和集成。 ## 支持的数据类型 + Bitmap String List Hash Set Sorted Set + ## 主要特性 + - **快速和可嵌入**: Golang 实现的设计目标是快速和易于嵌入到您的应用程序中。 - **低内存使用**: 该系统只在内存中存储热数据,将整体内存占用降到最低。 - **快照和 WAL 用于数据存储**: 这个 Redis 实现支持快照和预写日志(WAL)机制,用于可靠的数据存储。 - **自定义数据存储后端**: 您可以集成自定义的数据存储后端,如 Amazon S3、浏览器存储等。 -使用 WebAssembly 支持浏览器: 从 1.2.0 版本开始,这个 Redis 实现可以直接在浏览器中使用 WebAssembly 运行。 + 使用 WebAssembly 支持浏览器: 从 1.2.0 版本开始,这个 Redis 实现可以直接在浏览器中使用 WebAssembly 运行。 - **远程变更监控**: 从 1.2.0 版本开始,该系统支持监视来自远程源的变更。 - **Redis 协议兼容性**: 从 1.5.0 版本开始,这个 Redis 实现完全支持原始的 Redis 协议,确保与现有的 Redis 客户端无缝集成。 -## 支持的Redis命令 +## 支持的 Redis 命令 + | **Client Handling** | **Configuration** | **Key Commands** | **String Commands** | **Set Commands** | **Hash Commands** | **List Commands** | **Sorted Set Commands** | -|---------------------|-----------------|-----------------|---------------------|-----------------|-----------------|------------------|----------------| -| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD | -| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD | -| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK | -| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK | -| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE | -| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY | -| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE | -| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE | -| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE | -| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE | -| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM | -| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK | -| | | | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE | -| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR | -| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS | -| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE | -| | | | SETRANGE | | | | ZINTERSTORE | +| ------------------- | ----------------- | ---------------- | ------------------- | ---------------- | ----------------- | ----------------- | ----------------------- | +| CLIENT | FLUSHALL | DEL | GET | SADD | HSET | LPUSH | ZADD | +| PING | FLUSHDB | EXISTS | SET | SSCAN | HGET | RPUSH | ZCARD | +| QUIT | SAVE | EXPIRE | INCR | SCARD | HDEL | LPOP | ZRANK | +| ECHO | INFO | EXPIREAT | DECR | SPOP | HLEN | RPOP | ZREVRANK | +| DBSIZE | | KEYS | SETBIT | SDIFF | HKEYS | LLEN | ZSCORE | +| MULTI | | TTL | GETBIT | SINTER | HEXISTS | LINDEX | ZINCRBY | +| DISCARD | | RENAME | INCR | SISMEMBER | HGETALL | LINSERT | ZRANGE | +| EXEC | | TYPE | DESR | SMEMBERS | HINCRBY | LPUSHX | ZREVRANGE | +| | | SCAN | SETEX | SREM | HICRBYFLOAT | RPUSHX | ZRANGEBYSCORE | +| | | RANDOMKEY | INCRBY | SMOVE | HSETNX | LREM | ZREVRANGEBYSCORE | +| | | RENAMEEX | DECRBY | SRANDMEMBER | HMGET | LSET | ZREM | +| | | PERSIST | SETNX | SINTERSTORE | HMSET | LRANGE | ZREMRANGEBYRANK | +| | | | INCRBYFLOAT | SUNIONSTORE | HCLEAR | LPOPRPUSH | ZREMRANGEBYSCORE | +| | | | APPEND | | HSCAN | RPOPLPUSH | ZCLEAR | +| | | | GETRANGE | | HVALS | BLPOP | ZEXISTS | +| | | | STRLEN | | HSTRLEN | BRPOP | ZUNIONSTORE | +| | | | SETRANGE | | | | ZINTERSTORE | + ## Get Started + ```bash go get github.com/diiyw/nodis@v1.5.0 ``` + Or use test version + ```bash go get github.com/diiyw/nodis@main ``` + ```go package main @@ -66,16 +76,18 @@ func main() { n := nodis.Open(opt) defer n.Close() // Set a key-value pair - n.Set("key", []byte("value")) + n.Set("key", []byte("value"), false) n.LPush("list", []byte("value1")) } ``` + ## Examples
Watch changes -Server: +Server: + ```go package main @@ -106,11 +118,13 @@ func main() { } } ``` + - Browser client built with WebAssembly ```bash GOOS=js GOARCH=wasm go build -o test.wasm ``` + ```go package main @@ -137,9 +151,11 @@ func main() { select {} } ``` +
## Benchmark +
Embed benchmark Windows 11: 12C/32G @@ -165,7 +181,7 @@ Linux VM: 4C/8GB ```bash goos: linux goarch: amd64 -pkg: github.com/diiyw/nodis/bench +pkg: github.com/diiyw/nodis/bench BenchmarkSet-4 806912 1658 ns/op 543 B/op 7 allocs/op BenchmarkGet-4 5941904 190.6 ns/op 7 B/op 0 allocs/op BenchmarkLPush-4 852932 1757 ns/op 615 B/op 9 allocs/op diff --git a/bench/nodis_test.go b/bench/nodis_test.go index 12c1227..da34b46 100644 --- a/bench/nodis_test.go +++ b/bench/nodis_test.go @@ -16,7 +16,7 @@ func BenchmarkSet(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { id := strconv.Itoa(i) - n.Set(id, []byte("value"+id)) + n.Set(id, []byte("value"+id), false) } } @@ -27,7 +27,7 @@ func BenchmarkGet(b *testing.B) { }) for i := 0; i < 100000; i++ { id := strconv.Itoa(i) - n.Set(id, []byte("value"+id)) + n.Set(id, []byte("value"+id), false) } b.ResetTimer() b.ReportAllocs() diff --git a/examples/hello/main.go b/examples/hello/main.go index fa33626..9663822 100644 --- a/examples/hello/main.go +++ b/examples/hello/main.go @@ -12,6 +12,6 @@ func main() { n := nodis.Open(opt) defer n.Close() // Set a key-value pair - n.Set("echo", []byte("hello world")) + n.Set("echo", []byte("hello world"), false) fmt.Println("Set key-value pair: ", string(n.Get("echo"))) } diff --git a/handler.go b/handler.go index 9ae28cd..1780f9f 100644 --- a/handler.go +++ b/handler.go @@ -77,6 +77,8 @@ func getCommand(name string) func(n *Nodis, conn *redis.Conn, cmd redis.Command) return randomKey case "TTL": return ttl + case "PTTL": + return pTtl case "PERSIST": return Persist case "RENAME": @@ -557,6 +559,25 @@ func ttl(n *Nodis, conn *redis.Conn, cmd redis.Command) { }) } +func pTtl(n *Nodis, conn *redis.Conn, cmd redis.Command) { + if len(cmd.Args) == 0 { + conn.WriteError("PTTL requires at least one argument") + return + } + execCommand(conn, func() { + v := n.PTTL(cmd.Args[0]) + if v == -1 { + conn.WriteInteger(-1) + return + } + if v == -2 { + conn.WriteInteger(-2) + return + } + conn.WriteInteger(v) + }) +} + func Persist(n *Nodis, conn *redis.Conn, cmd redis.Command) { if len(cmd.Args) == 0 { conn.WriteError("PERSIST requires at least one argument") @@ -675,11 +696,17 @@ func setString(n *Nodis, conn *redis.Conn, cmd redis.Command) { get = n.Get(key) } if cmd.Options.NX > 1 { - n.SetNX(key, value) + if !n.SetNX(key, value, cmd.Options.KEEPTTL > 1) { + conn.WriteBulkNull() + return + } } else if cmd.Options.XX > 1 { - n.SetXX(key, value) + if !n.SetXX(key, value, cmd.Options.KEEPTTL > 1) { + conn.WriteBulkNull() + return + } } else { - n.Set(key, value) + n.Set(key, value, cmd.Options.KEEPTTL > 1) } if cmd.Options.EX > 1 { seconds, _ := strconv.ParseInt(cmd.Args[cmd.Options.EX], 10, 64) @@ -689,13 +716,19 @@ func setString(n *Nodis, conn *redis.Conn, cmd redis.Command) { } if cmd.Options.PX > 1 { milliseconds, _ := strconv.ParseInt(cmd.Args[cmd.Options.PX], 10, 64) - n.ExpirePX(key, milliseconds) + if n.ExpirePX(key, milliseconds) == 0 { + conn.WriteBulkNull() + return + } conn.WriteOK() return } if cmd.Options.EXAT > 1 { seconds, _ := strconv.ParseInt(cmd.Args[cmd.Options.EXAT], 10, 64) - n.ExpireAt(key, time.Unix(seconds, 0)) + if n.ExpireAt(key, time.Unix(seconds, 0)) == 0 { + conn.WriteBulkNull() + return + } conn.WriteOK() return } @@ -722,7 +755,7 @@ func mSet(n *Nodis, conn *redis.Conn, cmd redis.Command) { } execCommand(conn, func() { for i := 0; i < len(cmd.Args); i += 2 { - n.Set(cmd.Args[i], []byte(cmd.Args[i+1])) + n.Set(cmd.Args[i], []byte(cmd.Args[i+1]), false) } conn.WriteOK() }) @@ -762,7 +795,7 @@ func setnx(n *Nodis, conn *redis.Conn, cmd redis.Command) { execCommand(conn, func() { key := cmd.Args[0] value := []byte(cmd.Args[1]) - if n.SetNX(key, value) { + if n.SetNX(key, value, false) { conn.WriteInteger(1) return } diff --git a/key.go b/key.go index b3575a7..090cd06 100644 --- a/key.go +++ b/key.go @@ -66,9 +66,7 @@ func (n *Nodis) Expire(key string, seconds int64) int64 { v = 0 return nil } - if meta.expiration == 0 { - meta.expiration = time.Now().UnixMilli() - } + meta.expiration = time.Now().UnixMilli() meta.expiration += seconds * 1000 n.signalModifiedKey(key, meta) n.notify(pb.NewOp(pb.OpType_Expire, key).Expiration(meta.expiration)) @@ -401,6 +399,25 @@ func (n *Nodis) TTL(key string) time.Duration { return v } +// PTTL gets the TTL in milliseconds +func (n *Nodis) PTTL(key string) int64 { + var v int64 + _ = n.exec(func(tx *Tx) error { + meta := tx.readKey(key) + if !meta.isOk() { + v = -2 + return nil + } + if meta.expiration == 0 { + v = -1 + return nil + } + v = meta.expiration - time.Now().UnixMilli() + return nil + }) + return v +} + // Rename a key func (n *Nodis) Rename(key, dstKey string) error { return n.exec(func(tx *Tx) error { diff --git a/key_test.go b/key_test.go index afefaa0..657f6cb 100644 --- a/key_test.go +++ b/key_test.go @@ -15,7 +15,7 @@ func TestKey_Expire(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) n.Expire("test", 2) time.Sleep(time.Second * 2) if n.TTL("test") > 0 { @@ -28,7 +28,7 @@ func TestKey_ExpireXX(t *testing.T) { n := Open(&Options{ Path: "testdata", }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) n.ExpireXX("test", 3) if n.TTL("test") != -1 { t.Errorf("TTL() = %v, want %v", 0, n.TTL("test")) @@ -46,7 +46,7 @@ func TestKey_ExpireNX(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) n.ExpireNX("test", 2) if int64(n.TTL("test").Seconds()) == 0 { t.Errorf("TTL() = %v, want %vs", n.TTL("test"), 0) @@ -64,7 +64,7 @@ func TestKey_ExpireLT(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) v := n.ExpireLT("test", 2) if v != 0 { t.Errorf("ExpireLT() = %v, want %v", v, 0) @@ -82,7 +82,7 @@ func TestKey_ExpireGT(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) v := n.ExpireGT("test", 2) if v == 0 { t.Errorf("ExpireGT() = %v, want not %v", v, 0) @@ -100,7 +100,7 @@ func TestKey_ExpireAt(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) n.ExpireAt("test", time.Now().Add(2*time.Second)) time.Sleep(2 * time.Second) v := n.Get("test") @@ -115,7 +115,7 @@ func TestKey_TTL(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) n.Expire("test", 300) v := n.TTL("test") if v < 299 { @@ -134,7 +134,7 @@ func TestKey_Rename(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) n.Rename("test", "test2") v := n.Get("test") if v != nil { @@ -151,8 +151,8 @@ func TestKey_RenameNX(t *testing.T) { n := Open(&Options{ Path: "testdata", }) - n.Set("test", []byte("test1")) - n.Set("test2", []byte("test2")) + n.Set("test", []byte("test1"), false) + n.Set("test2", []byte("test2"), false) err := n.RenameNX("test", "test2") if err == nil { t.Errorf("RenameNX() = %v, want %v", err, "key exists") @@ -169,9 +169,9 @@ func TestKey_Keys(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test1", []byte("test1")) - n.Set("test2", []byte("test2")) - n.Set("test3", []byte("test3")) + n.Set("test1", []byte("test1"), false) + n.Set("test2", []byte("test2"), false) + n.Set("test3", []byte("test3"), false) keys := n.Keys("test*") if len(keys) != 3 { t.Errorf("Keys() = %v, want %v", len(keys), 3) @@ -185,7 +185,7 @@ func TestKey_Type(t *testing.T) { TidyDuration: 60 * time.Second, Filesystem: &fs.Disk{}, }) - n.Set("test1", []byte("test1")) + n.Set("test1", []byte("test1"), false) n.LPush("test2", []byte("test2")) n.ZAdd("test3", "test3", 10) n.SAdd("test4", "test4") @@ -237,37 +237,37 @@ func TestKey_Scan(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test1", []byte("test1")) - n.Set("test2", []byte("test2")) - n.Set("test3", []byte("test3")) - n.Set("test4", []byte("test4")) - n.Set("test5", []byte("test5")) - n.Set("test6", []byte("test6")) - n.Set("test7", []byte("test7")) - n.Set("test8", []byte("test8")) - n.Set("test9", []byte("test9")) - n.Set("test10", []byte("test10")) - n.Set("test11", []byte("test11")) - n.Set("test12", []byte("test12")) - n.Set("test13", []byte("test13")) - n.Set("test14", []byte("test14")) - n.Set("test15", []byte("test15")) - n.Set("test16", []byte("test16")) - n.Set("test17", []byte("test17")) - n.Set("test18", []byte("test18")) - n.Set("test19", []byte("test19")) - n.Set("test20", []byte("test20")) - n.Set("test21", []byte("test21")) - n.Set("test22", []byte("test22")) - n.Set("test23", []byte("test23")) - n.Set("test24", []byte("test24")) - n.Set("test25", []byte("test25")) - n.Set("test26", []byte("test26")) - n.Set("test27", []byte("test27")) - n.Set("test28", []byte("test28")) - n.Set("test29", []byte("test29")) - n.Set("test30", []byte("test30")) - n.Set("test31", []byte("test31")) + n.Set("test1", []byte("test1"), false) + n.Set("test2", []byte("test2"), false) + n.Set("test3", []byte("test3"), false) + n.Set("test4", []byte("test4"), false) + n.Set("test5", []byte("test5"), false) + n.Set("test6", []byte("test6"), false) + n.Set("test7", []byte("test7"), false) + n.Set("test8", []byte("test8"), false) + n.Set("test9", []byte("test9"), false) + n.Set("test10", []byte("test10"), false) + n.Set("test11", []byte("test11"), false) + n.Set("test12", []byte("test12"), false) + n.Set("test13", []byte("test13"), false) + n.Set("test14", []byte("test14"), false) + n.Set("test15", []byte("test15"), false) + n.Set("test16", []byte("test16"), false) + n.Set("test17", []byte("test17"), false) + n.Set("test18", []byte("test18"), false) + n.Set("test19", []byte("test19"), false) + n.Set("test20", []byte("test20"), false) + n.Set("test21", []byte("test21"), false) + n.Set("test22", []byte("test22"), false) + n.Set("test23", []byte("test23"), false) + n.Set("test24", []byte("test24"), false) + n.Set("test25", []byte("test25"), false) + n.Set("test26", []byte("test26"), false) + n.Set("test27", []byte("test27"), false) + n.Set("test28", []byte("test28"), false) + n.Set("test29", []byte("test29"), false) + n.Set("test30", []byte("test30"), false) + n.Set("test31", []byte("test31"), false) _, result := n.Scan(0, "test*", 10, ds.String) if len(result) != 10 { t.Errorf("Scan() = %v, want %v", len(result), 10) @@ -296,7 +296,7 @@ func TestKey_Exists(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("test", []byte("test1")) + n.Set("test", []byte("test1"), false) if n.Exists("test") != 1 { t.Errorf("Exists() = %v, want %v", n.Exists("test"), true) } diff --git a/nodis.go b/nodis.go index 97ca20b..a511d4f 100644 --- a/nodis.go +++ b/nodis.go @@ -198,7 +198,7 @@ func (n *Nodis) patch(op *pb.Op) error { case pb.OpType_SRem: n.SRem(op.Key, op.Operation.Members...) case pb.OpType_Set: - n.Set(op.Key, op.Operation.Value) + n.Set(op.Key, op.Operation.Value, op.Operation.KeepTTL) case pb.OpType_ZAdd: n.ZAdd(op.Key, op.Operation.Member, op.Operation.Score) case pb.OpType_ZClear: diff --git a/nodis_test.go b/nodis_test.go index 4b29ef0..3588879 100644 --- a/nodis_test.go +++ b/nodis_test.go @@ -31,7 +31,7 @@ func TestNodis_OpenAndCloseBigdata10000(t *testing.T) { n := Open(&opt) for i := 0; i < 10000; i++ { is := strconv.Itoa(i) - n.Set(is, []byte(is)) + n.Set(is, []byte(is), false) } for i := 10000; i < 20000; i++ { n.ZAdd("zset", strconv.Itoa(i), float64(i)) @@ -81,7 +81,7 @@ func TestNodis_Snapshot(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("test", []byte("test")) + n.Set("test", []byte("test"), false) n.Snapshot("testdata") _ = n.Close() } @@ -92,10 +92,10 @@ func TestNodis_SnapshotChanged(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("test", []byte("test")) + n.Set("test", []byte("test"), false) n.Snapshot(opt.Path) time.Sleep(time.Second) - n.Set("test", []byte("test_new")) + n.Set("test", []byte("test_new"), false) n.Snapshot(opt.Path) _ = n.Close() } @@ -129,7 +129,7 @@ func TestNodis_Clear(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("test", []byte("test")) + n.Set("test", []byte("test"), false) n.Clear() v := n.Get("test") if v != nil { @@ -212,7 +212,7 @@ func TestNodis_SetEntity(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("test", []byte("test")) + n.Set("test", []byte("test"), false) data := n.GetEntry("test") n.Clear() v := n.Get("test") @@ -236,13 +236,13 @@ func TestNodis_Stick(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("test", []byte("test")) + n.Set("test", []byte("test"), false) n.Stick([]string{"test"}, func(op *pb.Operation) { if op == nil || string(op.Value) != "test_new" { t.Errorf("Stick() = %v, want %v", op, "test_new") } }) - n.Set("test", []byte("test_new")) + n.Set("test", []byte("test_new"), false) time.Sleep(time.Second) } @@ -252,14 +252,14 @@ func TestNodis_UnStick(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("test", []byte("test")) + n.Set("test", []byte("test"), false) id := n.Stick([]string{"test"}, func(op *pb.Operation) { if op == nil || string(op.Value) != "test_new" { t.Errorf("Stick() = %v, want %v", op, "test_new") } }) n.UnStick(id) - n.Set("test", []byte("test_new")) + n.Set("test", []byte("test_new"), false) time.Sleep(time.Second) } @@ -269,7 +269,7 @@ func TestNodis_OpenAndClose(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("str", []byte("set")) + n.Set("str", []byte("set"), false) n.ZAdd("zset", "zset", 1) n.HSet("hset", "hset", []byte("hset")) n.LPush("lpush", []byte("lpush")) diff --git a/pb/nodis.pb.go b/pb/nodis.pb.go index f6286d6..0d4bff0 100644 --- a/pb/nodis.pb.go +++ b/pb/nodis.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.9.1 +// protoc-gen-go v1.34.0 +// protoc v3.6.1 // source: nodis.proto package pb @@ -201,6 +201,7 @@ type Operation struct { Weights []float64 `protobuf:"fixed64,23,rep,packed,name=weights,proto3" json:"weights,omitempty"` Aggregate string `protobuf:"bytes,24,opt,name=aggregate,proto3" json:"aggregate,omitempty"` Mode int64 `protobuf:"varint,25,opt,name=Mode,proto3" json:"Mode,omitempty"` + KeepTTL bool `protobuf:"varint,26,opt,name=KeepTTL,proto3" json:"KeepTTL,omitempty"` } func (x *Operation) Reset() { @@ -410,6 +411,13 @@ func (x *Operation) GetMode() int64 { return 0 } +func (x *Operation) GetKeepTTL() bool { + if x != nil { + return x.KeepTTL + } + return false +} + type KeyScore struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1008,7 +1016,7 @@ var File_nodis_proto protoreflect.FileDescriptor var file_nodis_proto_rawDesc = []byte{ 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x69, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, - 0x62, 0x22, 0xd9, 0x04, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x62, 0x22, 0xf3, 0x04, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, 0x65, @@ -1045,85 +1053,87 @@ var file_nodis_proto_rawDesc = []byte{ 0x28, 0x01, 0x52, 0x07, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, - 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x38, 0x0a, - 0x08, 0x4b, 0x65, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, - 0x52, 0x05, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x31, 0x0a, 0x09, 0x5a, 0x53, 0x65, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x63, 0x6f, - 0x72, 0x65, 0x52, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x23, 0x0a, 0x09, 0x4c, 0x69, - 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, - 0x23, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x22, 0x22, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x34, 0x0a, 0x09, 0x48, 0x61, 0x73, 0x68, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x52, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xc4, 0x02, 0x0a, 0x05, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x0b, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x48, 0x00, 0x52, 0x0b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x2d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x2a, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, - 0x00, 0x52, 0x08, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x48, - 0x61, 0x73, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, - 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, - 0x09, 0x48, 0x61, 0x73, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x5a, 0x53, - 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x70, 0x62, 0x2e, 0x5a, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, - 0x5a, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x78, 0x70, - 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x5b, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x05, 0x49, - 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x49, 0x74, 0x65, 0x6d, - 0x73, 0x1a, 0x2c, 0x0a, 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x44, - 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x2a, - 0xd4, 0x03, 0x0a, 0x06, 0x4f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, - 0x6e, 0x65, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x10, 0x01, 0x12, - 0x07, 0x0a, 0x03, 0x44, 0x65, 0x6c, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x69, - 0x72, 0x65, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, - 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x48, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x10, 0x05, 0x12, 0x08, - 0x0a, 0x04, 0x48, 0x44, 0x65, 0x6c, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x49, 0x6e, 0x63, - 0x72, 0x42, 0x79, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, 0x48, 0x49, 0x6e, 0x63, 0x72, 0x42, 0x79, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x10, 0x08, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x4d, 0x53, 0x65, 0x74, - 0x10, 0x09, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x53, 0x65, 0x74, 0x10, 0x0a, 0x12, 0x0b, 0x0a, 0x07, - 0x4c, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x10, 0x0c, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x50, 0x6f, - 0x70, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x50, 0x6f, 0x70, 0x52, 0x50, 0x75, 0x73, 0x68, - 0x10, 0x0e, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x50, 0x75, 0x73, 0x68, 0x10, 0x0f, 0x12, 0x0a, 0x0a, - 0x06, 0x4c, 0x50, 0x75, 0x73, 0x68, 0x58, 0x10, 0x10, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x52, 0x65, - 0x6d, 0x10, 0x11, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x53, 0x65, 0x74, 0x10, 0x12, 0x12, 0x09, 0x0a, - 0x05, 0x4c, 0x54, 0x72, 0x69, 0x6d, 0x10, 0x13, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x50, 0x6f, 0x70, - 0x10, 0x14, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x50, 0x6f, 0x70, 0x4c, 0x50, 0x75, 0x73, 0x68, 0x10, - 0x15, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x50, 0x75, 0x73, 0x68, 0x10, 0x16, 0x12, 0x0a, 0x0a, 0x06, - 0x52, 0x50, 0x75, 0x73, 0x68, 0x58, 0x10, 0x17, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x41, 0x64, 0x64, - 0x10, 0x18, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x52, 0x65, 0x6d, 0x10, 0x19, 0x12, 0x07, 0x0a, 0x03, - 0x53, 0x65, 0x74, 0x10, 0x1a, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x41, 0x64, 0x64, 0x10, 0x1b, 0x12, - 0x0a, 0x0a, 0x06, 0x5a, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x10, 0x1c, 0x12, 0x0b, 0x0a, 0x07, 0x5a, - 0x49, 0x6e, 0x63, 0x72, 0x42, 0x79, 0x10, 0x1d, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x52, 0x65, 0x6d, - 0x10, 0x1e, 0x12, 0x13, 0x0a, 0x0f, 0x5a, 0x52, 0x65, 0x6d, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, - 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x10, 0x1f, 0x12, 0x14, 0x0a, 0x10, 0x5a, 0x52, 0x65, 0x6d, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x10, 0x20, 0x12, 0x0a, 0x0a, - 0x06, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x10, 0x21, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x65, 0x72, - 0x73, 0x69, 0x73, 0x74, 0x10, 0x22, 0x12, 0x0f, 0x0a, 0x0b, 0x5a, 0x55, 0x6e, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x10, 0x23, 0x12, 0x0f, 0x0a, 0x0b, 0x5a, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x10, 0x24, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x4e, 0x58, 0x10, 0x25, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x4b, 0x65, 0x65, 0x70, 0x54, 0x54, 0x4c, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x4b, 0x65, 0x65, 0x70, 0x54, 0x54, 0x4c, 0x22, 0x38, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x53, 0x63, + 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x53, + 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x53, 0x63, 0x6f, 0x72, + 0x65, 0x22, 0x31, 0x0a, 0x09, 0x5a, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x24, + 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x70, 0x62, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x06, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x22, 0x23, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x23, 0x0a, 0x0b, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3b, + 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x08, 0x53, + 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, + 0x34, 0x0a, 0x09, 0x48, 0x61, 0x73, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x06, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, + 0x62, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x06, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xc4, 0x02, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x4c, 0x69, + 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, + 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x53, 0x65, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, + 0x2e, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x08, 0x53, 0x65, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x48, 0x61, 0x73, 0x68, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x48, 0x61, + 0x73, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, 0x48, 0x61, 0x73, 0x68, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2d, 0x0a, 0x09, 0x5a, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x5a, 0x53, 0x65, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x09, 0x5a, 0x53, 0x65, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x5b, 0x0a, 0x05, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x2e, + 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x1a, 0x2c, 0x0a, 0x04, 0x49, + 0x74, 0x65, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x2a, 0xd4, 0x03, 0x0a, 0x06, 0x4f, 0x70, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x09, + 0x0a, 0x05, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x65, 0x6c, + 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x10, 0x03, 0x12, 0x0c, + 0x0a, 0x08, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, + 0x48, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x10, 0x05, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x44, 0x65, 0x6c, + 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x49, 0x6e, 0x63, 0x72, 0x42, 0x79, 0x10, 0x07, 0x12, + 0x10, 0x0a, 0x0c, 0x48, 0x49, 0x6e, 0x63, 0x72, 0x42, 0x79, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x10, + 0x08, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x4d, 0x53, 0x65, 0x74, 0x10, 0x09, 0x12, 0x08, 0x0a, 0x04, + 0x48, 0x53, 0x65, 0x74, 0x10, 0x0a, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x49, 0x6e, 0x73, 0x65, 0x72, + 0x74, 0x10, 0x0c, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x50, 0x6f, 0x70, 0x10, 0x0d, 0x12, 0x0d, 0x0a, + 0x09, 0x4c, 0x50, 0x6f, 0x70, 0x52, 0x50, 0x75, 0x73, 0x68, 0x10, 0x0e, 0x12, 0x09, 0x0a, 0x05, + 0x4c, 0x50, 0x75, 0x73, 0x68, 0x10, 0x0f, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x50, 0x75, 0x73, 0x68, + 0x58, 0x10, 0x10, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x52, 0x65, 0x6d, 0x10, 0x11, 0x12, 0x08, 0x0a, + 0x04, 0x4c, 0x53, 0x65, 0x74, 0x10, 0x12, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x54, 0x72, 0x69, 0x6d, + 0x10, 0x13, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x50, 0x6f, 0x70, 0x10, 0x14, 0x12, 0x0d, 0x0a, 0x09, + 0x52, 0x50, 0x6f, 0x70, 0x4c, 0x50, 0x75, 0x73, 0x68, 0x10, 0x15, 0x12, 0x09, 0x0a, 0x05, 0x52, + 0x50, 0x75, 0x73, 0x68, 0x10, 0x16, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x50, 0x75, 0x73, 0x68, 0x58, + 0x10, 0x17, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x41, 0x64, 0x64, 0x10, 0x18, 0x12, 0x08, 0x0a, 0x04, + 0x53, 0x52, 0x65, 0x6d, 0x10, 0x19, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x10, 0x1a, 0x12, + 0x08, 0x0a, 0x04, 0x5a, 0x41, 0x64, 0x64, 0x10, 0x1b, 0x12, 0x0a, 0x0a, 0x06, 0x5a, 0x43, 0x6c, + 0x65, 0x61, 0x72, 0x10, 0x1c, 0x12, 0x0b, 0x0a, 0x07, 0x5a, 0x49, 0x6e, 0x63, 0x72, 0x42, 0x79, + 0x10, 0x1d, 0x12, 0x08, 0x0a, 0x04, 0x5a, 0x52, 0x65, 0x6d, 0x10, 0x1e, 0x12, 0x13, 0x0a, 0x0f, + 0x5a, 0x52, 0x65, 0x6d, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x10, + 0x1f, 0x12, 0x14, 0x0a, 0x10, 0x5a, 0x52, 0x65, 0x6d, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x10, 0x20, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x10, 0x21, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x10, 0x22, + 0x12, 0x0f, 0x0a, 0x0b, 0x5a, 0x55, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x10, + 0x23, 0x12, 0x0f, 0x0a, 0x0b, 0x5a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x65, + 0x10, 0x24, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4e, 0x58, 0x10, 0x25, + 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/pb/nodis.proto b/pb/nodis.proto index f99c09a..0a32674 100644 --- a/pb/nodis.proto +++ b/pb/nodis.proto @@ -69,6 +69,7 @@ message Operation { repeated double weights = 23; string aggregate = 24; int64 Mode = 25; + bool KeepTTL = 26; } message KeyScore { diff --git a/pb/op.go b/pb/op.go index d29f825..db8ed18 100644 --- a/pb/op.go +++ b/pb/op.go @@ -158,6 +158,12 @@ func (o *Op) Mode(mode int64) *Op { return o } +// KeepTTL set the keep ttl +func (o *Op) KeepTTL(keepTTL bool) *Op { + o.Operation.KeepTTL = keepTTL + return o +} + func (o *Op) Reset() { o.Operation.Reset() opPool.Put(o) diff --git a/store_test.go b/store_test.go index 4b9540b..cc8e3f8 100644 --- a/store_test.go +++ b/store_test.go @@ -275,7 +275,7 @@ func TestStore_parseValue(t *testing.T) { Path: "testdata", } n := Open(opt) - n.Set("test", []byte("test")) + n.Set("test", []byte("test"), false) data := n.GetEntry("test") value, err := n.store.parseValue(data) if err != nil { diff --git a/str.go b/str.go index 2e6cba4..d9f674d 100644 --- a/str.go +++ b/str.go @@ -15,12 +15,15 @@ func (n *Nodis) newStr() ds.Value { } // Set a key with a value and a TTL -func (n *Nodis) Set(key string, value []byte) { +func (n *Nodis) Set(key string, value []byte, keepTTL bool) { _ = n.exec(func(tx *Tx) error { meta := tx.writeKey(key, n.newStr) meta.value.(*str.String).Set(value) + if !keepTTL { + meta.expiration = 0 + } n.signalModifiedKey(key, meta) - n.notify(pb.NewOp(pb.OpType_Set, key).Value(value)) + n.notify(pb.NewOp(pb.OpType_Set, key).Value(value).KeepTTL(keepTTL)) return nil }) } @@ -42,9 +45,7 @@ func (n *Nodis) GetSet(key string, value []byte) []byte { func (n *Nodis) SetEX(key string, value []byte, seconds int64) { _ = n.exec(func(tx *Tx) error { meta := tx.writeKey(key, n.newStr) - if meta.expiration == 0 { - meta.expiration = time.Now().UnixMilli() - } + meta.expiration = time.Now().UnixMilli() meta.expiration += seconds * 1000 meta.value.(*str.String).Set(value) n.signalModifiedKey(key, meta) @@ -57,9 +58,7 @@ func (n *Nodis) SetEX(key string, value []byte, seconds int64) { func (n *Nodis) SetPX(key string, value []byte, milliseconds int64) { _ = n.exec(func(tx *Tx) error { meta := tx.writeKey(key, n.newStr) - if meta.expiration == 0 { - meta.expiration = time.Now().UnixMilli() - } + meta.expiration = time.Now().UnixMilli() meta.expiration += milliseconds n.signalModifiedKey(key, meta) n.notify(pb.NewOp(pb.OpType_Set, key).Value(value).Expiration(meta.expiration)) @@ -69,7 +68,7 @@ func (n *Nodis) SetPX(key string, value []byte, milliseconds int64) { } // SetNX set a key with a value if it does not exist -func (n *Nodis) SetNX(key string, value []byte) bool { +func (n *Nodis) SetNX(key string, value []byte, keepTTL bool) bool { var ok bool _ = n.exec(func(tx *Tx) error { meta := tx.writeKey(key, nil) @@ -77,9 +76,12 @@ func (n *Nodis) SetNX(key string, value []byte) bool { return nil } meta = tx.newKey(meta, key, n.newStr) + if !keepTTL { + meta.expiration = 0 + } meta.value.(*str.String).Set(value) n.signalModifiedKey(key, meta) - n.notify(pb.NewOp(pb.OpType_Set, key).Value(value)) + n.notify(pb.NewOp(pb.OpType_Set, key).Value(value).KeepTTL(keepTTL)) ok = true return nil }) @@ -87,16 +89,19 @@ func (n *Nodis) SetNX(key string, value []byte) bool { } // SetXX set a key with a value if it exists -func (n *Nodis) SetXX(key string, value []byte) bool { +func (n *Nodis) SetXX(key string, value []byte, keepTTL bool) bool { var ok bool _ = n.exec(func(tx *Tx) error { meta := tx.writeKey(key, nil) if !meta.isOk() { return nil } - n.signalModifiedKey(key, meta) - n.notify(pb.NewOp(pb.OpType_Set, key).Value(value)) meta.value.(*str.String).Set(value) + if !keepTTL { + meta.expiration = 0 + } + n.signalModifiedKey(key, meta) + n.notify(pb.NewOp(pb.OpType_Set, key).Value(value).KeepTTL(keepTTL)) ok = true return nil }) @@ -321,6 +326,6 @@ func (n *Nodis) MSet(pairs ...string) { return } for i := 0; i < len(pairs); i += 2 { - n.Set(pairs[i], unsafe.Slice(unsafe.StringData(pairs[i+1]), len(pairs[i+1]))) + n.Set(pairs[i], unsafe.Slice(unsafe.StringData(pairs[i+1]), len(pairs[i+1])), false) } } diff --git a/str_test.go b/str_test.go index 724b738..fabe737 100644 --- a/str_test.go +++ b/str_test.go @@ -10,17 +10,17 @@ func TestStr_Set(t *testing.T) { Path: "testdata", TidyDuration: 60 * time.Second, }) - n.Set("a", []byte("b")) + n.Set("a", []byte("b"), false) v := n.Get("a") if string(v) != "b" { t.Errorf("Set failed expected b got `%s`", string(v)) } - n.Set("a", []byte("b")) + n.Set("a", []byte("b"), false) v = n.Get("a") if string(v) != "b" { t.Errorf("Set failed expected b got `%s`", string(v)) } - n.Set("a", []byte("b")) + n.Set("a", []byte("b"), false) v = n.Get("a") if string(v) != "b" { t.Errorf("Set failed expected b got `%s`", string(v)) @@ -56,6 +56,6 @@ func TestStr_BitCount(t *testing.T) { n.SetBit("a", 6, true) n.SetBit("a", 7, true) if n.BitCount("a", 0, 0, true) != 8 { - t.Errorf("BitCount failed expected 8 got %d", n.BitCount("a", 0, 0,true)) + t.Errorf("BitCount failed expected 8 got %d", n.BitCount("a", 0, 0, true)) } }