Compare commits
103 Commits
feat-stora
...
master
Author | SHA1 | Date |
---|---|---|
innov | a1fa8b22de | |
bandl | a9fac2572b | |
bandl | 57caa66ef8 | |
bandl | d254a71560 | |
bandl | 07dd0f8874 | |
bandl | dafffdde2c | |
bandl | c6b14ced27 | |
bandl | b87799a88e | |
bandl | dcfae2353b | |
bandl | bf0c03a77f | |
bandl | a57eab1184 | |
bandl | ef4cbb0cee | |
bandl | f62a59b551 | |
bandl | a949ab2edc | |
bandl | 7ac9651ef3 | |
bandl | 19e1bb59a3 | |
bandl | c381c57374 | |
bandl | 3f337dba9b | |
bandl | a37097b3dd | |
bandl | d90c05296a | |
bandl | 2a556a9db6 | |
bandl | c0da22ef6f | |
bandl | cf4b24ea86 | |
bandl | 953daca82c | |
Pyroo | 5974dadd3e | |
bandl | 1baac521fa | |
Pyroo | d6792444a7 | |
bandl | 64a02b642e | |
bandl | a5ef559e14 | |
bandl | 0c8a17b21d | |
bandl | 0207878507 | |
bandl | 813b48b650 | |
bandl | cdd26736a5 | |
bandl | 40afd8057d | |
bandl | 08bc1892df | |
bandl | 5e89f37e40 | |
bandl | 6b2f3fb3be | |
bandl | 499322c080 | |
bandl | e5f217b3b0 | |
bandl | 113185d17c | |
bandl | 981a3341ef | |
bandl | af6426f83b | |
bandl | d68209c94c | |
bandl | 60cf8f5eb1 | |
bandl | 594f8acf32 | |
bandl | 366793d955 | |
bandl | 5105a62bca | |
bandl | 400d620aa4 | |
bandl | 25be4a1509 | |
bandl | 60de1a6ae9 | |
bandl | 55204575d7 | |
bandl | 2f81eab981 | |
bandl | 3eb515325d | |
bandl | 3f3b208db1 | |
bandl | 8b8fd58c09 | |
bandl | 62d3105273 | |
bandl | 51bd9b242f | |
bandl | f6eaae71b9 | |
bandl | 921078c61d | |
bandl | c8ef4c6e46 | |
bandl | c6273d084e | |
bandl | fd605d125f | |
bandl | c9dcb41cad | |
bandl | f7bb695e82 | |
bandl | 4e6c2ed22a | |
bandl | 0c08e40667 | |
bandl | 7fa66abbf0 | |
bandl | a910e4af21 | |
bandl | 51914aea8a | |
bandl | bbfd32cebc | |
bandl | 44bd5bc7cd | |
bandl | fcdb2310fe | |
bandl | 222bcc4eea | |
bandl | c3cff03b2b | |
bandl | 06baf3993d | |
bandl | 976215ee10 | |
bandl | 778d5152c8 | |
bandl | 5ce350f115 | |
bandl | 047c910278 | |
bandl | dcada2f2fe | |
bandl | 88774daede | |
bandl | 344c136586 | |
bandl | 4c9ab82123 | |
bandl | 2ed75832ba | |
bandl | 0f1142d434 | |
bandl | b6dedfa384 | |
bandl | 0f2b73e932 | |
bandl | 2f46dfaa2e | |
bandl | c867665b60 | |
bandl | b91966709b | |
bandl | 47cdf0859b | |
bandl | 0b9230094a | |
bandl | eccfd6a439 | |
bandl | f5c3b0e1db | |
bandl | 5ee502021d | |
bandl | 9fed552380 | |
bandl | 7d9081ce8e | |
bandl | 4ca09febb4 | |
bandl | be528cbb6d | |
bandl | 70b23849bc | |
bandl | 99133bf7ea | |
bandl | 1ca43cde6c | |
bandl | de59f13234 |
|
@ -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.
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"]
|
||||
|
||||
|
|
|
@ -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 |
|
@ -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 |
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 |
|
@ -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 |
|
@ -0,0 +1,13 @@
|
|||
### 事件驱动 2.0
|
||||
|
||||
### event 1.0 存在的问题
|
||||
事件驱动 1.0 在 相互关联访问时,会发生 死锁问题, 导致一个事件执行周期失败
|
||||
|
||||
### event 2.0 新特性
|
||||
- 异步事件支持
|
||||
- 挂起操作
|
||||
|
||||
|
||||
### event 2.0 设计图
|
||||
![](../../_icon/event.svg)
|
||||
|
|
@ -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 迁移
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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...)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package transport
|
||||
package endpoint
|
||||
|
||||
type TransPortInterface interface {
|
||||
type EndpointInterface interface {
|
||||
GetTargetAddr(...string) (string, error)
|
||||
IsEmpty() bool
|
||||
AddTarget(targets ...string)
|
|
@ -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")
|
||||
}
|
|
@ -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"
|
||||
|
|
@ -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()
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
3
go.mod
|
@ -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
1
go.sum
|
@ -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=
|
||||
|
|
4
makefile
4
makefile
|
@ -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
|
@ -0,0 +1,5 @@
|
|||
package errorx
|
||||
|
||||
func EventRecoveryErr() error {
|
||||
return New("this event has been recycled")
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"gitee.com/timedb/wheatCache/pkg/errorx"
|
||||
"gitee.com/wheat-os/wheatCache/pkg/errorx"
|
||||
)
|
||||
|
||||
// 事件 poll 降低 new 对象的频率
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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()
|
||||
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -15,7 +15,7 @@ const (
|
|||
// NewBaseKey
|
||||
// key,ttl,expire
|
||||
func NewBaseKey(key string, t ...int64) *BaseKey {
|
||||
var expire *timestamppb.Timestamp
|
||||
var expire *timestamppb.Timestamp = nil
|
||||
var ttl int64
|
||||
|
||||
if len(t) > 1 {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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 (
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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"
|
||||
)
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitee.com/timedb/wheatCache/pkg/errorx"
|
||||
"gitee.com/wheat-os/wheatCache/pkg/errorx"
|
||||
)
|
||||
|
||||
// ParseSizeToBit
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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%}
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -7,4 +7,8 @@ message BaseKey {
|
|||
string key = 1;
|
||||
int64 ttl = 2;
|
||||
google.protobuf.Timestamp expire = 3;
|
||||
}
|
||||
|
||||
message External {
|
||||
|
||||
}
|
|
@ -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 {
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -53,7 +53,6 @@ message SetBitRequest {
|
|||
}
|
||||
|
||||
message SetBitResponse {
|
||||
string result = 2;
|
||||
}
|
||||
|
||||
message GetBitRequest {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -17,6 +17,7 @@ def out_proto():
|
|||
|
||||
if err:
|
||||
print(f, "-> out put err")
|
||||
return os._exit(-1)
|
||||
else:
|
||||
print(f, "-> success")
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
_ "gitee.com/timedb/wheatCache/conf"
|
||||
)
|
|
@ -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
|
||||
}
|
|
@ -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"})
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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")
|
||||
}
|
|
@ -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")
|
||||
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue