Compare commits

..

103 Commits

Author SHA1 Message Date
innov a1fa8b22de ADD file via upload 2022-03-09 16:19:43 +08:00
bandl a9fac2572b fix(doc): fix redme image err 2022-02-23 18:08:05 +08:00
bandl 57caa66ef8
!103 更新文档
Merge pull request !103 from bandl/feat-doc-update
2022-02-23 05:40:30 +00:00
bandl d254a71560 feat(doc): update doc 2022-02-23 13:39:27 +08:00
bandl 07dd0f8874
!102 修复 dao 的测试错误
Merge pull request !102 from bandl/fix-dao-test
2022-02-23 05:36:52 +00:00
bandl dafffdde2c fix(dao): fix dao test err 2022-02-23 13:34:10 +08:00
bandl c6b14ced27 !101 feat-channex
Merge pull request !101 from bandl/feat-storage-channelx
2021-11-30 10:55:07 +00:00
bandl b87799a88e feat(README): update Readme 2021-11-30 18:54:32 +08:00
bandl dcfae2353b test(dao-channelX): add dao channelX test 2021-11-30 18:54:32 +08:00
bandl bf0c03a77f feat(dao-channelx): add dao channelx 2021-11-30 18:54:32 +08:00
bandl a57eab1184 test(channex): add channelx test 2021-11-30 18:54:32 +08:00
bandl ef4cbb0cee f 2021-11-30 18:54:32 +08:00
bandl f62a59b551 feat(structure): add channelx 2021-11-29 23:35:18 +08:00
bandl a949ab2edc chore(mock): update mock 2021-11-29 23:34:14 +08:00
bandl 7ac9651ef3 fix(lru): add key update length 2021-11-29 16:11:28 +08:00
bandl 19e1bb59a3 test(channelx): add channelx test 2021-11-29 00:16:17 +08:00
bandl c381c57374 feat(structure-channelx): add channelx 2021-11-29 00:16:04 +08:00
bandl 3f337dba9b chore(dao-service): update dao service 2021-11-28 20:11:21 +08:00
bandl a37097b3dd !100 修复 stringx 的一些 bug
Merge pull request !100 from bandl/fix-dao-stringx
2021-11-28 11:50:29 +00:00
bandl d90c05296a test(dao-stringx): update GetSet 2021-11-28 19:47:23 +08:00
bandl 2a556a9db6 fix(structure-stringx): fix GetSet set init nil key 2021-11-28 19:47:08 +08:00
bandl c0da22ef6f test(dao-stringx): add test TestDao_GetRange 2021-11-28 19:33:25 +08:00
bandl cf4b24ea86 fix(value): add fix value get range slice 2021-11-28 19:32:59 +08:00
bandl 953daca82c !99 修复 Stringx 的测试中的 warning
Merge pull request !99 from Pyroo/dao-stringx-test
2021-11-27 11:23:49 +00:00
Pyroo 5974dadd3e fix(storage-stringx): fix warning 2021-11-25 20:50:57 +08:00
bandl 1baac521fa !98 添加 Stringx 的测试
Merge pull request !98 from Pyroo/test-dao-stringx
2021-11-25 12:37:25 +00:00
Pyroo d6792444a7 test(storage-stringx): add stringx test 2021-11-25 20:28:53 +08:00
bandl 64a02b642e !97 完成 setx 测试
Merge pull request !97 from bandl/feat-dao-setx
2021-11-21 15:11:37 +00:00
bandl a5ef559e14 feat(dao-external): add external mock 2021-11-21 23:10:14 +08:00
bandl 0c8a17b21d test(setx): add setx test 2021-11-21 23:09:55 +08:00
bandl 0207878507 fix(setx): fix make cap 2021-11-21 23:09:40 +08:00
bandl 813b48b650 !96 添加 hashx 测试
Merge pull request !96 from bandl/test-dao-hashx
2021-11-18 11:03:32 +00:00
bandl cdd26736a5 feat(dao-hashx): add dao hashx test 2021-11-18 18:59:15 +08:00
bandl 40afd8057d fix(hashx): fix HIncrBy err catch 2021-11-18 18:58:35 +08:00
bandl 08bc1892df chore(proto): update proto 2021-11-18 17:05:03 +08:00
bandl 5e89f37e40 !95 add dao test stringx
Merge pull request !95 from bandl/test-dao-mock
2021-11-18 07:36:48 +00:00
bandl 6b2f3fb3be test(dao-stringx): add dao stringx test 2021-11-18 15:35:21 +08:00
bandl 499322c080 chore(mock): update mock 2021-11-18 14:54:42 +08:00
bandl e5f217b3b0 teat(storage-gateway): add gateway mock 2021-11-18 14:54:27 +08:00
bandl 113185d17c feat(storage-gateway): add storage gateway mock 2021-11-18 14:54:03 +08:00
bandl 981a3341ef !94 添加 setx 接口
Merge pull request !94 from bandl/feat-storage-setx
2021-11-16 06:44:29 +00:00
bandl af6426f83b feay(storage-dao): add setx type dao 2021-11-16 00:19:18 +08:00
bandl d68209c94c feat(external-gateway): add external gateway call 2021-11-16 00:19:18 +08:00
bandl 60cf8f5eb1 test(structure-hashx): add hashx range test 2021-11-16 00:19:18 +08:00
bandl 594f8acf32 feat(structure-hashx): add hashx range 2021-11-16 00:19:18 +08:00
bandl 366793d955 chore(proto): update proto 2021-11-16 00:19:18 +08:00
bandl 5105a62bca test(hashx): add unsafe.Point test 2021-11-13 20:04:21 +08:00
bandl 400d620aa4 test(lru-worker): update lru worker test 2021-11-11 23:00:21 +08:00
bandl 25be4a1509 test(hash-endpoint): update hash endpoint test 2021-11-11 23:00:04 +08:00
bandl 60de1a6ae9 chore(service): update service 2021-11-11 22:46:39 +08:00
bandl 55204575d7 feat(temp): update service temp to event2 2021-11-11 22:46:20 +08:00
bandl 2f81eab981 feat(lru, single service): update event2 2021-11-11 22:39:50 +08:00
bandl 3eb515325d feat(lru): update lru event2 2021-11-11 22:32:14 +08:00
bandl 3f3b208db1 test(event2): add event2 test 2021-11-11 22:24:28 +08:00
bandl 8b8fd58c09 feat(event2): add event2 2021-11-11 22:24:17 +08:00
bandl 62d3105273 doc(event): add event2.0 doc 2021-11-10 17:38:20 +08:00
bandl 51bd9b242f fix(hash-endpoint): tranport to endpoint 2021-11-07 21:57:22 +08:00
bandl f6eaae71b9 chore(service): update service 2021-11-07 21:49:34 +08:00
bandl 921078c61d chore(proto): update proto 2021-11-07 20:46:22 +08:00
bandl c8ef4c6e46 !93 doc(storage): update storage
Merge pull request !93 from bandl/auto-5261189-master-1636186822154
2021-11-06 08:20:46 +00:00
bandl c6273d084e doc(storage): update storage 2021-11-06 16:20:15 +08:00
bandl fd605d125f !92 doc(storage): add storage icon
Merge pull request !92 from bandl/auto-5261189-master-1636177701995
2021-11-06 05:49:01 +00:00
bandl c9dcb41cad doc(storage): add storage icon 2021-11-06 13:48:17 +08:00
bandl f7bb695e82 !91 doc(storage): fix url
Merge pull request !91 from bandl/auto-5261189-master-1636124592092
2021-11-05 15:03:34 +00:00
bandl 4e6c2ed22a doc(storage): fix url 2021-11-05 23:03:08 +08:00
bandl 0c08e40667 !90 doc(Redeme): fix url !
Merge pull request !90 from bandl/auto-5261189-master-1636124488904
2021-11-05 15:01:51 +00:00
bandl 7fa66abbf0 doc(Redeme): fix url ! 2021-11-05 23:01:24 +08:00
bandl a910e4af21 !89 添加开发者文档
Merge pull request !89 from bandl/doc-developer-doc
2021-11-05 14:59:50 +00:00
bandl 51914aea8a doc(storage): add developer doc 2021-11-05 22:58:59 +08:00
bandl bbfd32cebc !88 完成
Merge pull request !88 from bandl/feat-structure-hashx
2021-11-05 12:51:13 +00:00
bandl 44bd5bc7cd doc(readme): over hashx 2021-11-05 20:48:34 +08:00
bandl fcdb2310fe feat(storage-dao): add hashx 2021-11-05 20:44:09 +08:00
bandl 222bcc4eea chore(service): update service 2021-11-05 20:43:56 +08:00
bandl c3cff03b2b test(structure-hashx): add hashx test 2021-11-05 16:36:18 +08:00
bandl 06baf3993d feat(hashx-interface): add hash interface 2021-11-05 16:36:00 +08:00
bandl 976215ee10 feat(structure-hashx): add hashx 2021-11-05 16:34:50 +08:00
bandl 778d5152c8 perf(incr): option incr to values 2021-11-05 14:41:39 +08:00
bandl 5ce350f115 fix(linces): update license 2021-11-04 21:35:09 +08:00
bandl 047c910278 chore(service): update service 2021-11-04 20:36:42 +08:00
bandl dcada2f2fe feat(shell): add parse proto map 2021-11-04 20:33:37 +08:00
bandl 88774daede chore(proto): update proto 2021-11-04 20:28:42 +08:00
bandl 344c136586 feat(yaml): add hashx yaml 2021-11-04 19:18:56 +08:00
bandl 4c9ab82123 !87 test(structure-val): add perf test
Merge pull request !87 from bandl/auto-5261189-master-1636014762802
2021-11-04 08:33:07 +00:00
bandl 2ed75832ba test(structure-val): add perf test 2021-11-04 16:32:17 +08:00
bandl 0f1142d434 perf(structure-value): perf set bit 2021-11-04 16:31:55 +08:00
bandl b6dedfa384 !86 添加 docker 安装,以及描述
Merge pull request !86 from bandl/docker-build
2021-11-03 16:03:03 +00:00
bandl 0f2b73e932 doc(readme): add v1 readme 2021-11-04 00:01:14 +08:00
bandl 2f46dfaa2e feat(icon): add icon 2021-11-04 00:01:14 +08:00
bandl c867665b60 feat(conf): update conf 2021-11-04 00:01:14 +08:00
bandl b91966709b feat(dockerfile): add docker file
f
2021-11-04 00:00:17 +08:00
bandl 47cdf0859b !85 fix(proto): fix proto key err
Merge pull request !85 from bandl/auto-5261189-master-1635925021767
2021-11-03 07:37:57 +00:00
bandl 0b9230094a fix(proto): fix proto key err 2021-11-03 15:36:55 +08:00
bandl eccfd6a439 !84 aof
Merge pull request !84 from bandl/feat-recover-aof
2021-11-03 04:42:21 +00:00
bandl f5c3b0e1db fat(ttl): add permanent storage 2021-11-03 12:40:58 +08:00
bandl 5ee502021d feat(eooorx): update errorx key base 2021-11-02 21:34:23 +08:00
bandl 9fed552380 feat(storage): recver lru by aof 2021-11-02 21:19:35 +08:00
bandl 7d9081ce8e chore(service): updater dao service 2021-11-02 20:35:45 +08:00
bandl 4ca09febb4 feat(shell): add recover aof 2021-11-02 20:35:28 +08:00
bandl be528cbb6d !83 更新 mod 号为 wheat-os
Merge pull request !83 from bandl/refactor-mod
2021-11-02 06:46:09 +00:00
bandl 70b23849bc refactor(mod): gitee.com/wheat-os 2021-11-02 14:45:08 +08:00
bandl 99133bf7ea !82 fix-aof
Merge pull request !82 from bandl/fix-aof-nil
2021-11-02 05:03:07 +00:00
bandl 1ca43cde6c fix(aof): fix aof is nil 2021-11-02 13:02:02 +08:00
bandl de59f13234 !81 add-AOF
Merge pull request !81 from bandl/feat-storage-aof
2021-11-01 16:00:57 +00:00
111 changed files with 11974 additions and 583 deletions

7
Dockerfile Normal file
View File

@ -0,0 +1,7 @@
FROM ubuntu:18.04
WORKDIR /home/src/gitee.com/wheat-os/wheat-cache
ADD . /home/src/gitee.com/wheat-os/wheat-cache
RUN mkdir /etc/wheat-cache
RUN mv /home/src/gitee.com/wheat-os/wheat-cache/conf/wheat-cache.yaml /etc/wheat-cache/

Binary file not shown.

147
README.md

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
package client
import (
"gitee.com/timedb/wheatCache/client/middle"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/client/middle"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"google.golang.org/grpc"
)

View File

@ -4,8 +4,8 @@ import (
"context"
"testing"
"gitee.com/timedb/wheatCache/client/middle"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/client/middle"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/stretchr/testify/require"
)
@ -14,10 +14,7 @@ func TestClient(t *testing.T) {
require.NoError(t, err)
ctx := context.Background()
bKey := &proto.BaseKey{
Key: "apple",
Ttl: 10,
}
bKey := proto.NewBaseKey("apple")
resp, err := cli.Set(ctx, &proto.SetRequest{
Key: bKey,
Val: "yyyy",

View File

@ -3,7 +3,7 @@ package middle
import (
"context"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"

View File

@ -3,7 +3,7 @@ version: 'v1.0'
env: 'dev'
storage:
host: '127.0.0.1'
host: '0.0.0.0'
port: 5890
timeOut: 2 # second
@ -52,7 +52,7 @@ plugins-control:
plugins-infos-context: ["mock-plugins"]
gateway:
host: '127.0.0.1'
host: '0.0.0.0'
port: 5891
target: ["127.0.0.1:5890"]

2
doc/_icon/alf.svg Normal file
View File

@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="94" height="20" role="img" aria-label="license: AFL3.0"><title>license: AFL3.0</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="94" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="47" height="20" fill="#555"/><rect x="47" width="47" height="20" fill="#97ca00"/><rect width="94" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">license</text><text x="245" y="140" transform="scale(.1)" fill="#fff" textLength="370">license</text><text aria-hidden="true" x="695" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">AFL3.0</text><text x="695" y="140" transform="scale(.1)" fill="#fff" textLength="370">AFL3.0</text></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

2
doc/_icon/cache.svg Normal file
View File

@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="88" height="20" role="img" aria-label="Wheat: Cache"><title>Wheat: Cache</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="88" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="45" height="20" fill="#555"/><rect x="45" width="43" height="20" fill="#a4a61d"/><rect width="88" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="235" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">Wheat</text><text x="235" y="140" transform="scale(.1)" fill="#fff" textLength="350">Wheat</text><text aria-hidden="true" x="655" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">Cache</text><text x="655" y="140" transform="scale(.1)" fill="#fff" textLength="330">Cache</text></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

3
doc/_icon/event.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.9 KiB

2
doc/_icon/version.svg Normal file
View File

@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20" role="img" aria-label="version: v1.1"><title>version: v1.1</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="51" height="20" fill="#555"/><rect x="51" width="35" height="20" fill="#007ec6"/><rect width="86" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="265" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="410">version</text><text x="265" y="140" transform="scale(.1)" fill="#fff" textLength="410">version</text><text aria-hidden="true" x="675" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="250">v1.1</text><text x="675" y="140" transform="scale(.1)" fill="#fff" textLength="250">v1.1</text></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,13 @@
### 事件驱动 2.0
### event 1.0 存在的问题
事件驱动 1.0 在 相互关联访问时,会发生 死锁问题, 导致一个事件执行周期失败
### event 2.0 新特性
- 异步事件支持
- 挂起操作
### event 2.0 设计图
![](../../_icon/event.svg)

View File

@ -1,6 +1,15 @@
### 快速进行 storage 开发
#### 开发环境
- ubuntu18, 可以使用 wsl
- go1.15+, python3
- jinja2
- go mod
- protobuf 3.17.3
- protoc-gen-go v1.26.0
#### storage 执行流程
![](../_icon/storage-dao.svg)
#### 分层,简介
```sh
.
@ -27,6 +36,8 @@
#### 快速开发接口
> [快速开发视频 blibli](https://www.bilibili.com/video/BV1HL4y1v7ps)
1. 修改 temp/tem.yaml 文件,添加新接口
2. 在项目根目录执行 `make dcgen` 生成 proto 原始结构
3. 修改对应新添加接口的 proto 文件,再次执行 `make dcgen` 完成 proto 迁移

View File

@ -7,9 +7,9 @@ package dao
import (
"testing"
_ "gitee.com/timedb/wheatCache/conf"
"gitee.com/timedb/wheatCache/pkg/lru"
"gitee.com/timedb/wheatCache/pkg/proto"
_ "gitee.com/wheat-os/wheatCache/conf"
"gitee.com/wheat-os/wheatCache/pkg/lru"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/stretchr/testify/require"
)

View File

@ -4,12 +4,12 @@ import (
"fmt"
"net"
_ "gitee.com/timedb/wheatCache/conf"
wheatCodec "gitee.com/timedb/wheatCache/gateway/codec"
"gitee.com/timedb/wheatCache/gateway/proxy"
"gitee.com/timedb/wheatCache/gateway/transport"
"gitee.com/timedb/wheatCache/pkg/logx"
"gitee.com/timedb/wheatCache/pkg/util/server"
_ "gitee.com/wheat-os/wheatCache/conf"
wheatCodec "gitee.com/wheat-os/wheatCache/gateway/codec"
"gitee.com/wheat-os/wheatCache/gateway/endpoint"
"gitee.com/wheat-os/wheatCache/gateway/proxy"
"gitee.com/wheat-os/wheatCache/pkg/logx"
"gitee.com/wheat-os/wheatCache/pkg/util/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"google.golang.org/grpc"
@ -56,13 +56,13 @@ func GetGatewayServer() *grpc.Server {
logx.Debug("service target in %v", targets)
stream := proxy.GetDirectorByServiceHash()
transport := transport.NewHashTransport(transport.HashReplicasDefault, nil, targets...)
endpoint := endpoint.NewHashEndpoint(endpoint.HashReplicasDefault, nil, targets...)
opts := make([]grpc.ServerOption, 0)
opts = append(
opts,
grpc.ForceServerCodec(wheatCodec.Codec()),
grpc.UnknownServiceHandler(proxy.TransparentHandler(stream, transport)),
grpc.UnknownServiceHandler(proxy.TransparentHandler(stream, endpoint)),
)
return grpc.NewServer(opts...)

View File

@ -1,6 +1,6 @@
package transport
package endpoint
type TransPortInterface interface {
type EndpointInterface interface {
GetTargetAddr(...string) (string, error)
IsEmpty() bool
AddTarget(targets ...string)

View File

@ -1,11 +1,11 @@
package transport
package endpoint
import (
"hash/crc32"
"sort"
"strconv"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
)
type HashFunc func(data []byte) uint32
@ -25,34 +25,34 @@ func (s UInt32Slice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
type HashTransport struct {
type HashEndpoint struct {
hash HashFunc
replicas int // 复制因子
keys UInt32Slice
hashMap map[uint32]string // taraget 隐射
}
func NewHashTransport(replicas int, fn HashFunc, target ...string) TransPortInterface {
transport := &HashTransport{
func NewHashEndpoint(replicas int, fn HashFunc, target ...string) EndpointInterface {
endpoint := &HashEndpoint{
replicas: replicas,
hash: fn,
hashMap: make(map[uint32]string, len(target)),
}
if transport.hash == nil {
transport.hash = crc32.ChecksumIEEE // 默认使用 CRC32 算法
if endpoint.hash == nil {
endpoint.hash = crc32.ChecksumIEEE // 默认使用 CRC32 算法
}
transport.AddTarget(target...)
endpoint.AddTarget(target...)
return transport
return endpoint
}
func (h *HashTransport) IsEmpty() bool {
func (h *HashEndpoint) IsEmpty() bool {
return len(h.keys) == 0
}
func (h *HashTransport) AddTarget(targets ...string) {
func (h *HashEndpoint) AddTarget(targets ...string) {
for _, tar := range targets {
for i := 0; i < h.replicas; i++ {
@ -66,7 +66,7 @@ func (h *HashTransport) AddTarget(targets ...string) {
sort.Sort(h.keys)
}
func (h *HashTransport) GetTargetAddr(str ...string) (string, error) {
func (h *HashEndpoint) GetTargetAddr(str ...string) (string, error) {
if h.IsEmpty() {
return "", errorx.New("gateway not register transport")
}

View File

@ -1,4 +1,4 @@
package transport
package endpoint
import (
"testing"
@ -7,7 +7,7 @@ import (
)
func TestHashTransport_GetTargetAddr(t *testing.T) {
tran := NewHashTransport(3, nil, "127.0.0.1:5581", "127.0.0.1:5582", "127.0.0.1:5583")
tran := NewHashEndpoint(3, nil, "127.0.0.1:5581", "127.0.0.1:5582", "127.0.0.1:5583")
key := "test"

View File

@ -1,21 +1,6 @@
/*
Copyright © 2021 NAME HERE <EMAIL ADDRESS>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import "gitee.com/timedb/wheatCache/gateway/cmd"
import "gitee.com/wheat-os/wheatCache/gateway/cmd"
func main() {
cmd.Execute()

View File

@ -3,11 +3,11 @@ package proxy
import (
"context"
"gitee.com/timedb/wheatCache/gateway/transport"
"gitee.com/wheat-os/wheatCache/gateway/endpoint"
"google.golang.org/grpc"
)
type StreamDirector func(ctx context.Context, fullMethodName string, transport transport.TransPortInterface) (context.Context, *grpc.ClientConn, error)
type StreamDirector func(ctx context.Context, fullMethodName string, endpoint endpoint.EndpointInterface) (context.Context, *grpc.ClientConn, error)
var (
clientStreamDescForProxying = &grpc.StreamDesc{

View File

@ -3,9 +3,9 @@ package proxy
import (
"context"
"gitee.com/timedb/wheatCache/gateway/codec"
"gitee.com/timedb/wheatCache/gateway/transport"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/gateway/codec"
"gitee.com/wheat-os/wheatCache/gateway/endpoint"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
@ -13,7 +13,7 @@ import (
)
func GetDirectorByServiceHash() StreamDirector {
return func(ctx context.Context, fullMethodName string, transport transport.TransPortInterface) (context.Context, *grpc.ClientConn, error) {
return func(ctx context.Context, fullMethodName string, endpoint endpoint.EndpointInterface) (context.Context, *grpc.ClientConn, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
@ -26,7 +26,7 @@ func GetDirectorByServiceHash() StreamDirector {
"grpc header is not found %s, please check the client interceptor", proto.BaseKeyMethodKey)
}
target, err := transport.GetTargetAddr(baseKey...)
target, err := endpoint.GetTargetAddr(baseKey...)
if err != nil {
return nil, nil, status.Errorf(codes.Unknown, "get transport err, err:%v", err)
}

View File

@ -4,8 +4,8 @@ import (
"context"
"io"
wheatCodec "gitee.com/timedb/wheatCache/gateway/codec"
"gitee.com/timedb/wheatCache/gateway/transport"
wheatCodec "gitee.com/wheat-os/wheatCache/gateway/codec"
"gitee.com/wheat-os/wheatCache/gateway/endpoint"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@ -16,17 +16,17 @@ import (
// backends. It should be used as a `grpc.UnknownServiceHandler`.
//
// This can *only* be used if the `server` also uses grpcproxy.CodecForServer() ServerOption.
func TransparentHandler(director StreamDirector, tranport transport.TransPortInterface) grpc.StreamHandler {
func TransparentHandler(director StreamDirector, endpoint endpoint.EndpointInterface) grpc.StreamHandler {
streamer := &handler{
director,
tranport,
endpoint,
}
return streamer.handler
}
type handler struct {
director StreamDirector
transport transport.TransPortInterface
director StreamDirector
endpoint endpoint.EndpointInterface
}
// handler is where the real magic of proxying happens.
@ -38,7 +38,7 @@ func (s *handler) handler(srv interface{}, serverStream grpc.ServerStream) error
return status.Errorf(codes.Internal, "lowLevelServerStream not exists in context")
}
outgoingCtx, backendConn, err := s.director(serverStream.Context(), fullMethodName, s.transport)
outgoingCtx, backendConn, err := s.director(serverStream.Context(), fullMethodName, s.endpoint)
if err != nil {
return err
}

3
go.mod
View File

@ -1,8 +1,9 @@
module gitee.com/timedb/wheatCache
module gitee.com/wheat-os/wheatCache
go 1.16
require (
github.com/golang/mock v1.5.0
github.com/spf13/cobra v1.2.1
github.com/spf13/viper v1.8.1
github.com/stretchr/testify v1.7.0

1
go.sum
View File

@ -89,6 +89,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=

View File

@ -52,3 +52,7 @@ init-conf:
.PHONY: gen-service
gen-service:
@python3 ./shell/make_service.py
.PHONY: gen-mock
gen-mock:
@mockgen -source=./pkg/proto/storage.pb.go CommServerClient > ./mock/storage/mock_client.gen.go

File diff suppressed because it is too large Load Diff

5
pkg/errorx/event.go Normal file
View File

@ -0,0 +1,5 @@
package errorx
func EventRecoveryErr() error {
return New("this event has been recycled")
}

View File

@ -5,5 +5,5 @@ func LruNotWorkFuncEventErr() error {
}
func KeyBaseIsNilErr() error {
return New("key base not is nil")
return New("key base can't be nil")
}

View File

@ -4,7 +4,7 @@ import (
"sync/atomic"
"time"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
)
// 事件 poll 降低 new 对象的频率

21
pkg/event2/consumer.go Normal file
View File

@ -0,0 +1,21 @@
package event2
import "context"
type Consumer struct {
driver DriverInterface
}
func (c *Consumer) Receive(ctx context.Context) *event {
return c.driver.Get()
}
func (c *Consumer) NewEvent(name string) *event {
return c.driver.NewEvent(name)
}
func NewConsumer(driver DriverInterface) ConsumerInterface {
return &Consumer{
driver: driver,
}
}

49
pkg/event2/define.go Normal file
View File

@ -0,0 +1,49 @@
package event2
import (
"context"
)
const (
initEventState = int32(iota) // 初始化状态
waitEventState // 等待状态
workEventState // 工作状态
closeEventState // 事件关闭状态
recoveryEventState // 事件回收状态
)
const (
awaitThread = 3
)
const (
WorkFuncEventKey = "workFunc"
)
// 线程安全
type EventWorkFunc func() (interface{}, error)
// 挂起事件, 线程不安全
type EventAwaitFunc func() (interface{}, error)
// 实际操作
type awaitFunc func() (*event, interface{}, error)
type DriverInterface interface {
Get() *event
Put(*event)
GetLength() int
NewEvent(string) *event
await(awaitFunc)
recovery(e *event)
}
type ProduceInterface interface {
Call(context.Context, *event)
NewEvent(string) *event
}
type ConsumerInterface interface {
Receive(ctx context.Context) *event
}

221
pkg/event2/driver.go Normal file
View File

@ -0,0 +1,221 @@
package event2
import (
"sync/atomic"
"time"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
)
type event struct {
msgCtx map[string]interface{}
eventName string
msg map[string]string // 消息
waitResult chan interface{} // 等待返回
err error
eventStatus int32
ttlManage *time.Timer
parentDriver DriverInterface
}
func (e *event) reset() {
if e.ttlManage != nil {
e.ttlManage.Stop()
if len(e.ttlManage.C) > 0 {
<-e.ttlManage.C
}
}
e.err = nil
// 清空结果
if len(e.waitResult) != 0 {
<-e.waitResult
}
}
func (e *event) Recovery() {
e.parentDriver.recovery(e)
}
func (e *event) SetMsg(key string, val string) {
if e.msg == nil {
e.msg = make(map[string]string)
}
e.msg[key] = val
}
func (e *event) GetMsg(key string) string {
if e.msg == nil {
return ""
}
return e.msg[key]
}
func (e *event) GetEventName() string {
return e.eventName
}
// SetValue 写入 ctx 传递用参数
func (e *event) SetValue(key string, value interface{}) {
if e.msgCtx == nil {
e.msgCtx = make(map[string]interface{})
}
e.msgCtx[key] = value
}
func (e *event) GetValue(key string) (interface{}, bool) {
if e.msgCtx == nil {
return nil, false
}
val, ok := e.msgCtx[key]
return val, ok
}
func (e *event) InitWaitEvent() {
e.reset()
if e.waitResult == nil {
e.waitResult = make(chan interface{})
}
atomic.SwapInt32(&e.eventStatus, waitEventState)
}
func (e *event) SetResultErr(err error) {
if !atomic.CompareAndSwapInt32(&e.eventStatus, waitEventState, workEventState) {
return
}
e.err = err
e.waitResult <- nil
}
// StartWaitEvent 开始一个等待任务
func (e *event) StartWaitEvent(ttl time.Duration) (interface{}, error) {
if e.ttlManage == nil {
e.ttlManage = time.NewTimer(ttl)
} else {
e.ttlManage.Reset(ttl)
}
for {
select {
case <-e.ttlManage.C:
if atomic.CompareAndSwapInt32(&e.eventStatus, waitEventState, closeEventState) {
return nil, errorx.TimeOutErr()
}
continue
case result := <-e.waitResult:
atomic.SwapInt32(&e.eventStatus, closeEventState)
return result, e.err
}
}
}
// 实际执行推送
func (e *event) execWorker(res interface{}, err error) {
switch work := res.(type) {
case EventAwaitFunc:
await := func() (*event, interface{}, error) {
result, err := work()
return e, result, err
}
e.parentDriver.await(await)
case EventWorkFunc:
e.InitWaitEvent()
e.SetValue(WorkFuncEventKey, work)
e.parentDriver.Put(e)
default:
e.err = err
e.waitResult <- res
}
}
func (e *event) ExecWorkAndSendResult(work EventWorkFunc) (interface{}, error) {
if !atomic.CompareAndSwapInt32(&e.eventStatus, waitEventState, workEventState) {
return nil, errorx.New("not wait status, exec err")
}
res, err := work()
e.execWorker(res, err)
return res, err
}
type driver struct {
waitQueue chan awaitFunc
eventQueue chan *event
levelQueue chan *event
// event 池的实现
poll chan *event
maxPoolSize int32
nowPoolSize int32
}
func NewDriver(maxSize int) DriverInterface {
d := &driver{
// pool
maxPoolSize: int32(maxSize),
nowPoolSize: 0,
poll: make(chan *event, maxSize),
// waitQueue 1/3 的挂起指标
waitQueue: make(chan awaitFunc, maxSize/3),
levelQueue: make(chan *event, maxSize/3),
eventQueue: make(chan *event, maxSize),
}
d.awaitWorker()
return d
}
func (d *driver) NewEvent(name string) *event {
issSize := atomic.LoadInt32(&d.nowPoolSize)
if issSize < d.maxPoolSize {
atomic.AddInt32(&d.nowPoolSize, 1)
return d.newEvent(name)
}
e := <-d.poll
e.eventName = name
return e
}
func (d *driver) newEvent(name string) *event {
status := initEventState
return &event{
eventStatus: status,
parentDriver: d,
eventName: name,
}
}
// 先尝试 level
func (d *driver) Get() *event {
if len(d.levelQueue) > 0 {
return <-d.levelQueue
}
return <-d.eventQueue
}
func (d *driver) Put(e *event) {
d.eventQueue <- e
}
func (d *driver) GetLength() int {
return len(d.eventQueue) + len(d.levelQueue)
}
func (d *driver) recovery(e *event) {
atomic.SwapInt32(&e.eventStatus, recoveryEventState)
e.reset()
d.poll <- e
}
// 挂起操作相关
func (d *driver) await(a awaitFunc) {
d.waitQueue <- a
}

152
pkg/event2/driver_test.go Normal file
View File

@ -0,0 +1,152 @@
package event2
import (
"context"
"fmt"
"strconv"
"sync"
"testing"
"time"
"github.com/stretchr/testify/require"
)
const testEvent = "1001"
const waitTestEvent = "1002"
// 简单的 单向 event 使用
func Test_EventDriver(t *testing.T) {
driver := NewDriver(2000)
produce := NewProduce(driver)
consumer := NewConsumer(driver)
ctx := context.Background()
wait := sync.WaitGroup{}
wait.Add(30000)
go func() {
for i := 0; i < 30000; i++ {
event := produce.NewEvent(testEvent)
event.SetMsg("k", strconv.Itoa(i))
produce.Call(ctx, event)
}
}()
go func() {
for {
event := consumer.Receive(ctx)
fmt.Println(event.GetMsg("k"))
event.Recovery()
wait.Done()
}
}()
wait.Wait()
}
// 双向 event
func Test_EventDriver_Tow_way(t *testing.T) {
ctx := context.Background()
driver := NewDriver(2000)
produce := NewProduce(driver)
consumer := NewConsumer(driver)
go func() {
for {
event := consumer.Receive(ctx)
work, ok := event.GetValue(WorkFuncEventKey)
if !ok {
panic("get work key err")
}
workFunc, ok := work.(EventWorkFunc)
if !ok {
panic("work func err")
}
_, err := event.ExecWorkAndSendResult(workFunc)
require.NoError(t, err)
}
}()
// 一般的 two-way 模式
for i := 0; i < 10000; i++ {
event := produce.NewEvent(waitTestEvent)
event.InitWaitEvent()
event.SetValue(WorkFuncEventKey, EventWorkFunc(func() (interface{}, error) {
return i + 1, nil
}))
produce.Call(ctx, event)
res, err := event.StartWaitEvent(2 * time.Second)
require.NoError(t, err)
require.Equal(t, res, i+1)
event.Recovery()
}
// 挂起模式2 秒左右的执行时间
group := sync.WaitGroup{}
group.Add(5)
for i := 0; i < 5; i++ {
go func(i int) {
event := produce.NewEvent(waitTestEvent)
event.InitWaitEvent()
event.SetValue(WorkFuncEventKey, EventWorkFunc(func() (interface{}, error) {
// 访问 await Work 来发起一个 异步请求操作
return EventAwaitFunc(func() (interface{}, error) {
time.Sleep(time.Second)
return i + 1, nil
}), nil
}))
produce.Call(ctx, event)
res, err := event.StartWaitEvent(2 * time.Second)
require.NoError(t, err)
require.Equal(t, res, i+1)
event.Recovery()
group.Done()
}(i)
}
// 挂起成功不发生超时
for i := 0; i < 10000; i++ {
event := produce.NewEvent(waitTestEvent)
event.InitWaitEvent()
event.SetValue(WorkFuncEventKey, EventWorkFunc(func() (interface{}, error) {
return i + 1, nil
}))
produce.Call(ctx, event)
res, err := event.StartWaitEvent(500 * time.Millisecond)
require.NoError(t, err)
require.Equal(t, res, i+1)
event.Recovery()
}
group.Wait()
// 挂起一个高延迟操作, 保证局部操作还在事件中
group = sync.WaitGroup{}
group.Add(5)
for i := 0; i < 5; i++ {
event := produce.NewEvent(waitTestEvent)
event.InitWaitEvent()
event.SetValue(WorkFuncEventKey, EventWorkFunc(func() (interface{}, error) {
return EventAwaitFunc(func() (interface{}, error) {
// 返回值为 EventWorkFunc 时, 会重新加入末端队列
return EventWorkFunc(func() (interface{}, error) {
return i + 1, nil
}), nil
}), nil
}))
produce.Call(ctx, event)
res, err := event.StartWaitEvent(2 * time.Second)
require.NoError(t, err)
require.Equal(t, res, i+1)
event.Recovery()
group.Done()
fmt.Println(i)
}
group.Wait()
}

21
pkg/event2/produce.go Normal file
View File

@ -0,0 +1,21 @@
package event2
import "context"
type Produce struct {
driver DriverInterface
}
func (p *Produce) NewEvent(name string) *event {
return p.driver.NewEvent(name)
}
func (p *Produce) Call(ctx context.Context, e *event) {
p.driver.Put(e)
}
func NewProduce(driver DriverInterface) ProduceInterface {
return &Produce{
driver: driver,
}
}

13
pkg/event2/worker.go Normal file
View File

@ -0,0 +1,13 @@
package event2
func (d *driver) awaitWorker() {
for i := 0; i < awaitThread; i++ {
go func() {
for {
awaitFunc := <-d.waitQueue
e, res, err := awaitFunc()
e.execWorker(res, err)
}
}()
}
}

View File

@ -2,9 +2,10 @@ package logx
import (
"context"
"gitee.com/timedb/wheatCache/pkg/event"
"github.com/spf13/viper"
"sync"
"gitee.com/wheat-os/wheatCache/pkg/event"
"github.com/spf13/viper"
)
type LogLevelState int8

View File

@ -8,8 +8,8 @@ import (
"strings"
"time"
"gitee.com/timedb/wheatCache/pkg/event"
middleMsg "gitee.com/timedb/wheatCache/pkg/middle-msg"
"gitee.com/wheat-os/wheatCache/pkg/event"
middleMsg "gitee.com/wheat-os/wheatCache/pkg/middle-msg"
)
func With(ctx context.Context, p event.ProduceInterface) *upLogger {

View File

@ -2,9 +2,10 @@ package logx
import (
"context"
_ "gitee.com/timedb/wheatCache/conf"
"gitee.com/timedb/wheatCache/pkg/event"
"testing"
_ "gitee.com/wheat-os/wheatCache/conf"
"gitee.com/wheat-os/wheatCache/pkg/event"
)
func TestStd(t *testing.T) {

View File

@ -4,17 +4,16 @@ import (
"sync"
"time"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure"
)
type SingleWorkFunc func() interface{}
const (
OptionEventName = "operateEvent"
CleanEventName = "clearEvent"
TtlEventName = "ttlEvent"
WorkFuncEventKey = "workFunc"
OptionEventName = "operateEvent"
CleanEventName = "clearEvent"
TtlEventName = "ttlEvent"
)
var (

View File

@ -4,13 +4,14 @@ import (
"container/list"
"sync/atomic"
_ "gitee.com/timedb/wheatCache/conf"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/timedb/wheatCache/pkg/event"
"gitee.com/timedb/wheatCache/pkg/middle"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/structure"
"gitee.com/timedb/wheatCache/pkg/util"
_ "gitee.com/wheat-os/wheatCache/conf"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/event"
"gitee.com/wheat-os/wheatCache/pkg/event2"
"gitee.com/wheat-os/wheatCache/pkg/middle"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/util"
"github.com/spf13/viper"
)
@ -29,9 +30,9 @@ type SingleCache struct {
lruMaxDiverSize int
lruTtlManage *lruTTl // 定时清理器
lruDriver event.DriverInterface
lruConsumer event.ConsumerInterface
lruCleanProduce event.ProduceInterface // 发送清理事件
lruDriver event2.DriverInterface
lruConsumer event2.ConsumerInterface
lruCleanProduce event2.ProduceInterface // 发送清理事件
middleProduce event.ProduceInterface // 中间件驱动
}
@ -76,7 +77,7 @@ func cacheInit() (int64, int64, int, int) {
// NewLRUCache lru初始化
func NewLRUCache() *SingleCache {
maxSize, clearSize, maxDriverSize, detachNum := cacheInit()
lruDriver := event.NewDriver(maxDriverSize)
lruDriver := event2.NewDriver(maxDriverSize)
lruCacheOnce.Do(func() {
lru := &SingleCache{
maxsize: maxSize,
@ -86,8 +87,8 @@ func NewLRUCache() *SingleCache {
lruMap: make(map[string]*list.Element),
lruMaxDiverSize: maxDriverSize,
lruDriver: lruDriver,
lruConsumer: event.NewConsumer(lruDriver),
lruCleanProduce: event.NewProduce(lruDriver),
lruConsumer: event2.NewConsumer(lruDriver),
lruCleanProduce: event2.NewProduce(lruDriver),
middleProduce: event.NewProduce(middle.NewMiddleWare().GetEventDriver()),
lruTtlManage: newLruTTl(detachNum),
}
@ -103,7 +104,7 @@ func NewLRUCache() *SingleCache {
}
// GetDriver 获取驱动
func (lru *SingleCache) GetDriver() event.DriverInterface {
func (lru *SingleCache) GetDriver() event2.DriverInterface {
return lru.lruDriver
}
@ -122,6 +123,9 @@ func (lru *SingleCache) Add(key *proto.BaseKey, val structure.KeyBaseInterface)
}
if elVal, ok := lru.lruMap[key.Key]; ok {
lru.li.MoveToFront(elVal)
oldSize := elVal.Value.(structure.KeyBaseInterface).SizeByte()
lru.UpdateLruSize(structure.UpdateLength(val.SizeByte() - oldSize))
elVal.Value = keyBaseVal
return nil
}

View File

@ -5,8 +5,8 @@ import (
"testing"
"time"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/structure/stringx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure/stringx"
"github.com/stretchr/testify/require"
)

View File

@ -4,8 +4,8 @@ import (
"sync"
"time"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/util/skiplist"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/util/skiplist"
)
// lru 的 ttl 管理器
@ -20,6 +20,11 @@ func (l *lruTTl) setKeys(key *proto.BaseKey) int64 {
l.mu.Lock()
defer l.mu.Unlock()
// 永久存储
if key.Expire == nil && key.Ttl == 0 {
return 0
}
ttlTime := time.Now().Unix()
if key.Expire != nil {
ttlTime = key.Expire.GetSeconds()

View File

@ -5,8 +5,8 @@ import (
"testing"
"time"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/structure/stringx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure/stringx"
"github.com/stretchr/testify/require"
)

View File

@ -5,19 +5,19 @@ import (
"testing"
"time"
"gitee.com/timedb/wheatCache/pkg/event"
"gitee.com/timedb/wheatCache/pkg/logx"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/structure/stringx"
"gitee.com/wheat-os/wheatCache/pkg/event2"
"gitee.com/wheat-os/wheatCache/pkg/logx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure/stringx"
"github.com/stretchr/testify/require"
)
func TestWorker(t *testing.T) {
ctx := context.Background()
lru := NewLRUCache()
produce := event.NewProduce(lru.GetDriver())
produce := event2.NewProduce(lru.GetDriver())
workEvent := produce.NewEvent(OptionEventName)
workEvent.SetValue(WorkFuncEventKey, event.EventWorkFunc(func() (interface{}, error) {
workEvent.SetValue(event2.WorkFuncEventKey, event2.EventWorkFunc(func() (interface{}, error) {
v1 := stringx.NewStringSingle()
key := proto.BaseKey{
Key: "v1",
@ -36,11 +36,11 @@ func TestWorker(t *testing.T) {
func TestSingleCache_DelToClearSize(t *testing.T) {
ctx := context.Background()
lru := NewLRUCache()
produce := event.NewProduce(lru.GetDriver())
produce := event2.NewProduce(lru.GetDriver())
for i := int32(20000); i > 0; i-- {
workEvent := produce.NewEvent(OptionEventName)
workEvent.SetValue(WorkFuncEventKey, event.EventWorkFunc(func() (interface{}, error) {
workEvent.SetValue(event2.WorkFuncEventKey, event2.EventWorkFunc(func() (interface{}, error) {
v1 := stringx.NewStringSingle()
key := proto.BaseKey{
Key: string(i),
@ -53,7 +53,7 @@ func TestSingleCache_DelToClearSize(t *testing.T) {
workEvent.InitWaitEvent()
produce.Call(ctx, workEvent)
workEvent.StartWaitEvent(2 * time.Second)
produce.Recovery(workEvent)
workEvent.Recovery()
}
logx.Info("start size is %d", lru.nowSize)

View File

@ -4,17 +4,18 @@ import (
"context"
"time"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/timedb/wheatCache/pkg/event"
"gitee.com/timedb/wheatCache/pkg/logx"
mMsg "gitee.com/timedb/wheatCache/pkg/middle-msg"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/event"
"gitee.com/wheat-os/wheatCache/pkg/event2"
"gitee.com/wheat-os/wheatCache/pkg/logx"
mMsg "gitee.com/wheat-os/wheatCache/pkg/middle-msg"
)
func (lru *SingleCache) lruSingleWork() {
ctx := context.Background()
for {
workEvent := lru.lruConsumer.Receive(ctx)
workFunc, ok := workEvent.GetValue(WorkFuncEventKey)
workFunc, ok := workEvent.GetValue(event2.WorkFuncEventKey)
if !ok {
workEvent.SetResultErr(errorx.LruNotWorkFuncEventErr())
continue
@ -22,7 +23,7 @@ func (lru *SingleCache) lruSingleWork() {
switch workEvent.GetEventName() {
case OptionEventName:
if work, ok := workFunc.(event.EventWorkFunc); ok {
if work, ok := workFunc.(event2.EventWorkFunc); ok {
workEvent.ExecWorkAndSendResult(work)
}
@ -33,12 +34,12 @@ func (lru *SingleCache) lruSingleWork() {
lru.lruCleanProduce.Call(ctx, workEvent)
continue
}
if work, ok := workFunc.(event.EventWorkFunc); ok {
if work, ok := workFunc.(event2.EventWorkFunc); ok {
workEvent.ExecWorkAndSendResult(work)
}
case TtlEventName:
if work, ok := workFunc.(event.EventWorkFunc); ok {
if work, ok := workFunc.(event2.EventWorkFunc); ok {
workEvent.ExecWorkAndSendResult(work)
}
}
@ -52,7 +53,7 @@ func (lru *SingleCache) lruTtlWork() {
// 清理事件
go func() {
work := event.EventWorkFunc(func() (interface{}, error) {
work := event2.EventWorkFunc(func() (interface{}, error) {
beforeTime := time.Now().Unix()
cle := lru.lruTtlManage.detachNum
@ -80,12 +81,12 @@ func (lru *SingleCache) lruTtlWork() {
}
ttlEvent := lru.lruCleanProduce.NewEvent(TtlEventName)
ttlEvent.SetValue(WorkFuncEventKey, work)
ttlEvent.SetValue(event2.WorkFuncEventKey, work)
ttlEvent.InitWaitEvent()
lru.lruCleanProduce.Call(ctx, ttlEvent)
keys, err := ttlEvent.StartWaitEvent(time.Second * 2)
lru.lruCleanProduce.Recovery(ttlEvent)
ttlEvent.Recovery()
mMsg.SendMiddleMsg(ctx, lru.middleProduce, mMsg.LruTTlContext{
Keys: keys.([]string),
@ -118,7 +119,7 @@ func (lru *SingleCache) cleanWork() {
time.Sleep(2 * time.Second)
if lru.clearSize < lru.nowSize {
lruCleanEvent := lru.lruCleanProduce.NewEvent(CleanEventName)
lruCleanEvent.SetValue(WorkFuncEventKey, work)
lruCleanEvent.SetValue(event2.WorkFuncEventKey, work)
lruCleanEvent.InitWaitEvent()
lru.lruCleanProduce.Call(cxt, lruCleanEvent)
@ -128,7 +129,7 @@ func (lru *SingleCache) cleanWork() {
}
// 归还
lru.lruCleanProduce.Recovery(lruCleanEvent)
lruCleanEvent.Recovery()
}
}
}

View File

@ -3,8 +3,8 @@ package middlemsg
import (
"context"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/timedb/wheatCache/pkg/event"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/event"
)
const (

View File

@ -1,10 +1,10 @@
package middle
import (
_ "gitee.com/timedb/wheatCache/conf"
"gitee.com/timedb/wheatCache/pkg/event"
"gitee.com/timedb/wheatCache/plugins"
"gitee.com/timedb/wheatCache/plugins/config"
_ "gitee.com/wheat-os/wheatCache/conf"
"gitee.com/wheat-os/wheatCache/pkg/event"
"gitee.com/wheat-os/wheatCache/plugins"
"gitee.com/wheat-os/wheatCache/plugins/config"
"github.com/spf13/viper"
)

View File

@ -3,8 +3,8 @@ package middle
import (
"context"
"gitee.com/timedb/wheatCache/pkg/logx"
middleMsg "gitee.com/timedb/wheatCache/pkg/middle-msg"
"gitee.com/wheat-os/wheatCache/pkg/logx"
middleMsg "gitee.com/wheat-os/wheatCache/pkg/middle-msg"
)
func (m *MiddleWare) startWork() {

View File

@ -6,8 +6,8 @@ import (
"testing"
"time"
"gitee.com/timedb/wheatCache/pkg/event"
middleMsg "gitee.com/timedb/wheatCache/pkg/middle-msg"
"gitee.com/wheat-os/wheatCache/pkg/event"
middleMsg "gitee.com/wheat-os/wheatCache/pkg/middle-msg"
)
func Test_middleware_loadPlugins(t *testing.T) {

View File

@ -84,6 +84,44 @@ func (x *BaseKey) GetExpire() *timestamppb.Timestamp {
return nil
}
type External struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *External) Reset() {
*x = External{}
if protoimpl.UnsafeEnabled {
mi := &file_base_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *External) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*External) ProtoMessage() {}
func (x *External) ProtoReflect() protoreflect.Message {
mi := &file_base_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use External.ProtoReflect.Descriptor instead.
func (*External) Descriptor() ([]byte, []int) {
return file_base_proto_rawDescGZIP(), []int{1}
}
var File_base_proto protoreflect.FileDescriptor
var file_base_proto_rawDesc = []byte{
@ -96,8 +134,9 @@ var file_base_proto_rawDesc = []byte{
0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65,
0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x22, 0x0a, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x42, 0x0b, 0x5a, 0x09,
0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
@ -112,13 +151,14 @@ func file_base_proto_rawDescGZIP() []byte {
return file_base_proto_rawDescData
}
var file_base_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_base_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_base_proto_goTypes = []interface{}{
(*BaseKey)(nil), // 0: BaseKey
(*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp
(*External)(nil), // 1: External
(*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp
}
var file_base_proto_depIdxs = []int32{
1, // 0: BaseKey.expire:type_name -> google.protobuf.Timestamp
2, // 0: BaseKey.expire:type_name -> google.protobuf.Timestamp
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
@ -144,6 +184,18 @@ func file_base_proto_init() {
return nil
}
}
file_base_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*External); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -151,7 +203,7 @@ func file_base_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_base_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},

733
pkg/proto/channelx.pb.go Normal file
View File

@ -0,0 +1,733 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.17.3
// source: channelx.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type CPushRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key *BaseKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Value []string `protobuf:"bytes,2,rep,name=value,proto3" json:"value,omitempty"`
}
func (x *CPushRequest) Reset() {
*x = CPushRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CPushRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CPushRequest) ProtoMessage() {}
func (x *CPushRequest) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CPushRequest.ProtoReflect.Descriptor instead.
func (*CPushRequest) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{0}
}
func (x *CPushRequest) GetKey() *BaseKey {
if x != nil {
return x.Key
}
return nil
}
func (x *CPushRequest) GetValue() []string {
if x != nil {
return x.Value
}
return nil
}
type CPushResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
E *External `protobuf:"bytes,1,opt,name=e,proto3" json:"e,omitempty"`
}
func (x *CPushResponse) Reset() {
*x = CPushResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CPushResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CPushResponse) ProtoMessage() {}
func (x *CPushResponse) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CPushResponse.ProtoReflect.Descriptor instead.
func (*CPushResponse) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{1}
}
func (x *CPushResponse) GetE() *External {
if x != nil {
return x.E
}
return nil
}
type CPopRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key *BaseKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Count int32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
}
func (x *CPopRequest) Reset() {
*x = CPopRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CPopRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CPopRequest) ProtoMessage() {}
func (x *CPopRequest) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CPopRequest.ProtoReflect.Descriptor instead.
func (*CPopRequest) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{2}
}
func (x *CPopRequest) GetKey() *BaseKey {
if x != nil {
return x.Key
}
return nil
}
func (x *CPopRequest) GetCount() int32 {
if x != nil {
return x.Count
}
return 0
}
type CPopResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
E *External `protobuf:"bytes,1,opt,name=e,proto3" json:"e,omitempty"`
Result []string `protobuf:"bytes,2,rep,name=result,proto3" json:"result,omitempty"`
}
func (x *CPopResponse) Reset() {
*x = CPopResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CPopResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CPopResponse) ProtoMessage() {}
func (x *CPopResponse) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CPopResponse.ProtoReflect.Descriptor instead.
func (*CPopResponse) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{3}
}
func (x *CPopResponse) GetE() *External {
if x != nil {
return x.E
}
return nil
}
func (x *CPopResponse) GetResult() []string {
if x != nil {
return x.Result
}
return nil
}
type CMakeRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key *BaseKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Length int32 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"`
}
func (x *CMakeRequest) Reset() {
*x = CMakeRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CMakeRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CMakeRequest) ProtoMessage() {}
func (x *CMakeRequest) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CMakeRequest.ProtoReflect.Descriptor instead.
func (*CMakeRequest) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{4}
}
func (x *CMakeRequest) GetKey() *BaseKey {
if x != nil {
return x.Key
}
return nil
}
func (x *CMakeRequest) GetLength() int32 {
if x != nil {
return x.Length
}
return 0
}
type CMakeResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *CMakeResponse) Reset() {
*x = CMakeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CMakeResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CMakeResponse) ProtoMessage() {}
func (x *CMakeResponse) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CMakeResponse.ProtoReflect.Descriptor instead.
func (*CMakeResponse) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{5}
}
type CLenRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key *BaseKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (x *CLenRequest) Reset() {
*x = CLenRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CLenRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CLenRequest) ProtoMessage() {}
func (x *CLenRequest) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CLenRequest.ProtoReflect.Descriptor instead.
func (*CLenRequest) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{6}
}
func (x *CLenRequest) GetKey() *BaseKey {
if x != nil {
return x.Key
}
return nil
}
type CLenResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Length int32 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"`
}
func (x *CLenResponse) Reset() {
*x = CLenResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CLenResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CLenResponse) ProtoMessage() {}
func (x *CLenResponse) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CLenResponse.ProtoReflect.Descriptor instead.
func (*CLenResponse) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{7}
}
func (x *CLenResponse) GetLength() int32 {
if x != nil {
return x.Length
}
return 0
}
type CCleanRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key *BaseKey `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (x *CCleanRequest) Reset() {
*x = CCleanRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CCleanRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CCleanRequest) ProtoMessage() {}
func (x *CCleanRequest) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CCleanRequest.ProtoReflect.Descriptor instead.
func (*CCleanRequest) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{8}
}
func (x *CCleanRequest) GetKey() *BaseKey {
if x != nil {
return x.Key
}
return nil
}
type CCleanResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *CCleanResponse) Reset() {
*x = CCleanResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_channelx_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CCleanResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CCleanResponse) ProtoMessage() {}
func (x *CCleanResponse) ProtoReflect() protoreflect.Message {
mi := &file_channelx_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CCleanResponse.ProtoReflect.Descriptor instead.
func (*CCleanResponse) Descriptor() ([]byte, []int) {
return file_channelx_proto_rawDescGZIP(), []int{9}
}
var File_channelx_proto protoreflect.FileDescriptor
var file_channelx_proto_rawDesc = []byte{
0x0a, 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x1a, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x40, 0x0a, 0x0c,
0x43, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03,
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65,
0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x28,
0x0a, 0x0d, 0x43, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x17, 0x0a, 0x01, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x45, 0x78, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x01, 0x65, 0x22, 0x3f, 0x0a, 0x0b, 0x43, 0x50, 0x6f, 0x70,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01,
0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3f, 0x0a, 0x0c, 0x43, 0x50, 0x6f,
0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x01, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52,
0x01, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x03,
0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x42, 0x0a, 0x0c, 0x43, 0x4d,
0x61, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65,
0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x0f,
0x0a, 0x0d, 0x43, 0x4d, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x29, 0x0a, 0x0b, 0x43, 0x4c, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61,
0x73, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x26, 0x0a, 0x0c, 0x43, 0x4c,
0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65,
0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67,
0x74, 0x68, 0x22, 0x2b, 0x0a, 0x0d, 0x43, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22,
0x10, 0x0a, 0x0e, 0x43, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_channelx_proto_rawDescOnce sync.Once
file_channelx_proto_rawDescData = file_channelx_proto_rawDesc
)
func file_channelx_proto_rawDescGZIP() []byte {
file_channelx_proto_rawDescOnce.Do(func() {
file_channelx_proto_rawDescData = protoimpl.X.CompressGZIP(file_channelx_proto_rawDescData)
})
return file_channelx_proto_rawDescData
}
var file_channelx_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_channelx_proto_goTypes = []interface{}{
(*CPushRequest)(nil), // 0: CPushRequest
(*CPushResponse)(nil), // 1: CPushResponse
(*CPopRequest)(nil), // 2: CPopRequest
(*CPopResponse)(nil), // 3: CPopResponse
(*CMakeRequest)(nil), // 4: CMakeRequest
(*CMakeResponse)(nil), // 5: CMakeResponse
(*CLenRequest)(nil), // 6: CLenRequest
(*CLenResponse)(nil), // 7: CLenResponse
(*CCleanRequest)(nil), // 8: CCleanRequest
(*CCleanResponse)(nil), // 9: CCleanResponse
(*BaseKey)(nil), // 10: BaseKey
(*External)(nil), // 11: External
}
var file_channelx_proto_depIdxs = []int32{
10, // 0: CPushRequest.key:type_name -> BaseKey
11, // 1: CPushResponse.e:type_name -> External
10, // 2: CPopRequest.key:type_name -> BaseKey
11, // 3: CPopResponse.e:type_name -> External
10, // 4: CMakeRequest.key:type_name -> BaseKey
10, // 5: CLenRequest.key:type_name -> BaseKey
10, // 6: CCleanRequest.key:type_name -> BaseKey
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_channelx_proto_init() }
func file_channelx_proto_init() {
if File_channelx_proto != nil {
return
}
file_base_proto_init()
if !protoimpl.UnsafeEnabled {
file_channelx_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CPushRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CPushResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CPopRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CPopResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CMakeRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CMakeResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CLenRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CLenResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CCleanRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_channelx_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CCleanResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_channelx_proto_rawDesc,
NumEnums: 0,
NumMessages: 10,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_channelx_proto_goTypes,
DependencyIndexes: file_channelx_proto_depIdxs,
MessageInfos: file_channelx_proto_msgTypes,
}.Build()
File_channelx_proto = out.File
file_channelx_proto_rawDesc = nil
file_channelx_proto_goTypes = nil
file_channelx_proto_depIdxs = nil
}

View File

@ -15,7 +15,7 @@ const (
// NewBaseKey
// keyttlexpire
func NewBaseKey(key string, t ...int64) *BaseKey {
var expire *timestamppb.Timestamp
var expire *timestamppb.Timestamp = nil
var ttl int64
if len(t) > 1 {

1301
pkg/proto/hashx.pb.go Normal file

File diff suppressed because it is too large Load Diff

1913
pkg/proto/setx.pb.go Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -580,8 +580,6 @@ type SetBitResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Result string `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"`
}
func (x *SetBitResponse) Reset() {
@ -616,13 +614,6 @@ func (*SetBitResponse) Descriptor() ([]byte, []int) {
return file_stringx_proto_rawDescGZIP(), []int{11}
}
func (x *SetBitResponse) GetResult() string {
if x != nil {
return x.Result
}
return ""
}
type GetBitRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -1071,37 +1062,35 @@ var file_stringx_proto_rawDesc = []byte{
0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x02,
0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x66, 0x66,
0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x22,
0x28, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x42, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x41, 0x0a, 0x0d, 0x47, 0x65, 0x74,
0x42, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65,
0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x18,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x22, 0x22, 0x0a, 0x0e,
0x47, 0x65, 0x74, 0x42, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10,
0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x76, 0x61, 0x6c,
0x22, 0x55, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01,
0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x2a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x61,
0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x22, 0x3d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x76,
0x61, 0x6c, 0x22, 0x28, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x2b, 0x0a, 0x0d,
0x53, 0x74, 0x72, 0x4c, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a,
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73,
0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x28, 0x0a, 0x0e, 0x53, 0x74, 0x72,
0x4c, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c,
0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65, 0x6e,
0x67, 0x74, 0x68, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x10, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x42, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x41, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
0x0a, 0x05, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6f,
0x66, 0x66, 0x65, 0x72, 0x22, 0x22, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x74, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20,
0x01, 0x28, 0x08, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x55, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52,
0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b,
0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a,
0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22,
0x2a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3d, 0x0a, 0x0d, 0x47,
0x65, 0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03,
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65,
0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x28, 0x0a, 0x0e, 0x47, 0x65,
0x74, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06,
0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x22, 0x2b, 0x0a, 0x0d, 0x53, 0x74, 0x72, 0x4c, 0x65, 0x6e, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x08, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x22, 0x28, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x4c, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x42, 0x0b, 0x5a, 0x09, 0x70,
0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -0,0 +1,66 @@
package channelx
import (
"sync/atomic"
"gitee.com/wheat-os/wheatCache/pkg/structure"
)
type ChannelX struct {
channel chan *structure.Value
sizeByte int64
}
func MakeChannelX(length int) structure.ChannelXInterface {
return &ChannelX{
channel: make(chan *structure.Value, length),
sizeByte: 0,
}
}
func (c *ChannelX) SizeByte() int64 {
return c.sizeByte
}
// RollBack TODO 事务相关, V2 实现
func (c *ChannelX) RollBack() error {
panic("not implemented") // TODO: Implement
}
// Begin 事务相关, V2 实现
func (c *ChannelX) Begin() error {
panic("not implemented") // TODO: Implement
}
// Comment 事务相关, V2 实现
func (c *ChannelX) Comment() error {
panic("not implemented") // TODO: Implement
}
func (c *ChannelX) Encode() ([]byte, error) {
panic("not implemented") // TODO: Implement
}
func (c *ChannelX) Push(value string) structure.UpdateLength {
val := structure.NewValue(value)
up := val.GetSize()
c.channel <- val
atomic.AddInt64(&c.sizeByte, int64(up))
return structure.UpdateLength(up)
}
func (c *ChannelX) Pop() (string, structure.UpdateLength) {
val := <-c.channel
return val.ToString(), structure.UpdateLength(val.GetSize()) * -1
}
func (c *ChannelX) Length() int {
return len(c.channel)
}
func (c *ChannelX) Clean() structure.UpdateLength {
c.channel = make(chan *structure.Value, cap(c.channel))
up := c.sizeByte
c.sizeByte = 0
return structure.UpdateLength(up) * -1
}

View File

@ -0,0 +1,24 @@
package channelx
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestChannelX_Push(t *testing.T) {
c := MakeChannelX(10)
require.Equal(t, c.Length(), 0)
up := c.Push("111")
require.Equal(t, 24, int(up))
res, up := c.Pop()
require.Equal(t, -24, int(up))
require.Equal(t, res, "111")
up = c.Push("111")
c.Clean()
require.Equal(t, c.Length(), 0)
}

View File

@ -53,3 +53,25 @@ type ListXInterface interface {
Range(start, end int) ([]string, error)
Remove(value string, count int) (int, UpdateLength)
}
type HashXInterface interface {
KeyBaseInterface
Set(key string, val string) UpdateLength
Get(key string) (string, error)
Del(key string) (UpdateLength, error)
Key() []string
Value() []string
Item() map[string]string
Add(renewal int, key ...string) (int, []string, error) // 访问影响成功的结果
SetX(key string, val string) (bool, UpdateLength) // 不存在才插入
Length() int
Range(consur, count int, regex string) []string
}
type ChannelXInterface interface {
KeyBaseInterface
Push(value string) UpdateLength
Pop() (string, UpdateLength)
Length() int
Clean() UpdateLength
}

View File

@ -0,0 +1,157 @@
package hashx
import (
"regexp"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/structure"
)
type HashX map[string]*structure.Value
func NewHashXSingle() structure.HashXInterface {
return make(HashX)
}
func (h HashX) SizeByte() int64 {
var size int
for _, val := range h {
size += val.GetSize()
}
return int64(size)
}
// RollBack TODO 事务相关, V2 实现
func (h HashX) RollBack() error {
panic("not implemented") // TODO: Implement
}
// Begin 事务相关, V2 实现
func (h HashX) Begin() error {
panic("not implemented") // TODO: Implement
}
// Comment 事务相关, V2 实现
func (h HashX) Comment() error {
panic("not implemented") // TODO: Implement
}
func (h HashX) Encode() ([]byte, error) {
panic("not implemented") // TODO: Implement
}
func (h HashX) Set(key string, val string) structure.UpdateLength {
var Length structure.UpdateLength
if v, ok := h[key]; ok {
Length -= structure.UpdateLength(v.GetSize())
}
strVal := structure.NewValue(val)
h[key] = strVal
return Length + structure.UpdateLength(strVal.GetSize())
}
func (h HashX) Get(key string) (string, error) {
if v, ok := h[key]; ok {
return v.ToString(), nil
}
return "", errorx.New("this key does not exist in hashx, key:%s", key)
}
func (h HashX) Del(key string) (structure.UpdateLength, error) {
if v, ok := h[key]; ok {
delete(h, key)
return structure.UpdateLength(v.GetSize()), nil
}
return 0, errorx.New("this key does not exist in hashx, key:%s", key)
}
func (h HashX) Key() []string {
result := make([]string, 0, len(h))
for key := range h {
result = append(result, key)
}
return result
}
func (h HashX) Value() []string {
result := make([]string, 0, len(h))
for _, val := range h {
result = append(result, val.ToString())
}
return result
}
func (h HashX) Item() map[string]string {
result := make(map[string]string, len(h))
for key, val := range h {
result[key] = val.ToString()
}
return result
}
func (h HashX) Add(renewal int, keys ...string) (count int, result []string, err error) {
for _, key := range keys {
if v, ok := h[key]; ok {
res, err := v.Incr(int32(renewal))
if err != nil {
continue
}
count += 1
result = append(result, res)
}
}
return count, result, nil
}
func (h HashX) SetX(key string, val string) (bool, structure.UpdateLength) {
if _, ok := h[key]; ok {
return false, 0
}
strVal := structure.NewValue(val)
h[key] = strVal
return true, structure.UpdateLength(strVal.GetSize())
}
func (h HashX) Length() int {
return len(h)
}
func (h HashX) Range(consur, count int, regex string) []string {
var reComp *regexp.Regexp
if regex == "" {
reComp = nil
} else {
reComp = regexp.MustCompile(regex)
}
result := make([]string, 0)
for _, val := range h {
if consur > 0 {
consur--
continue
}
if count == 0 && count != -1 {
break
}
s := val.ToString()
if reComp == nil {
count--
result = append(result, s)
continue
}
if reComp.MatchString(s) {
count--
result = append(result, s)
}
}
return result
}

View File

@ -0,0 +1,113 @@
package hashx
import (
"fmt"
"reflect"
"regexp"
"testing"
"unsafe"
"github.com/stretchr/testify/require"
)
func TestHashX_Set_SetX(t *testing.T) {
h := NewHashXSingle()
h.Set("key", "opq")
res, err := h.Get("key")
require.NoError(t, err)
require.Equal(t, res, "opq")
b, _ := h.SetX("key", "opq")
require.Equal(t, b, false)
b, _ = h.SetX("key1", "opq")
require.Equal(t, b, true)
res, err = h.Get("key1")
require.NoError(t, err)
require.Equal(t, res, "opq")
}
func TestHashX_Del(t *testing.T) {
h := NewHashXSingle()
up := h.Set("key", "opq")
upu, err := h.Del("key")
require.NoError(t, err)
require.Equal(t, up, upu)
}
func TestHashX_Key(t *testing.T) {
h := NewHashXSingle()
h.Set("key", "opq")
h.Set("key1", "opq")
h.Set("key2", "opq")
require.Equal(t, h.Key(), []string{"key", "key1", "key2"})
}
func TestHashX_Value(t *testing.T) {
h := NewHashXSingle()
h.Set("key", "opq")
h.Set("key1", "opq")
h.Set("key2", "opq")
require.Equal(t, h.Value(), []string{"opq", "opq", "opq"})
}
func TestHashX_Add(t *testing.T) {
h := NewHashXSingle()
h.Set("1", "1")
c, res, err := h.Add(1, "1")
require.NoError(t, err)
require.Equal(t, c, 1)
require.Equal(t, res, []string{"2"})
s, err := h.Get("1")
require.NoError(t, err)
require.Equal(t, s, "2")
}
func Test_Pointer(t *testing.T) {
s := make([]int, 9, 20)
lens := *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(8)))
fmt.Println(lens, len(s))
mp := make(map[string]int)
mp["qcrao"] = 100
mp["stefno"] = 18
count := **(**uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(&mp)) + uintptr(16)))
fmt.Println(count, len(mp)) // 2
}
func string2bytes(s string) []byte {
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
result := reflect.SliceHeader{
Data: stringHeader.Data,
Len: stringHeader.Len,
Cap: stringHeader.Len,
}
return *(*[]byte)(unsafe.Pointer(&result))
}
func TestHashX_Range(t *testing.T) {
reComp := regexp.MustCompile("a.+")
require.True(t, reComp.MatchString("abbs"))
h := NewHashXSingle()
h.Set("abbs", "abbs")
h.Set("ppp", "ppp")
h.Set("accs", "accs")
result := h.Range(0, 3, "")
require.Len(t, result, 3)
result = h.Range(0, -1, "")
require.Len(t, result, 3)
result = h.Range(0, -1, "a.+")
require.Len(t, result, 2)
result = h.Range(1, -1, "a.+")
require.Len(t, result, 1)
}

View File

@ -1,8 +1,8 @@
package listx
import (
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/timedb/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/structure"
)
/*

View File

@ -1,10 +1,7 @@
package stringx
import (
"strconv"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/timedb/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/structure"
)
type StringSingle struct {
@ -51,32 +48,8 @@ func (s *StringSingle) Get() string {
return s.val.ToString()
}
func updateValueNotString(s *StringSingle, val int32) (string, error) {
switch s.val.GetDynamicType() {
case structure.DynamicNull:
s.val.SetInt(int64(val))
return strconv.Itoa(int(val)), nil
case structure.DynamicFloat:
f, err := s.val.ToFloat64()
if err != nil {
return "", err
}
s.val.SetFloat64(f + float64(val))
return strconv.FormatFloat(f+float64(val), 'f', 2, 64), nil
case structure.DynamicInt:
i, err := s.val.ToInt()
if err != nil {
return "", err
}
s.val.SetInt(int64(val) + i)
return strconv.Itoa(int(i + int64(val))), nil
default:
return "", errorx.New("string cannot perform add operations")
}
}
func (s *StringSingle) Add(renewal int32) (string, error) {
result, err := updateValueNotString(s, renewal)
result, err := s.val.Incr(renewal)
if err != nil {
return "", err
}
@ -84,7 +57,7 @@ func (s *StringSingle) Add(renewal int32) (string, error) {
}
func (s *StringSingle) Reduce(renewal int32) (string, error) {
result, err := updateValueNotString(s, -1*renewal)
result, err := s.val.Incr(-1 * renewal)
if err != nil {
return "", err
}

View File

@ -5,7 +5,7 @@ import (
"testing"
"unsafe"
"gitee.com/timedb/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/structure"
"github.com/stretchr/testify/require"
)

View File

@ -3,10 +3,11 @@ package structure
import (
"bytes"
"encoding/binary"
"fmt"
"math"
"strconv"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
)
// Value 提供一个基础的 动态类型
@ -147,41 +148,90 @@ func (v *Value) ChangeValueLength(f func()) UpdateLength {
func (v *Value) SetByte(offset int, val bool) {
v.onType = DynamicNull // 位图使用无类型
b := byte(0)
if val {
b = byte(1)
}
if v.length >= offset {
v.val[offset] = b
// 扩容
if len(v.val) <= offset/8 {
newByte := make([]byte, (offset/8)+1)
copy(newByte, v.val[:len(v.val)])
v.val = newByte
v.length = len(v.val)
}
if val {
// true 位
v.val[offset/8] |= (0b1 << (offset % 8))
return
}
newByte := make([]byte, offset+1)
newByte[offset] = b
copy(newByte, v.val[:v.length])
v.val = newByte
v.length = len(newByte)
// false 位
v.val[offset/8] ^= (0b1 << (offset % 8))
}
func (v *Value) GetByte(offset int) (bool, error) {
if v.length >= offset {
return v.val[offset] == byte(1), nil
if len(v.val) >= offset/8 {
// 采用 & 来运算 是否为 true
return v.val[offset/8]&(0b1<<(offset%8)) != 0, nil
}
return false, errorx.New("the maximum length is exceeded")
}
func (v *Value) SliceByString(start, end int) ([]byte, error) {
if v.onType != DynamicString {
return nil, errorx.New("not is string")
}
if start > end {
return nil, errorx.New("the end cannot be greater than the beginning")
}
if v.onType == DynamicInt {
ret, err := v.ToInt()
if err != nil {
return nil, err
}
value := strconv.Itoa(int(ret))
if end > len(value) {
return nil, errorx.New("the maximum index is exceeded, max index: %d", len(value))
}
return []byte(value[start:end]), nil
}
if v.onType == DynamicFloat {
ret, err := v.ToFloat64()
if err != nil {
return nil, err
}
value := fmt.Sprintf("%.2f", ret)
if end > len(value) {
return nil, errorx.New("the maximum index is exceeded, max index: %d", len(value))
}
return []byte(value[start:end]), nil
}
if end > v.length {
return nil, errorx.New("the maximum index is exceeded, max index: %d", v.length)
}
return v.val[start:end], nil
}
// 自增
func (v *Value) Incr(renewal int32) (string, error) {
switch v.GetDynamicType() {
case DynamicNull:
v.SetInt(int64(renewal))
return strconv.Itoa(int(renewal)), nil
case DynamicFloat:
f, err := v.ToFloat64()
if err != nil {
return "", err
}
v.SetFloat64(f + float64(renewal))
return strconv.FormatFloat(f+float64(renewal), 'f', 2, 64), nil
case DynamicInt:
i, err := v.ToInt()
if err != nil {
return "", err
}
v.SetInt(int64(renewal) + i)
return strconv.Itoa(int(i + int64(renewal))), nil
default:
return "", errorx.New("string cannot perform add operations")
}
}

View File

@ -1,6 +1,7 @@
package structure
import (
"fmt"
"strconv"
"testing"
@ -126,4 +127,20 @@ func TestValue_SetByte(t *testing.T) {
v, err = value.GetByte(10001)
require.NoError(t, err)
require.Equal(t, v, true)
require.Equal(t, value.GetSize(), (10001/8)+1+16)
}
func TestValue_SetByteWei(t *testing.T) {
k := make([]byte, 100)
offset := 700
k[offset/8] = 0b00000001
k[offset/8] |= 0b1 << (offset % 8)
fmt.Printf("%b\n", k[offset/8])
fmt.Printf("%v", (k[offset/8]&(0b1<<(offset%8))) != 0)
k[offset/8] ^= 0b1 << (offset % 8)
fmt.Printf("%v", (k[offset/8]&(0b1<<(offset%8))) != 0)
}

View File

@ -5,7 +5,7 @@ import (
"strconv"
"strings"
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
)
// ParseSizeToBit

View File

@ -5,7 +5,7 @@ import (
"os/signal"
"syscall"
"gitee.com/timedb/wheatCache/pkg/logx"
"gitee.com/wheat-os/wheatCache/pkg/logx"
"google.golang.org/grpc"
)

View File

@ -6,7 +6,7 @@ import (
"testing"
"time"
"gitee.com/timedb/wheatCache/pkg/logx"
"gitee.com/wheat-os/wheatCache/pkg/logx"
"github.com/stretchr/testify/require"
)

View File

@ -4,9 +4,9 @@
package config
import (
"gitee.com/timedb/wheatCache/plugins"
"gitee.com/wheat-os/wheatCache/plugins"
mockPlugin "gitee.com/timedb/wheatCache/plugins/mock-plugin"
mockPlugin "gitee.com/wheat-os/wheatCache/plugins/mock-plugin"
)
func GetMiddlewareMap() map[string]plugins.PluginInterface {

View File

@ -4,9 +4,9 @@
package config
import (
"gitee.com/timedb/wheatCache/plugins"
"gitee.com/wheat-os/wheatCache/plugins"
{%for dir in dirs %}
{{dir[0]}} "gitee.com/timedb/wheatCache/plugins/{{dir[1]}}"
{{dir[0]}} "gitee.com/wheat-os/wheatCache/plugins/{{dir[1]}}"
{%- endfor%}
)

View File

@ -5,8 +5,8 @@ import (
"net/http"
_ "net/http/pprof"
_ "gitee.com/timedb/wheatCache/conf"
"gitee.com/timedb/wheatCache/pkg/logx"
_ "gitee.com/wheat-os/wheatCache/conf"
"gitee.com/wheat-os/wheatCache/pkg/logx"
"github.com/spf13/viper"
)

View File

@ -7,4 +7,8 @@ message BaseKey {
string key = 1;
int64 ttl = 2;
google.protobuf.Timestamp expire = 3;
}
message External {
}

45
protobuf/channelx.proto Normal file
View File

@ -0,0 +1,45 @@
syntax = "proto3";
import "base.proto";
option go_package = "pkg/proto";
message CPushRequest {
BaseKey key = 1;
repeated string value = 2;
}
message CPushResponse {
External e = 1;
}
message CPopRequest {
BaseKey key = 1;
int32 count = 2;
}
message CPopResponse {
External e = 1;
repeated string result = 2;
}
message CMakeRequest {
BaseKey key = 1;
int32 length = 2;
}
message CMakeResponse {
}
message CLenRequest {
BaseKey key = 1;
}
message CLenResponse {
int32 length = 2;
}
message CCleanRequest {
BaseKey key = 1;
}
message CCleanResponse {
}

81
protobuf/hashx.proto Normal file
View File

@ -0,0 +1,81 @@
syntax = "proto3";
import "base.proto";
option go_package = "pkg/proto";
message HDelRequest {
BaseKey key = 1;
repeated string h_keys = 2;
}
message HDelResponse {
}
message HExistsRequest {
BaseKey key = 1;
string h_key = 2;
}
message HExistsResponse {
bool exists = 1;
}
message HGetRequest {
BaseKey key = 1;
repeated string h_keys = 2;
}
message HGetResponse {
map<string, string> items = 1;
}
message HGetAllRequest {
BaseKey key = 1;
}
message HGetAllResponse {
map<string, string> items = 1;
}
message HIncrByRequest {
BaseKey key = 1;
repeated string h_keys = 2;
int32 renewal = 3;
}
message HIncrByResponse {
int32 count = 1;
repeated string values = 2;
}
message HKeysRequest {
BaseKey key = 1;
}
message HKeysResponse {
repeated string keys = 1;
}
message HLenRequest {
BaseKey key = 1;
}
message HLenResponse {
int32 length = 1;
}
message HSetRequest {
BaseKey key = 1;
map<string, string> items = 2;
}
message HSetResponse {
}
message HSetXRequest {
BaseKey key = 1;
map<string, string> items = 2;
}
message HSetXResponse {
int32 count = 1;
}

126
protobuf/setx.proto Normal file
View File

@ -0,0 +1,126 @@
syntax = "proto3";
import "base.proto";
option go_package = "pkg/proto";
message SAddRequest {
BaseKey key = 1;
repeated string member = 2;
}
message SAddResponse {
}
message SCardRequest {
BaseKey key = 1;
}
message SCardResponse {
int32 length = 1;
}
message SDiffRequest {
BaseKey key = 1;
repeated string s_keys = 2;
}
message SDiffResponse {
External e = 1;
repeated string result = 2;
}
message SDiffStoreRequest {
BaseKey key = 1;
repeated string s_keys = 2;
string save_key = 3;
}
message SDiffStoreResponse {
External e = 1; // External
}
message SInterRequest {
BaseKey key = 1;
repeated string s_keys = 2;
}
message SInterResponse {
External e = 1;
repeated string result = 2;
}
message SInterStoreRequest {
BaseKey key = 1;
repeated string s_keys = 2;
string save_key = 3;
}
message SInterStoreResponse {
External e = 1;
}
message SIsMemberRequest {
BaseKey key = 1;
string member = 2;
}
message SIsMemberResponse {
bool exist = 1;
}
message SMoveRequest {
BaseKey key = 1;
string move_key = 2;
repeated string members = 3;
}
message SMoveResponse {
External e = 1;
}
message SPopRequest {
BaseKey key = 1;
int32 count = 2;
}
message SPopResponse {
repeated string members = 1;
}
message SRemRequest {
BaseKey key = 1;
int32 count = 2;
}
message SRemResponse {
}
message SUnionRequest {
BaseKey key = 1;
repeated string s_keys = 2;
}
message SUnionResponse {
External e = 1;
repeated string result = 2;
}
message SUnionStoreRequest {
BaseKey key = 1;
repeated string s_keys = 2;
string save_key = 3;
}
message SUnionStoreResponse {
External e = 1;
}
message SScanRequest {
BaseKey key = 1;
int32 cursor = 2;
string regexp = 3;
int32 count = 4;
}
message SScanResponse {
repeated string results = 1;
}

View File

@ -7,6 +7,9 @@ option go_package = "pkg/proto";
import "stringx.proto";
import "listx.proto";
import "hashx.proto";
import "setx.proto";
import "channelx.proto";
service CommServer {
@ -32,4 +35,31 @@ service CommServer {
rpc LTrim (LTrimRequest) returns (LTrimResponse);
rpc RPush (RPushRequest) returns (RPushResponse);
rpc RPushX (RPushXRequest) returns (RPushXResponse);
rpc HDel (HDelRequest) returns (HDelResponse);
rpc HExists (HExistsRequest) returns (HExistsResponse);
rpc HGet (HGetRequest) returns (HGetResponse);
rpc HGetAll (HGetAllRequest) returns (HGetAllResponse);
rpc HIncrBy (HIncrByRequest) returns (HIncrByResponse);
rpc HKeys (HKeysRequest) returns (HKeysResponse);
rpc HLen (HLenRequest) returns (HLenResponse);
rpc HSet (HSetRequest) returns (HSetResponse);
rpc HSetX (HSetXRequest) returns (HSetXResponse);
rpc SAdd (SAddRequest) returns (SAddResponse);
rpc SCard (SCardRequest) returns (SCardResponse);
rpc SDiff (SDiffRequest) returns (SDiffResponse);
rpc SDiffStore (SDiffStoreRequest) returns (SDiffStoreResponse);
rpc SInter (SInterRequest) returns (SInterResponse);
rpc SInterStore (SInterStoreRequest) returns (SInterStoreResponse);
rpc SIsMember (SIsMemberRequest) returns (SIsMemberResponse);
rpc SMove (SMoveRequest) returns (SMoveResponse);
rpc SPop (SPopRequest) returns (SPopResponse);
rpc SRem (SRemRequest) returns (SRemResponse);
rpc SUnion (SUnionRequest) returns (SUnionResponse);
rpc SUnionStore (SUnionStoreRequest) returns (SUnionStoreResponse);
rpc SScan (SScanRequest) returns (SScanResponse);
rpc CPush (CPushRequest) returns (CPushResponse);
rpc CPop (CPopRequest) returns (CPopResponse);
rpc CMake (CMakeRequest) returns (CMakeResponse);
rpc CLen (CLenRequest) returns (CLenResponse);
rpc CClean (CCleanRequest) returns (CCleanResponse);
}

View File

@ -53,7 +53,6 @@ message SetBitRequest {
}
message SetBitResponse {
string result = 2;
}
message GetBitRequest {

View File

@ -17,6 +17,7 @@ class ProtoOption(object):
self.method = method
self.option = []
self.ret = []
self.external = False
def add_option(self, opt: List[str]):
self.option.extend(opt)
@ -32,13 +33,17 @@ class ProtoOption(object):
def dist_to_ProOpt(req, resp) -> List[ProtoOption]:
def to_camel(val: str) -> str:
return "".join([k.capitalize() for k in val.split('_')])
def parse_type(l: str) -> List[str]:
l = l.strip()
if l == "":
return []
return [], False
opt = l.split(";")
result = []
f = False
for l_opt in opt:
l_opt = l_opt.strip()
l_list = l_opt.split()
@ -48,21 +53,34 @@ def dist_to_ProOpt(req, resp) -> List[ProtoOption]:
val = l_list[0]
if val == "BaseKey":
val = "*proto.BaseKey"
result.append([l_list[1].capitalize(), val])
result.append([to_camel(l_list[1]), val])
elif val == "repeated":
val = f"[]{l_list[1]}"
result.append([l_list[2].capitalize(), val])
result.append([to_camel(l_list[2]), val])
elif "map" in val:
resMap = re.findall(
r"^map\s*<(.*?)\s*,\s*(.*?)\s*>.*?(\w+).*?", l_opt)
if len(resMap[0]) == 3:
mapKey, mapVal, var = resMap[0]
result.append([to_camel(var), f"map[{mapKey}]{mapVal}"])
elif "External" in val:
f = True
else:
result.append([l_list[1].capitalize(), val])
return result
result.append([to_camel(l_list[1]), val])
return result, f
lists = []
for key, value in req.items():
p = ProtoOption(method=key)
p.add_option(parse_type(value))
p.add_ret(parse_type(resp.get(key, "")))
p.add_option(parse_type(value)[0])
ret, e = parse_type(resp.get(key, ""))
if e:
p.external = True
p.add_ret(ret)
lists.append(p)
return lists
@ -104,6 +122,7 @@ def load_protobuf() -> List[ProtoOption]:
li.extend(parse_protobuf_to_Opt(name))
return li
def go_fmt(path: str):
os.system(f"go fmt {path}")
@ -112,6 +131,7 @@ def load_template(name: str) -> str:
with open(f"{tempPath}/{name}", "r", encoding="utf-8") as fp:
return fp.read()
def gen_dao_interface(proto):
tem_text = load_template("dao.template")
@ -134,6 +154,7 @@ def gen_single_service(proto):
with open(temp_path, 'w', encoding='utf-8') as f:
f.write(text)
def gen_aof(proto):
tem_text = load_template("aof.template")
template = Template(tem_text)
@ -144,10 +165,23 @@ def gen_aof(proto):
with open(temp_path, 'w', encoding='utf-8') as f:
f.write(text)
# 生成 AOF 恢复机制
tem_text = load_template("dao_aof.template")
template = Template(tem_text)
text = template.render(keys=proto)
temp_path = f"{daoPath}/dao.gen.go"
with open(temp_path, 'w', encoding='utf-8') as f:
f.write(text)
def format_code_go():
go_fmt(f"{daoPath}/interface.gen.go")
go_fmt(f"{servicePath}/single_service.gen.go")
go_fmt(f"{aofPath}/codec.gen.go")
go_fmt(f"{daoPath}/dao.gen.go")
def main():
# 加载 protobuf
@ -163,5 +197,6 @@ def main():
gen_aof(protobuf)
format_code_go()
if __name__ == "__main__":
main()

View File

@ -17,6 +17,7 @@ def out_proto():
if err:
print(f, "-> out put err")
return os._exit(-1)
else:
print(f, "-> success")

View File

@ -6,12 +6,12 @@ import (
"log"
"net"
"gitee.com/timedb/wheatCache/storage/service"
"gitee.com/wheat-os/wheatCache/storage/service"
_ "gitee.com/timedb/wheatCache/conf"
"gitee.com/timedb/wheatCache/pkg/logx"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/util/server"
_ "gitee.com/wheat-os/wheatCache/conf"
"gitee.com/wheat-os/wheatCache/pkg/logx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/util/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"google.golang.org/grpc"

94
storage/dao/channelx.go Normal file
View File

@ -0,0 +1,94 @@
package dao
import (
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/event2"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/structure/channelx"
)
func (d *Dao) CPush(key *proto.BaseKey, Value []string) (interface{}, error) {
val, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
chanVal, ok := val.(structure.ChannelXInterface)
if !ok {
return nil, errorx.DaoTypeErr("channelx")
}
return event2.EventAwaitFunc(func() (interface{}, error) {
var sumUp structure.UpdateLength
for _, v := range Value {
sumUp += chanVal.Push(v)
}
d.lru.UpdateLruSize(sumUp)
return &proto.CPushResponse{}, nil
}), nil
}
func (d *Dao) CPop(key *proto.BaseKey, count int32) (interface{}, error) {
val, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
chanVal, ok := val.(structure.ChannelXInterface)
if !ok {
return nil, errorx.DaoTypeErr("channelx")
}
return event2.EventAwaitFunc(func() (interface{}, error) {
var sumUp structure.UpdateLength
result := make([]string, 0, count)
for i := int32(0); i < count; i++ {
v, up := chanVal.Pop()
sumUp += up
result = append(result, v)
}
d.lru.UpdateLruSize(sumUp)
return &proto.CPopResponse{Result: result}, nil
}), nil
}
func (d *Dao) CMake(key *proto.BaseKey, length int32) (*proto.CMakeResponse, error) {
chanVal := channelx.MakeChannelX(int(length))
err := d.lru.Add(key, chanVal)
if err != nil {
return nil, err
}
return &proto.CMakeResponse{}, nil
}
func (d *Dao) CLen(key *proto.BaseKey) (*proto.CLenResponse, error) {
val, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
chanVal, ok := val.(structure.ChannelXInterface)
if !ok {
return nil, errorx.DaoTypeErr("channelx")
}
return &proto.CLenResponse{Length: int32(chanVal.Length())}, nil
}
func (d *Dao) CClean(key *proto.BaseKey) (*proto.CCleanResponse, error) {
val, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
chanVal, ok := val.(structure.ChannelXInterface)
if !ok {
return nil, errorx.DaoTypeErr("channelx")
}
up := chanVal.Clean()
d.lru.UpdateLruSize(up)
return &proto.CCleanResponse{}, nil
}

View File

@ -0,0 +1,70 @@
package dao
import (
"strconv"
"testing"
"gitee.com/wheat-os/wheatCache/pkg/event2"
"gitee.com/wheat-os/wheatCache/pkg/lru"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/stretchr/testify/require"
)
func execWaitFunc(t *testing.T, work interface{}) (interface{}, error) {
wait, ok := work.(event2.EventAwaitFunc)
require.True(t, ok)
return wait()
}
func TestDao_CPush_CPop(t *testing.T) {
testBaseKey := proto.NewBaseKey("123")
l := lru.NewLRUCache()
dao := NewDao(l)
_, err := dao.CMake(testBaseKey, 200)
require.NoError(t, err)
wait, err := dao.CPush(testBaseKey, []string{"1", "2", "3"})
require.NoError(t, err)
waitFunc, ok := wait.(event2.EventAwaitFunc)
require.True(t, ok)
_, err = waitFunc()
require.NoError(t, err)
wait, err = dao.CPop(testBaseKey, 3)
require.NoError(t, err)
res, err := execWaitFunc(t, wait)
require.NoError(t, err)
require.Equal(t, res.(*proto.CPopResponse).Result, []string{"1", "2", "3"})
}
func TestDao_Async_Push(t *testing.T) {
testBaseKey := proto.NewBaseKey("123")
l := lru.NewLRUCache()
dao := NewDao(l)
_, err := dao.CMake(testBaseKey, 200)
require.NoError(t, err)
rq := make([]string, 0)
for i := 0; i < 300; i++ {
rq = append(rq, strconv.Itoa(i))
}
go func() {
wait, err := dao.CPush(testBaseKey, rq)
require.NoError(t, err)
_, err = execWaitFunc(t, wait)
require.NoError(t, err)
}()
wait, err := dao.CPop(testBaseKey, 300)
require.NoError(t, err)
resp, err := execWaitFunc(t, wait)
require.NoError(t, err)
require.Equal(t, resp.(*proto.CPopResponse).Result, rq)
}

176
storage/dao/dao.gen.go Normal file
View File

@ -0,0 +1,176 @@
// Code generated by gen-struct. DO NOT EDIT.
// make gen-service generated
package dao
import (
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/lru"
"gitee.com/wheat-os/wheatCache/pkg/proto"
protobuf "google.golang.org/protobuf/proto"
)
type Dao struct {
lru lru.CacheInterface
}
func NewDao(lru lru.CacheInterface) Interface {
return &Dao{
lru: lru,
}
}
// 执行 msg
func (d *Dao) ExecMessage(message protobuf.Message) error {
switch req := message.(type) {
case *proto.LIndexRequest:
_, err := d.LIndex(req.Key, req.Index)
return err
case *proto.LLenRequest:
_, err := d.LLen(req.Key)
return err
case *proto.LPopRequest:
_, err := d.LPop(req.Key, req.Count)
return err
case *proto.LPushRequest:
_, err := d.LPush(req.Key, req.Values)
return err
case *proto.LPushXRequest:
_, err := d.LPushX(req.Key, req.Values)
return err
case *proto.LRangeRequest:
_, err := d.LRange(req.Key, req.Start, req.End)
return err
case *proto.LRemRequest:
_, err := d.LRem(req.Key, req.Count, req.Value)
return err
case *proto.LSetRequest:
_, err := d.LSet(req.Key, req.Index, req.Value)
return err
case *proto.RPopRequest:
_, err := d.RPop(req.Key, req.Count)
return err
case *proto.LTrimRequest:
_, err := d.LTrim(req.Key, req.Start, req.End)
return err
case *proto.RPushRequest:
_, err := d.RPush(req.Key, req.Values)
return err
case *proto.RPushXRequest:
_, err := d.RPushX(req.Key, req.Values)
return err
case *proto.HDelRequest:
_, err := d.HDel(req.Key, req.HKeys)
return err
case *proto.HExistsRequest:
_, err := d.HExists(req.Key, req.HKey)
return err
case *proto.HGetRequest:
_, err := d.HGet(req.Key, req.HKeys)
return err
case *proto.HGetAllRequest:
_, err := d.HGetAll(req.Key)
return err
case *proto.HIncrByRequest:
_, err := d.HIncrBy(req.Key, req.HKeys, req.Renewal)
return err
case *proto.HKeysRequest:
_, err := d.HKeys(req.Key)
return err
case *proto.HLenRequest:
_, err := d.HLen(req.Key)
return err
case *proto.HSetRequest:
_, err := d.HSet(req.Key, req.Items)
return err
case *proto.HSetXRequest:
_, err := d.HSetX(req.Key, req.Items)
return err
case *proto.CPushRequest:
_, err := d.CPush(req.Key, req.Value)
return err
case *proto.CPopRequest:
_, err := d.CPop(req.Key, req.Count)
return err
case *proto.CMakeRequest:
_, err := d.CMake(req.Key, req.Length)
return err
case *proto.CLenRequest:
_, err := d.CLen(req.Key)
return err
case *proto.CCleanRequest:
_, err := d.CClean(req.Key)
return err
case *proto.SetRequest:
_, err := d.Set(req.Key, req.Val)
return err
case *proto.GetRequest:
_, err := d.Get(req.Key)
return err
case *proto.AddRequest:
_, err := d.Add(req.Key, req.Renewal)
return err
case *proto.ReduceRequest:
_, err := d.Reduce(req.Key, req.Renewal)
return err
case *proto.SetnxRequest:
_, err := d.Setnx(req.Key, req.Val)
return err
case *proto.SetBitRequest:
_, err := d.SetBit(req.Key, req.Val, req.Offer)
return err
case *proto.GetBitRequest:
_, err := d.GetBit(req.Key, req.Offer)
return err
case *proto.GetRangeRequest:
_, err := d.GetRange(req.Key, req.Start, req.End)
return err
case *proto.GetSetRequest:
_, err := d.GetSet(req.Key, req.Val)
return err
case *proto.StrLenRequest:
_, err := d.StrLen(req.Key)
return err
case *proto.SAddRequest:
_, err := d.SAdd(req.Key, req.Member)
return err
case *proto.SCardRequest:
_, err := d.SCard(req.Key)
return err
case *proto.SDiffRequest:
_, err := d.SDiff(req.Key, req.SKeys)
return err
case *proto.SDiffStoreRequest:
_, err := d.SDiffStore(req.Key, req.SKeys, req.SaveKey)
return err
case *proto.SInterRequest:
_, err := d.SInter(req.Key, req.SKeys)
return err
case *proto.SInterStoreRequest:
_, err := d.SInterStore(req.Key, req.SKeys, req.SaveKey)
return err
case *proto.SIsMemberRequest:
_, err := d.SIsMember(req.Key, req.Member)
return err
case *proto.SMoveRequest:
_, err := d.SMove(req.Key, req.MoveKey, req.Members)
return err
case *proto.SPopRequest:
_, err := d.SPop(req.Key, req.Count)
return err
case *proto.SRemRequest:
_, err := d.SRem(req.Key, req.Count)
return err
case *proto.SUnionRequest:
_, err := d.SUnion(req.Key, req.SKeys)
return err
case *proto.SUnionStoreRequest:
_, err := d.SUnionStore(req.Key, req.SKeys, req.SaveKey)
return err
case *proto.SScanRequest:
_, err := d.SScan(req.Key, req.Cursor, req.Regexp, req.Count)
return err
default:
return errorx.New("The type that is not registered exec err")
}
}

View File

@ -1,15 +0,0 @@
package dao
import (
"gitee.com/timedb/wheatCache/pkg/lru"
)
type Dao struct {
lru lru.CacheInterface
}
func NewDao(lru lru.CacheInterface) Interface {
return &Dao{
lru: lru,
}
}

View File

@ -1,5 +0,0 @@
package dao
import (
_ "gitee.com/timedb/wheatCache/conf"
)

169
storage/dao/hashx.go Normal file
View File

@ -0,0 +1,169 @@
package dao
import (
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/structure/hashx"
)
func (d *Dao) HDel(key *proto.BaseKey, hKeys []string) (*proto.HDelResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
for _, hK := range hKeys {
up, err := hashVal.Del(hK)
if err != nil {
return nil, err
}
d.lru.UpdateLruSize(up)
}
return &proto.HDelResponse{}, nil
}
func (d *Dao) HExists(key *proto.BaseKey, hKeys string) (*proto.HExistsResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
_, err := hashVal.Get(hKeys)
if err != nil {
return &proto.HExistsResponse{Exists: false}, nil
}
return &proto.HExistsResponse{Exists: true}, nil
}
func (d *Dao) HGet(key *proto.BaseKey, hKeys []string) (*proto.HGetResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
result := make(map[string]string)
for _, hK := range hKeys {
res, err := hashVal.Get(hK)
if err != nil {
return nil, err
}
result[hK] = res
}
return &proto.HGetResponse{Items: result}, nil
}
func (d *Dao) HGetAll(key *proto.BaseKey) (*proto.HGetAllResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
return &proto.HGetAllResponse{Items: hashVal.Item()}, nil
}
func (d *Dao) HIncrBy(key *proto.BaseKey, hKeys []string, renewal int32) (*proto.HIncrByResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
count, result, err := hashVal.Add(int(renewal), hKeys...)
return &proto.HIncrByResponse{
Count: int32(count),
Values: result,
}, err
}
func (d *Dao) HKeys(key *proto.BaseKey) (*proto.HKeysResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
return &proto.HKeysResponse{Keys: hashVal.Key()}, nil
}
func (d *Dao) HLen(key *proto.BaseKey) (*proto.HLenResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
return &proto.HLenResponse{Length: int32(hashVal.Length())}, nil
}
func (d *Dao) HSet(key *proto.BaseKey, set map[string]string) (*proto.HSetResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
hashVal := hashx.NewHashXSingle()
for k, v := range set {
hashVal.Set(k, v)
}
err := d.lru.Add(key, hashVal)
return &proto.HSetResponse{}, err
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
for k, v := range set {
upLength := hashVal.Set(k, v)
d.lru.UpdateLruSize(upLength)
}
return &proto.HSetResponse{}, nil
}
func (d *Dao) HSetX(key *proto.BaseKey, set map[string]string) (*proto.HSetXResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return &proto.HSetXResponse{}, errorx.NotKeyErr(key.Key)
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("hashx")
}
for k, v := range set {
upLength := hashVal.Set(k, v)
d.lru.UpdateLruSize(upLength)
}
return &proto.HSetXResponse{}, nil
}

160
storage/dao/hashx_test.go Normal file
View File

@ -0,0 +1,160 @@
package dao
import (
"testing"
"gitee.com/wheat-os/wheatCache/pkg/lru"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/stretchr/testify/require"
)
func initData(t *testing.T, key *proto.BaseKey, dao Interface) {
_, err := dao.HSet(key, map[string]string{
"test": "test",
"test1": "1",
"test2": "1.1",
})
require.NoError(t, err)
}
func TestDao_HSet(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
res, err := dao.HGet(baseKey, []string{"test", "test1"})
require.NoError(t, err)
require.Equal(t, res.Items, map[string]string{
"test": "test",
"test1": "1",
})
res, err = dao.HGet(baseKey, []string{"test", "test1", "test2"})
require.NoError(t, err)
require.Equal(t, res.Items, map[string]string{
"test": "test",
"test1": "1",
"test2": "1.10", // 默认2个小数点
})
}
func TestDao_HGet(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
res, err := dao.HGet(baseKey, []string{"test", "test1", "test2"})
require.NoError(t, err)
require.Equal(t, res.Items, map[string]string{
"test": "test",
"test1": "1",
"test2": "1.10", // 默认2个小数点
})
_, err = dao.HGet(baseKey, []string{"test", "test1", "test2", "a"})
require.Error(t, err)
}
func TestDao_HExists(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
resp, err := dao.HExists(baseKey, "test")
require.NoError(t, err)
require.Equal(t, resp.Exists, true)
resp, err = dao.HExists(baseKey, "kjd")
require.NoError(t, err)
require.Equal(t, resp.Exists, false)
}
func TestDao_HDel(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
_, err := dao.HDel(baseKey, []string{"test", "test1"})
require.NoError(t, err)
_, err = dao.HDel(baseKey, []string{"test"})
require.Error(t, err)
res, err := dao.HExists(baseKey, "test")
require.NoError(t, err)
require.Equal(t, res.Exists, false)
res, err = dao.HExists(baseKey, "test2")
require.NoError(t, err)
require.Equal(t, res.Exists, true)
}
func TestDao_HGetAll(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
resp, err := dao.HGetAll(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Items, map[string]string{
"test": "test",
"test1": "1",
"test2": "1.10",
})
}
func TestDao_HSetX(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
res, err := dao.HSetX(baseKey, map[string]string{
"test": "test",
"test1": "1",
"test2": "1.10", // 默认2个小数点
})
require.NoError(t, err)
require.Equal(t, res.Count, 0)
}
func TestDao_HLen(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
resp, err := dao.HLen(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Length, int32(3))
}
func TestDao_HKeys(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
res, err := dao.HKeys(baseKey)
require.NoError(t, err)
require.Equal(t, res.Keys, []string{"test", "test1", "test2"})
}
func TestDao_HIncrBy(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
initData(t, baseKey, dao)
resp, err := dao.HIncrBy(baseKey, []string{"test", "test1"}, 10)
require.NoError(t, err)
require.Equal(t, resp.Count, int32(1))
require.Equal(t, resp.Values, []string{"11"})
}

View File

@ -3,7 +3,10 @@
package dao
import "gitee.com/timedb/wheatCache/pkg/proto"
import (
"gitee.com/wheat-os/wheatCache/pkg/proto"
protobuf "google.golang.org/protobuf/proto"
)
type Interface interface {
LIndex(*proto.BaseKey, int32) (*proto.LIndexResponse, error)
@ -18,6 +21,20 @@ type Interface interface {
LTrim(*proto.BaseKey, int32, int32) (*proto.LTrimResponse, error)
RPush(*proto.BaseKey, []string) (*proto.RPushResponse, error)
RPushX(*proto.BaseKey, []string) (*proto.RPushXResponse, error)
HDel(*proto.BaseKey, []string) (*proto.HDelResponse, error)
HExists(*proto.BaseKey, string) (*proto.HExistsResponse, error)
HGet(*proto.BaseKey, []string) (*proto.HGetResponse, error)
HGetAll(*proto.BaseKey) (*proto.HGetAllResponse, error)
HIncrBy(*proto.BaseKey, []string, int32) (*proto.HIncrByResponse, error)
HKeys(*proto.BaseKey) (*proto.HKeysResponse, error)
HLen(*proto.BaseKey) (*proto.HLenResponse, error)
HSet(*proto.BaseKey, map[string]string) (*proto.HSetResponse, error)
HSetX(*proto.BaseKey, map[string]string) (*proto.HSetXResponse, error)
CPush(*proto.BaseKey, []string) (interface{}, error)
CPop(*proto.BaseKey, int32) (interface{}, error)
CMake(*proto.BaseKey, int32) (*proto.CMakeResponse, error)
CLen(*proto.BaseKey) (*proto.CLenResponse, error)
CClean(*proto.BaseKey) (*proto.CCleanResponse, error)
Set(*proto.BaseKey, string) (*proto.SetResponse, error)
Get(*proto.BaseKey) (*proto.GetResponse, error)
Add(*proto.BaseKey, int32) (*proto.AddResponse, error)
@ -28,4 +45,18 @@ type Interface interface {
GetRange(*proto.BaseKey, int32, int32) (*proto.GetRangeResponse, error)
GetSet(*proto.BaseKey, string) (*proto.GetSetResponse, error)
StrLen(*proto.BaseKey) (*proto.StrLenResponse, error)
SAdd(*proto.BaseKey, []string) (*proto.SAddResponse, error)
SCard(*proto.BaseKey) (*proto.SCardResponse, error)
SDiff(*proto.BaseKey, []string) (interface{}, error)
SDiffStore(*proto.BaseKey, []string, string) (interface{}, error)
SInter(*proto.BaseKey, []string) (interface{}, error)
SInterStore(*proto.BaseKey, []string, string) (interface{}, error)
SIsMember(*proto.BaseKey, string) (*proto.SIsMemberResponse, error)
SMove(*proto.BaseKey, string, []string) (interface{}, error)
SPop(*proto.BaseKey, int32) (*proto.SPopResponse, error)
SRem(*proto.BaseKey, int32) (*proto.SRemResponse, error)
SUnion(*proto.BaseKey, []string) (interface{}, error)
SUnionStore(*proto.BaseKey, []string, string) (interface{}, error)
SScan(*proto.BaseKey, int32, string, int32) (*proto.SScanResponse, error)
ExecMessage(message protobuf.Message) error
}

View File

@ -1,10 +1,10 @@
package dao
import (
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/structure"
"gitee.com/timedb/wheatCache/pkg/structure/listx"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/structure/listx"
)
func (d *Dao) LIndex(key *proto.BaseKey, index int32) (*proto.LIndexResponse, error) {

471
storage/dao/setx.go Normal file
View File

@ -0,0 +1,471 @@
package dao
import (
"context"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/event2"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/structure/hashx"
"gitee.com/wheat-os/wheatCache/storage/external"
)
func (d *Dao) SAdd(key *proto.BaseKey, setVal []string) (*proto.SAddResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
hashVal := hashx.NewHashXSingle()
for _, sv := range setVal {
hashVal.SetX(sv, sv)
}
d.lru.Add(key, hashVal)
return &proto.SAddResponse{}, nil
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
for _, sv := range setVal {
b, up := hashVal.SetX(sv, sv)
if b {
d.lru.UpdateLruSize(up)
}
}
return &proto.SAddResponse{}, nil
}
func (d *Dao) SCard(key *proto.BaseKey) (*proto.SCardResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
return &proto.SCardResponse{Length: int32(hashVal.Length())}, nil
}
func mathSDiff(masterItem []string, extKey []string) ([]string, error) {
cli, err := external.NewGatewayClient()
if err != nil {
return nil, err
}
m := make(map[string]struct{})
for _, bVal := range masterItem {
m[bVal] = struct{}{}
}
setItem := make([]string, 0, len(masterItem))
ctx := context.Background()
for _, sKey := range extKey {
baseKey := proto.NewBaseKey(sKey)
resp, err := cli.SScan(ctx, &proto.SScanRequest{
Key: baseKey,
Count: -1,
})
if err != nil {
continue
}
for _, item := range resp.Results {
if _, ok := m[item]; !ok {
setItem = append(setItem, item)
m[item] = struct{}{}
}
}
}
return setItem, nil
}
func (d *Dao) SDiff(key *proto.BaseKey, setKey []string) (interface{}, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
baseItem := hashVal.Key()
// await 挂起
return event2.EventAwaitFunc(func() (interface{}, error) {
setItem, err := mathSDiff(baseItem, setKey)
if err != nil {
return nil, err
}
return &proto.SDiffResponse{Result: setItem}, nil
}), nil
}
func (d *Dao) SDiffStore(key *proto.BaseKey, setKey []string, saveKey string) (interface{}, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
baseItem := hashVal.Key()
// await 挂起
return event2.EventAwaitFunc(func() (interface{}, error) {
setItem, err := mathSDiff(baseItem, setKey)
if err != nil {
return nil, err
}
cli, err := external.NewGatewayClient()
if err != nil {
return nil, err
}
ctx := context.Background()
_, err = cli.SAdd(ctx, &proto.SAddRequest{
Key: proto.NewBaseKey(saveKey),
Member: setItem,
})
if err != nil {
return nil, err
}
return &proto.SDiffStoreResponse{}, nil
}), nil
}
func mathSInter(masterItem []string, extKey []string) ([]string, error) {
cli, err := external.NewGatewayClient()
if err != nil {
return nil, err
}
m := make(map[string]struct{})
for _, bVal := range masterItem {
m[bVal] = struct{}{}
}
setItem := make([]string, 0, len(masterItem))
ctx := context.Background()
for _, sKey := range extKey {
resp, err := cli.SScan(ctx, &proto.SScanRequest{
Key: proto.NewBaseKey(sKey),
Count: -1,
})
if err != nil {
continue
}
for _, item := range resp.Results {
if _, ok := m[item]; ok {
setItem = append(setItem, item)
delete(m, item)
}
}
}
return setItem, nil
}
func (d *Dao) SInter(key *proto.BaseKey, setKey []string) (interface{}, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
baseItem := hashVal.Key()
// await 挂起
return event2.EventAwaitFunc(func() (interface{}, error) {
setItem, err := mathSInter(baseItem, setKey)
if err != nil {
return nil, err
}
return &proto.SInterResponse{Result: setItem}, nil
}), nil
}
func (d *Dao) SInterStore(key *proto.BaseKey, setKey []string, saveKey string) (interface{}, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
baseItem := hashVal.Key()
// await 挂起
return event2.EventAwaitFunc(func() (interface{}, error) {
setItem, err := mathSInter(baseItem, setKey)
if err != nil {
return nil, err
}
cli, err := external.NewGatewayClient()
if err != nil {
return nil, err
}
ctx := context.Background()
_, err = cli.SAdd(ctx, &proto.SAddRequest{
Key: proto.NewBaseKey(saveKey),
Member: setItem,
})
if err != nil {
return nil, err
}
return &proto.SInterStoreResponse{}, nil
}), nil
}
func (d *Dao) SIsMember(key *proto.BaseKey, member string) (*proto.SIsMemberResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
_, err := hashVal.Get(member)
if err != nil {
return &proto.SIsMemberResponse{Exist: false}, nil
}
return &proto.SIsMemberResponse{Exist: true}, nil
}
func (d *Dao) SMove(key *proto.BaseKey, moveKey string, members []string) (interface{}, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
moveMembers := make([]string, 0, len(members))
for _, member := range members {
up, err := hashVal.Del(member)
if err == nil {
d.lru.UpdateLruSize(up)
moveMembers = append(moveMembers, member)
}
}
return event2.EventAwaitFunc(func() (interface{}, error) {
cli, err := external.NewGatewayClient()
if err != nil {
return nil, err
}
ctx := context.Background()
_, err = cli.SAdd(ctx, &proto.SAddRequest{
Key: proto.NewBaseKey(moveKey),
Member: moveMembers,
})
if err != nil {
return nil, err
}
return &proto.SMoveResponse{}, nil
}), nil
}
func (d *Dao) SPop(key *proto.BaseKey, count int32) (*proto.SPopResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
members := make([]string, 0, count)
result := hashVal.Range(0, int(count), "")
for _, res := range result {
up, err := hashVal.Del(res)
if err != nil {
return nil, err
}
d.lru.UpdateLruSize(up)
members = append(members, res)
}
return &proto.SPopResponse{Members: members}, nil
}
func (d *Dao) SRem(key *proto.BaseKey, count int32) (*proto.SRemResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
result := hashVal.Range(0, int(count), "")
for _, res := range result {
up, err := hashVal.Del(res)
if err != nil {
return nil, err
}
d.lru.UpdateLruSize(up)
}
return &proto.SRemResponse{}, nil
}
func mathSUnion(masterItem []string, extKey []string) ([]string, error) {
cli, err := external.NewGatewayClient()
if err != nil {
return nil, err
}
m := make(map[string]struct{})
for _, bVal := range masterItem {
m[bVal] = struct{}{}
}
ctx := context.Background()
for _, sKey := range extKey {
resp, err := cli.SScan(ctx, &proto.SScanRequest{
Key: proto.NewBaseKey(sKey),
Count: -1,
})
if err != nil {
continue
}
for _, item := range resp.Results {
if _, ok := m[item]; !ok {
masterItem = append(masterItem, item)
m[item] = struct{}{}
}
}
}
return masterItem, nil
}
func (d *Dao) SUnion(key *proto.BaseKey, setKey []string) (interface{}, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
baseItem := hashVal.Key()
// await 挂起
return event2.EventAwaitFunc(func() (interface{}, error) {
setItem, err := mathSUnion(baseItem, setKey)
if err != nil {
return nil, err
}
return &proto.SUnionResponse{Result: setItem}, nil
}), nil
}
func (d *Dao) SUnionStore(key *proto.BaseKey, setKey []string, saveKey string) (interface{}, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
baseItem := hashVal.Key()
// await 挂起
return event2.EventAwaitFunc(func() (interface{}, error) {
setItem, err := mathSUnion(baseItem, setKey)
if err != nil {
return nil, err
}
cli, err := external.NewGatewayClient()
if err != nil {
return nil, err
}
ctx := context.Background()
_, err = cli.SAdd(ctx, &proto.SAddRequest{
Key: proto.NewBaseKey(saveKey),
Member: setItem,
})
if err != nil {
return nil, err
}
return &proto.SUnionStoreResponse{}, nil
}), nil
}
func (d *Dao) SScan(key *proto.BaseKey, cursor int32, regex string, count int32) (*proto.SScanResponse, error) {
value, ok := d.lru.Get(key)
if !ok {
return nil, errorx.KeyBaseIsNilErr()
}
hashVal, ok := value.(structure.HashXInterface)
if !ok {
return nil, errorx.DaoTypeErr("setx")
}
result := hashVal.Range(int(cursor), int(count), regex)
return &proto.SScanResponse{Results: result}, nil
}

386
storage/dao/setx_test.go Normal file
View File

@ -0,0 +1,386 @@
package dao
import (
"context"
"testing"
mockproto "gitee.com/wheat-os/wheatCache/mock/storage"
"gitee.com/wheat-os/wheatCache/pkg/event2"
"gitee.com/wheat-os/wheatCache/pkg/lru"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/storage/external"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
)
func TestDao_SAdd(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
_, err := dao.SAdd(baseKey, []string{"1", "2", "3"})
require.NoError(t, err)
res, err := dao.SPop(baseKey, 3)
require.NoError(t, err)
t.Log(res.Members)
require.Len(t, res.Members, 3)
}
func IsAdd(t *testing.T, baseKey *proto.BaseKey, dao Interface) {
_, err := dao.SAdd(baseKey, []string{"1", "2", "3", "4", "4"})
require.NoError(t, err)
}
func TestDao_SCard(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
IsAdd(t, baseKey, dao)
res, err := dao.SCard(baseKey)
require.NoError(t, err)
require.Equal(t, res.Length, int32(4))
}
func mockSScan(t *testing.T, ctrl *gomock.Controller) {
external.GateWayCtrl = ctrl
client, err := external.NewGatewayClient()
require.NoError(t, err)
mockCli, ok := client.(*mockproto.MockCommServerClient)
require.True(t, ok)
gomock.InOrder(
mockCli.EXPECT().SScan(gomock.Any(), gomock.Any()).Return(
&proto.SScanResponse{
Results: []string{"a", "b", "c"},
}, nil).MaxTimes(1),
mockCli.EXPECT().SScan(gomock.Any(), gomock.Any()).Return(
&proto.SScanResponse{
Results: []string{"1", "2", "3"},
}, nil).AnyTimes(),
mockCli.EXPECT().SScan(gomock.Any(), gomock.Any()).Return(
&proto.SScanResponse{
Results: []string{"1", "2", "4"},
}, nil).AnyTimes(),
mockCli.EXPECT().SScan(gomock.Any(), gomock.Any()).Return(
&proto.SScanResponse{
Results: []string{"99", "6", "1.20"},
}, nil).AnyTimes(),
)
}
func mockSAdd(t *testing.T, ctrl *gomock.Controller, dao Interface) {
external.GateWayCtrl = ctrl
client, err := external.NewGatewayClient()
require.NoError(t, err)
mockCli, ok := client.(*mockproto.MockCommServerClient)
require.True(t, ok)
execFunc := func(
ctx context.Context,
req *proto.SAddRequest,
) (*proto.SAddResponse, error) {
return dao.SAdd(req.Key, req.Member)
}
mockCli.EXPECT().SAdd(gomock.Any(), gomock.Any()).DoAndReturn(execFunc)
}
func TestDao_SDiff(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("diff")
_, err := dao.SAdd(baseKey, []string{"a", "b", "s"})
require.NoError(t, err)
// mock client
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSScan(t, ctrl)
wait, err := dao.SDiff(baseKey, []string{"opp"})
require.NoError(t, err)
waitWork, ok := wait.(event2.EventAwaitFunc)
require.True(t, ok)
resp, err := waitWork()
require.NoError(t, err)
res, ok := resp.(*proto.SDiffResponse)
require.True(t, ok)
require.Equal(t, res.Result, []string{"c"})
}
func TestDao_SDiffStore(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("diffStore")
storeKey := proto.NewBaseKey("apple")
_, err := dao.SAdd(baseKey, []string{"a", "b", "s"})
require.NoError(t, err)
// mock client
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSScan(t, ctrl)
// 必须调用一次 storage
mockSAdd(t, ctrl, dao)
wait, err := dao.SDiffStore(baseKey, []string{"opp", "oo2"}, storeKey.Key)
require.NoError(t, err)
waitWork, ok := wait.(event2.EventAwaitFunc)
require.True(t, ok)
resp, err := waitWork()
require.NoError(t, err)
_, ok = resp.(*proto.SDiffStoreResponse)
require.True(t, ok)
res, err := dao.SScan(storeKey, 0, "", -1)
require.NoError(t, err)
t.Log(res.Results)
require.Len(t, res.Results, 4)
}
func TestDao_SInter(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("inter")
_, err := dao.SAdd(baseKey, []string{"a", "b", "s"})
require.NoError(t, err)
// mock client
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSScan(t, ctrl)
wait, err := dao.SInter(baseKey, []string{"opp"})
require.NoError(t, err)
waitWork, ok := wait.(event2.EventAwaitFunc)
require.True(t, ok)
resp, err := waitWork()
require.NoError(t, err)
res, ok := resp.(*proto.SInterResponse)
require.True(t, ok)
require.Equal(t, res.Result, []string{"a", "b"})
}
func TestDao_SInterStore(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("interStore")
storeKey := proto.NewBaseKey("apple")
_, err := dao.SAdd(baseKey, []string{"a", "b", "s"})
require.NoError(t, err)
// mock client
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSScan(t, ctrl)
// 必须调用一次 storage
mockSAdd(t, ctrl, dao)
wait, err := dao.SInterStore(baseKey, []string{"opp", "oo2"}, storeKey.Key)
require.NoError(t, err)
waitWork, ok := wait.(event2.EventAwaitFunc)
require.True(t, ok)
resp, err := waitWork()
require.NoError(t, err)
_, ok = resp.(*proto.SInterStoreResponse)
require.True(t, ok)
res, err := dao.SScan(storeKey, 0, "", -1)
require.NoError(t, err)
t.Log(res.Results)
require.Len(t, res.Results, 2)
}
func TestDao_SIsMember(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
testKey := proto.NewBaseKey("testKey")
IsAdd(t, testKey, dao)
resp, err := dao.SIsMember(testKey, "1")
require.NoError(t, err)
require.Equal(t, resp.Exist, true)
resp, err = dao.SIsMember(testKey, "6")
require.NoError(t, err)
require.Equal(t, resp.Exist, false)
}
func TestDao_SMove(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
testKey := proto.NewBaseKey("testKey")
moveKey := proto.NewBaseKey("moveKey")
// mock client
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSAdd(t, ctrl, dao)
_, err := dao.SAdd(testKey, []string{"1", "2", "3", "4"})
require.NoError(t, err)
waitWork, err := dao.SMove(testKey, moveKey.Key, []string{"3", "4", "5"})
require.NoError(t, err)
_, err = waitWork.(event2.EventAwaitFunc)()
require.NoError(t, err)
res, err := dao.SScan(testKey, 0, "", -1)
require.NoError(t, err)
require.Equal(t, res.Results, []string{"1", "2"})
// 移动 key
res, err = dao.SScan(moveKey, 0, "", -1)
require.NoError(t, err)
require.Equal(t, res.Results, []string{"3", "4"})
}
func TestDao_SPop(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
testKey := proto.NewBaseKey("testKey")
_, err := dao.SAdd(testKey, []string{"1", "2", "3", "4"})
require.NoError(t, err)
resp, err := dao.SPop(testKey, 2)
require.NoError(t, err)
require.Len(t, resp.Members, 2)
res, err := dao.SScan(testKey, 0, "", -1)
require.NoError(t, err)
require.Len(t, res.Results, 2)
}
func TestDao_SRem(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
testKey := proto.NewBaseKey("testKey")
_, err := dao.SAdd(testKey, []string{"1", "2", "3", "4"})
require.NoError(t, err)
_, err = dao.SRem(testKey, 2)
require.NoError(t, err)
res, err := dao.SScan(testKey, 0, "", -1)
require.NoError(t, err)
require.Len(t, res.Results, 2)
}
func TestDao_SUnion(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("union")
_, err := dao.SAdd(baseKey, []string{"a", "b", "s"})
require.NoError(t, err)
// mock client
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSScan(t, ctrl)
wait, err := dao.SUnion(baseKey, []string{"opp"})
require.NoError(t, err)
waitWork, ok := wait.(event2.EventAwaitFunc)
require.True(t, ok)
resp, err := waitWork()
require.NoError(t, err)
res, ok := resp.(*proto.SUnionResponse)
require.True(t, ok)
require.Equal(t, res.Result, []string{"a", "b", "s", "c"})
}
func TestDao_SUnionStore(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("unionStore")
storeKey := proto.NewBaseKey("apple")
_, err := dao.SAdd(baseKey, []string{"a", "b", "s"})
require.NoError(t, err)
// mock client
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSScan(t, ctrl)
// 必须调用一次 storage
mockSAdd(t, ctrl, dao)
wait, err := dao.SUnionStore(baseKey, []string{"opp", "oo2"}, storeKey.Key)
require.NoError(t, err)
waitWork, ok := wait.(event2.EventAwaitFunc)
require.True(t, ok)
resp, err := waitWork()
require.NoError(t, err)
_, ok = resp.(*proto.SUnionStoreResponse)
require.True(t, ok)
res, err := dao.SScan(storeKey, 0, "", -1)
require.NoError(t, err)
t.Log(res.Results)
require.Len(t, res.Results, 7)
}
func TestDao_SScan(t *testing.T) {
lru := lru.NewLRUCache()
dao := NewDao(lru)
baseKey := proto.NewBaseKey("apple")
_, err := dao.SAdd(baseKey, []string{"1", "2", "3", "a", "b", "c"})
require.NoError(t, err)
scanResp, err := dao.SScan(baseKey, 0, "", -1)
require.NoError(t, err)
require.Len(t, scanResp.Results, 6)
scanResp, err = dao.SScan(baseKey, 0, `\d`, -1)
require.NoError(t, err)
require.Len(t, scanResp.Results, 3)
scanResp, err = dao.SScan(baseKey, 0, `\d`, 4)
require.NoError(t, err)
require.Len(t, scanResp.Results, 3)
scanResp, err = dao.SScan(baseKey, 0, `\d`, 2)
require.NoError(t, err)
require.Len(t, scanResp.Results, 2)
scanResp, err = dao.SScan(baseKey, 0, `[a-z]+`, -1)
require.NoError(t, err)
require.Len(t, scanResp.Results, 3)
}

View File

@ -1,10 +1,10 @@
package dao
import (
"gitee.com/timedb/wheatCache/pkg/errorx"
"gitee.com/timedb/wheatCache/pkg/proto"
"gitee.com/timedb/wheatCache/pkg/structure"
"gitee.com/timedb/wheatCache/pkg/structure/stringx"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"gitee.com/wheat-os/wheatCache/pkg/structure"
"gitee.com/wheat-os/wheatCache/pkg/structure/stringx"
)
// stringx 相关的方法
@ -147,19 +147,28 @@ func (d *Dao) GetRange(key *proto.BaseKey, start, end int32) (*proto.GetRangeRes
func (d *Dao) GetSet(key *proto.BaseKey, value string) (*proto.GetSetResponse, error) {
val, ok := d.lru.Get(key)
var oldValue string
if !ok {
return nil, errorx.NotKeyErr(key.Key)
oldValue = ""
strValue := stringx.NewStringSingle()
strValue.Set(value)
err := d.lru.Add(key, strValue)
if err != nil {
return nil, err
}
} else {
strVal, ok := val.(structure.StringXInterface)
if !ok {
return nil, errorx.DaoTypeErr("stringx")
}
oldValue = strVal.Get()
_, updateLength := strVal.Set(value)
d.lru.UpdateLruSize(updateLength)
}
strVal, ok := val.(structure.StringXInterface)
if !ok {
return nil, errorx.DaoTypeErr("stringx")
}
oldValue := strVal.Get()
_, updateLength := strVal.Set(value)
d.lru.UpdateLruSize(updateLength)
return &proto.GetSetResponse{Result: oldValue}, nil
}

175
storage/dao/stringx_test.go Normal file
View File

@ -0,0 +1,175 @@
package dao
import (
// "reflect"
"testing"
"gitee.com/wheat-os/wheatCache/pkg/lru"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/stretchr/testify/require"
)
func TestDao_Set_Get(t *testing.T) {
baseKey := proto.NewBaseKey("abbs")
lru := lru.NewLRUCache()
dao := NewDao(lru)
_, err := dao.Set(baseKey, "bbq")
require.NoError(t, err)
resp, err := dao.Get(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Result, "bbq")
}
func TestDao_Add(t *testing.T) {
baseKey := proto.NewBaseKey("test")
lru := lru.NewLRUCache()
dao := NewDao(lru)
// 整数 add
dao.Set(baseKey, "1")
dao.Add(baseKey, 2)
resp, err := dao.Get(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Result, "3")
// 浮点数
dao.Set(baseKey, "1.1")
dao.Add(baseKey, 2)
resp, err = dao.Get(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Result, "3.10")
// 字符串
dao.Set(baseKey, "1awd.1")
_, err = dao.Add(baseKey, 2)
require.Error(t, err)
}
func TestDao_Reduce(t *testing.T) {
baseKey := proto.NewBaseKey("test")
lru := lru.NewLRUCache()
dao := NewDao(lru)
// 整数 add
dao.Set(baseKey, "1")
dao.Reduce(baseKey, 2)
resp, err := dao.Get(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Result, "-1")
// 浮点数
dao.Set(baseKey, "1.1")
dao.Reduce(baseKey, 2)
resp, err = dao.Get(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Result, "-0.90")
// 字符串
dao.Set(baseKey, "1awd.1")
_, err = dao.Reduce(baseKey, 2)
require.Error(t, err)
}
func TestDao_SetBit_GitBit(t *testing.T) {
baseKey := proto.NewBaseKey("s")
lru := lru.NewLRUCache()
dao := NewDao(lru)
_, err := dao.GetBit(baseKey, 8)
require.Error(t, err)
_, err = dao.SetBit(baseKey, true, 8)
require.NoError(t, err)
resp, err := dao.GetBit(baseKey, 8)
require.NoError(t, err)
require.Equal(t, resp.Val, true)
resp, err = dao.GetBit(baseKey, 7)
require.NoError(t, err)
require.Equal(t, resp.Val, false)
resp, err = dao.GetBit(baseKey, 9)
require.NoError(t, err)
require.Equal(t, resp.Val, false)
}
func TestDao_GetRange(t *testing.T) {
baseKey := proto.NewBaseKey("s")
lru := lru.NewLRUCache()
dao := NewDao(lru)
_, err := dao.GetRange(baseKey, 0, 5)
require.Error(t, err)
_, err = dao.Set(baseKey, "abcdef")
require.NoError(t, err)
resp, err := dao.GetRange(baseKey, 0, 3)
require.NoError(t, err)
require.Equal(t, resp.Result, "abc")
_, err = dao.GetRange(baseKey, 0, 7)
require.Error(t, err)
_, err = dao.Set(baseKey, "123456")
require.NoError(t, err)
resp, err = dao.GetRange(baseKey, 0, 3)
require.NoError(t, err)
require.Equal(t, resp.Result, "123")
}
func TestDao_GetSet(t *testing.T) {
baseKey := proto.NewBaseKey("s")
lru := lru.NewLRUCache()
dao := NewDao(lru)
_, err := dao.Set(baseKey, "a")
require.NoError(t, err)
resp, err := dao.GetSet(baseKey, "ab")
require.NoError(t, err)
require.Equal(t, resp.Result, "a")
resp, err = dao.GetSet(baseKey, "s")
require.NoError(t, err)
require.Equal(t, resp.Result, "a")
l := proto.NewBaseKey("l")
resp, err = dao.GetSet(l, "s")
require.NoError(t, err)
require.Equal(t, resp.Result, "")
}
func TestDao_StrLen(t *testing.T) {
baseKey := proto.NewBaseKey("s")
lru := lru.NewLRUCache()
dao := NewDao(lru)
_, err := dao.StrLen(baseKey)
require.Error(t, err)
_, err = dao.Set(baseKey, "abc")
require.NoError(t, err)
resp, err := dao.StrLen(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Length, int32(3))
}
func TestDao_Setnx(t *testing.T) {
baseKey := proto.NewBaseKey("s")
lru := lru.NewLRUCache()
dao := NewDao(lru)
_, err := dao.Setnx(baseKey, "abc")
require.NoError(t, err)
resp, err := dao.Get(baseKey)
require.NoError(t, err)
require.Equal(t, resp.Result, "abc")
_, err = dao.Setnx(baseKey, "abc")
require.Error(t, err)
}

19
storage/external/define.go vendored Normal file
View File

@ -0,0 +1,19 @@
package external
import (
"sync"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/golang/mock/gomock"
)
var (
oneGatewayClient sync.Once
gatewayClient proto.CommServerClient
)
var (
GateWayCtrl *gomock.Controller
mockGatewayClient proto.CommServerClient
oneMockGatewayClient sync.Once
)

41
storage/external/gateway.go vendored Normal file
View File

@ -0,0 +1,41 @@
package external
import (
"errors"
"gitee.com/wheat-os/wheatCache/client"
"gitee.com/wheat-os/wheatCache/client/middle"
_ "gitee.com/wheat-os/wheatCache/conf"
mockClient "gitee.com/wheat-os/wheatCache/mock/storage"
"gitee.com/wheat-os/wheatCache/pkg/errorx"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/spf13/viper"
)
func NewGatewayClient() (proto.CommServerClient, error) {
if viper.GetString("env") == "dev" {
if GateWayCtrl == nil {
return nil, errorx.New("mock ctrl not init")
}
oneMockGatewayClient.Do(func() {
mockGatewayClient = mockClient.NewMockCommServerClient(GateWayCtrl)
})
return mockGatewayClient, nil
}
oneGatewayClient.Do(func() {
cli, err := client.NewWheatClient("127.0.0.1:5891", middle.WithUnaryColonyClient)
if err == nil {
gatewayClient = cli
}
})
if gatewayClient != nil {
return gatewayClient, nil
}
return nil, errors.New("get gateway err")
}

36
storage/external/gateway_test.go vendored Normal file
View File

@ -0,0 +1,36 @@
package external
import (
"context"
"testing"
_ "gitee.com/wheat-os/wheatCache/conf"
mockClient "gitee.com/wheat-os/wheatCache/mock/storage"
"gitee.com/wheat-os/wheatCache/pkg/proto"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
)
func TestNewGatewayClient(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
GateWayCtrl = ctrl
cli, err := NewGatewayClient()
require.NoError(t, err)
mockClient := cli.(*mockClient.MockCommServerClient)
ctx := context.Background()
mockClient.EXPECT().Get(ctx, gomock.Any()).Return(&proto.GetResponse{
Result: "mockData",
}, nil)
resp, err := mockClient.Get(ctx, nil)
require.NoError(t, err)
require.Equal(t, resp.Result, "mockData")
resp, err = mockClient.Get(ctx, nil)
require.NoError(t, err)
require.Equal(t, resp.Result, "mockData")
}

View File

@ -1,22 +1,7 @@
/*
Copyright © 2021 NAME HERE <EMAIL ADDRESS>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"gitee.com/timedb/wheatCache/storage/cmd"
"gitee.com/wheat-os/wheatCache/storage/cmd"
)
func main() {

Some files were not shown because too many files have changed in this diff Show More