소스 검색

v0.0.1开发:调整inner服务mock的信息

#Suyghur 2 년 전
부모
커밋
6ffd6287e2

+ 9 - 0
comm/model/playerinfo.go

@@ -4,6 +4,15 @@
 
 package model
 
+type PlayerInfo struct {
+	PlayerId   string `json:"player_id"`
+	GameId     string `json:"game_id"`
+	IsVip      int64  `json:"is_vip"`
+	CsId       string `json:"cs_id"`
+	ConnectTs  int64  `json:"connect_ts"`
+	LastChatTs int64  `json:"last_chat_ts"`
+}
+
 type PlayerWaitingInfo struct {
 	PlayerId    string `json:"player_id"`
 	GameId      string `json:"game_id"`

+ 7 - 0
core/inner/rpc/etc/inner.yaml

@@ -22,3 +22,10 @@ KqDbBoxProducerConf:
   Brokers:
     - 127.0.0.1:9092
   Topic: db-box-topic
+
+KqCmdBoxProducerConf:
+  Brokers:
+    - 127.0.0.1:9092
+  Topic: cmd-box-topic
+
+MockFolder: /Users/suyghur/Develop/yyxx/backend/ylink/core/inner/rpc/mock

+ 3 - 0
core/inner/rpc/internal/config/config.go

@@ -9,5 +9,8 @@ type Config struct {
 	zrpc.RpcServerConf
 	KqMsgBoxConsumerConf kafka.KqConsumerConfig
 	KqMsgBoxProducerConf kafka.KqProducerConfig
+	KqCmdBoxProducerConf kafka.KqProducerConfig
 	//KqDbBoxProducerConf  kafka.KqProducerConfig
+
+	MockFolder string
 }

+ 28 - 5
core/inner/rpc/internal/ext/global.go

@@ -7,12 +7,35 @@ package ext
 import (
 	"github.com/liyue201/gostl/ds/list/simplelist"
 	"github.com/liyue201/gostl/ds/map"
+	"ylink/comm/model"
 )
 
 var (
-	GameVipMap           *treemap.Map
-	CsInfoMap            *treemap.Map
-	Game2PlayerStatusMap *treemap.Map
-	GameConnMap          *treemap.Map
-	WaitingQueue         *simplelist.List
+	// GameVipMap vip玩家信息(GameId,*PlayerInfoMap)
+	GameVipMap *treemap.Map
+	// CsInfoMap 客服信息(CsId,*CsInfo)
+	CsInfoMap *treemap.Map
+	// GameOnlinePlayerMap 在线玩家信息
+	GameOnlinePlayerMap *treemap.Map
+	// GameConnectedMap 已连接客服玩家
+	GameConnectedMap *treemap.Map
+	// WaitingQueue 玩家等待队列
+	WaitingQueue *simplelist.List
 )
+
+func GetVipPlayer(gameId, playerId string) *model.PlayerInfo {
+	if GameVipMap.Contains(gameId) {
+		vipMap := GameVipMap.Get(gameId).(*treemap.Map)
+		if vipMap.Contains(playerId) {
+			return vipMap.Get(playerId).(*model.PlayerInfo)
+		}
+	}
+	return nil
+}
+
+func GetCsInfo(csId string) *model.CsInfo {
+	if CsInfoMap.Contains(csId) {
+		return CsInfoMap.Get(csId).(*model.CsInfo)
+	}
+	return nil
+}

+ 3 - 3
core/inner/rpc/internal/logic/csconnectplayerlogic.go

@@ -25,13 +25,13 @@ func NewCsConnectPlayerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *C
 }
 
 func (l *CsConnectPlayerLogic) CsConnectPlayer(in *pb.InnerCsConnectPlayerReq) (*pb.InnerCsConnectPlayerResp, error) {
-	if ext.GameConnMap.Contains(in.GameId) {
-		playerConnMap := ext.GameConnMap.Get(in.GameId).(*treemap.Map)
+	if ext.GameConnectedMap.Contains(in.GameId) {
+		playerConnMap := ext.GameConnectedMap.Get(in.GameId).(*treemap.Map)
 		playerConnMap.Insert(in.PlayerId, in.CsId)
 	} else {
 		playerConnMap := treemap.New(treemap.WithGoroutineSafe())
 		playerConnMap.Insert(in.PlayerId, in.CsId)
-		ext.GameConnMap.Insert(in.GameId, playerConnMap)
+		ext.GameConnectedMap.Insert(in.GameId, playerConnMap)
 	}
 
 	return &pb.InnerCsConnectPlayerResp{}, nil

+ 10 - 7
core/inner/rpc/internal/logic/notifyuserofflinelogic.go

@@ -2,7 +2,7 @@ package logic
 
 import (
 	"context"
-	"github.com/liyue201/gostl/ds/set"
+	treemap "github.com/liyue201/gostl/ds/map"
 	"github.com/pkg/errors"
 	"ylink/comm/globalkey"
 	"ylink/comm/model"
@@ -33,12 +33,12 @@ func (l *NotifyUserOfflineLogic) NotifyUserOffline(in *pb.NotifyUserStatusReq) (
 	switch in.Type {
 	case globalkey.CONNECT_TYPE_PLAYER:
 		// 修改玩家在线状态
-		if ext.Game2PlayerStatusMap.Contains(in.GameId) {
+		if ext.GameOnlinePlayerMap.Contains(in.GameId) {
 			// 有则取出玩家的set
-			playerStatSet := ext.Game2PlayerStatusMap.Get(in.GameId).(*set.Set)
-			if playerStatSet.Contains(in.Uid) {
+			onlinePlayerMap := ext.GameOnlinePlayerMap.Get(in.GameId).(*treemap.Map)
+			if onlinePlayerMap.Contains(in.Uid) {
 				// 有则清除,代表下线
-				playerStatSet.Erase(in.Uid)
+				onlinePlayerMap.Erase(in.Uid)
 			}
 		}
 
@@ -52,8 +52,11 @@ func (l *NotifyUserOfflineLogic) NotifyUserOffline(in *pb.NotifyUserStatusReq) (
 		}
 	case globalkey.CONNECT_TYPE_CS:
 		// 修改客服在线状态
-		csInfo := ext.CsInfoMap.Get(in.Uid).(*model.CsInfo)
-		csInfo.OnlineStatus = 0
+		if csInfo := ext.GetCsInfo(in.Uid); csInfo != nil {
+			csInfo.OnlineStatus = 0
+		} else {
+			return nil, errors.Wrap(result.NewErrMsg("no such user"), "")
+		}
 	default:
 		return nil, errors.Wrap(result.NewErrMsg("no such user type"), "")
 	}

+ 45 - 25
core/inner/rpc/internal/logic/notifyuseronlinelogic.go

@@ -3,7 +3,6 @@ package logic
 import (
 	"context"
 	treemap "github.com/liyue201/gostl/ds/map"
-	"github.com/liyue201/gostl/ds/set"
 	"github.com/pkg/errors"
 	"time"
 	"ylink/comm/globalkey"
@@ -35,40 +34,61 @@ func (l *NotifyUserOnlineLogic) NotifyUserOnline(in *pb.NotifyUserStatusReq) (*p
 	switch in.Type {
 	case globalkey.CONNECT_TYPE_PLAYER:
 		// 修改玩家在线状态
-		if ext.Game2PlayerStatusMap.Contains(in.GameId) {
-			// 有则取出玩家的set
-			playerStatSet := ext.Game2PlayerStatusMap.Get(in.GameId).(*set.Set)
-			if !playerStatSet.Contains(in.Uid) {
-				playerStatSet.Insert(in.Uid)
+		if ext.GameOnlinePlayerMap.Contains(in.GameId) {
+			// 有则取出玩家的map
+			onlinePlayerMap := ext.GameOnlinePlayerMap.Get(in.GameId).(*treemap.Map)
+			if onlinePlayerMap.Contains(in.Uid) {
+				l.Logger.Error("such player has been connected")
+			} else {
+				// 不存在换这个玩家,判断是否vip
+				if playerInfo := ext.GetVipPlayer(in.GameId, in.Uid); playerInfo != nil {
+					playerInfo.ConnectTs = time.Now().Unix()
+					onlinePlayerMap.Insert(in.Uid, playerInfo)
+				} else {
+					// 不是vip
+					onlinePlayerMap.Insert(in.Uid, &model.PlayerInfo{
+						PlayerId:  in.Uid,
+						GameId:    in.GameId,
+						ConnectTs: time.Now().Unix(),
+					})
+					// 放入等待队列
+					ext.WaitingQueue.PushBack(&model.PlayerWaitingInfo{
+						PlayerId:    in.Uid,
+						GameId:      in.GameId,
+						EnqueueTime: time.Now().Unix(),
+					})
+					l.Logger.Infof("enqueue waiting list: %s", ext.WaitingQueue.String())
+				}
 			}
 		} else {
-			playerStatSet := set.New()
-			playerStatSet.Insert(in.Uid)
-			ext.Game2PlayerStatusMap.Insert(in.GameId, playerStatSet)
-		}
-
-		// 判断是否有专属客服,没有则放入等待队列
-		if ext.GameVipMap.Contains(in.GameId) {
-			p2cMap := ext.GameVipMap.Get(in.GameId).(*treemap.Map)
-			if !p2cMap.Contains(in.Uid) {
+			onlinePlayerMap := treemap.New(treemap.WithGoroutineSafe())
+			// 判断是不是vip玩家
+			if playerInfo := ext.GetVipPlayer(in.GameId, in.Uid); playerInfo != nil {
+				playerInfo.ConnectTs = time.Now().Unix()
+				onlinePlayerMap.Insert(in.Uid, playerInfo)
+			} else {
+				// 不是vip
+				onlinePlayerMap.Insert(in.Uid, &model.PlayerInfo{
+					PlayerId:  in.Uid,
+					GameId:    in.GameId,
+					ConnectTs: time.Now().Unix(),
+				})
+				// 放入等待队列
 				ext.WaitingQueue.PushBack(&model.PlayerWaitingInfo{
 					PlayerId:    in.Uid,
 					GameId:      in.GameId,
 					EnqueueTime: time.Now().Unix(),
 				})
+				l.Logger.Infof("enqueue waiting list: %s", ext.WaitingQueue.String())
 			}
-		} else {
-			ext.WaitingQueue.PushBack(&model.PlayerWaitingInfo{
-				PlayerId:    in.Uid,
-				GameId:      in.GameId,
-				EnqueueTime: time.Now().Unix(),
-			})
+			ext.GameOnlinePlayerMap.Insert(in.GameId, onlinePlayerMap)
 		}
-		l.Logger.Infof("enqueue waiting list: %s", ext.WaitingQueue.String())
 	case globalkey.CONNECT_TYPE_CS:
-		// 修改客服在线状态
-		csInfo := ext.CsInfoMap.Get(in.Uid).(*model.CsInfo)
-		csInfo.OnlineStatus = 1
+		if csInfo := ext.GetCsInfo(in.Uid); csInfo != nil {
+			csInfo.OnlineStatus = 1
+		} else {
+			return nil, errors.Wrap(result.NewErrMsg("no such user"), "")
+		}
 	default:
 		return nil, errors.Wrap(result.NewErrMsg("no such user type"), "")
 	}

+ 2 - 2
core/inner/rpc/internal/logic/playerfetchcsinfologic.go

@@ -28,8 +28,8 @@ func NewPlayerFetchCsInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext)
 }
 
 func (l *PlayerFetchCsInfoLogic) PlayerFetchCsInfo(in *pb.InnerPlayerFetchCsInfoReq) (*pb.InnerPlayerFetchCsInfoResp, error) {
-	if ext.GameConnMap.Contains(in.GameId) {
-		playerConnMap := ext.GameConnMap.Get(in.GameId).(*treemap.Map)
+	if ext.GameConnectedMap.Contains(in.GameId) {
+		playerConnMap := ext.GameConnectedMap.Get(in.GameId).(*treemap.Map)
 		csId := playerConnMap.Get(in.PlayerId).(string)
 		if ext.CsInfoMap.Contains(csId) {
 			csInfo := ext.CsInfoMap.Get(csId).(model.CsInfo)

+ 48 - 44
core/inner/rpc/internal/svc/servicecontext.go

@@ -4,10 +4,12 @@ import (
 	"context"
 	"encoding/json"
 	"github.com/Shopify/sarama"
+	"github.com/bytedance/sonic"
 	"github.com/liyue201/gostl/ds/list/simplelist"
 	treemap "github.com/liyue201/gostl/ds/map"
 	"github.com/zeromicro/go-zero/core/logx"
 	"go.opentelemetry.io/otel/attribute"
+	"io/ioutil"
 	"ylink/comm/kafka"
 	"ylink/comm/model"
 	"ylink/comm/trace"
@@ -18,14 +20,15 @@ import (
 type ServiceContext struct {
 	Config           config.Config
 	KqMsgBoxProducer *kafka.Producer
+	KqCmdBoxProducer *kafka.Producer
 	ConsumerGroup    *kafka.ConsumerGroup
 }
 
 func NewServiceContext(c config.Config) *ServiceContext {
-	fetchCsCenterInfo()
 	svcCtx := &ServiceContext{
 		Config:           c,
 		KqMsgBoxProducer: kafka.NewKafkaProducer(c.KqMsgBoxProducerConf.Brokers, c.KqMsgBoxProducerConf.Topic),
+		KqCmdBoxProducer: kafka.NewKafkaProducer(c.KqCmdBoxProducerConf.Brokers, c.KqCmdBoxProducerConf.Topic),
 		ConsumerGroup: kafka.NewConsumerGroup(&kafka.ConsumerGroupConfig{
 			KafkaVersion:   sarama.V1_0_0_0,
 			OffsetsInitial: sarama.OffsetNewest,
@@ -36,7 +39,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
 			c.KqMsgBoxConsumerConf.GroupId),
 	}
 	go svcCtx.subscribe()
-	go fetchCsCenterInfo()
+	fetchCsCenterInfo(c)
 	return svcCtx
 }
 
@@ -72,9 +75,9 @@ func (s *ServiceContext) handleMessage(sess sarama.ConsumerGroupSession, msg *sa
 		trace.StartTrace(ctx, "InnerServer.handleMessage.SendMessage", func(ctx context.Context) {
 			if len(message.ReceiverId) == 0 || message.ReceiverId == "" {
 				// 玩家发的消息,先从connMap找对应的客服,没有则从vipMap找,都没有则丢弃信息不投递
-				if ext.GameConnMap.Contains(message.GameId) {
+				if ext.GameConnectedMap.Contains(message.GameId) {
 					// 先从connMap找对应的客服映射
-					if playerConnMap := ext.GameConnMap.Get(message.GameId).(*treemap.Map); playerConnMap.Contains(message.SenderId) {
+					if playerConnMap := ext.GameConnectedMap.Get(message.GameId).(*treemap.Map); playerConnMap.Contains(message.SenderId) {
 						message.ReceiverId = playerConnMap.Get(message.SenderId).(string)
 					} else {
 						if ext.GameVipMap.Contains(message.GameId) {
@@ -121,50 +124,51 @@ func (s *ServiceContext) subscribe() {
 	go s.ConsumerGroup.RegisterHandleAndConsumer(s)
 }
 
-func fetchCsCenterInfo() {
+func fetchCsCenterInfo(c config.Config) {
 	// mock info
-	ext.Game2PlayerStatusMap = treemap.New(treemap.WithGoroutineSafe())
-	ext.GameConnMap = treemap.New(treemap.WithGoroutineSafe())
 	ext.CsInfoMap = treemap.New(treemap.WithGoroutineSafe())
+	ext.GameVipMap = treemap.New(treemap.WithGoroutineSafe())
+	ext.GameOnlinePlayerMap = treemap.New(treemap.WithGoroutineSafe())
+	ext.GameConnectedMap = treemap.New(treemap.WithGoroutineSafe())
 	ext.WaitingQueue = simplelist.New()
-	mockInfo()
+	go loadMockInfo(c)
 }
-func mockInfo() {
-	ext.GameVipMap = treemap.New(treemap.WithGoroutineSafe())
-	ext.CsInfoMap = treemap.New(treemap.WithGoroutineSafe())
-
-	// 已连接的映射
-
-	// 专属客服映射
-	game1231P2cMap := treemap.New(treemap.WithGoroutineSafe())
-	game1231P2cMap.Insert("player_1231", "cs_1231")
-	game1231P2cMap.Insert("player_1111", "cs_2222")
-
-	game1111P2cMap := treemap.New(treemap.WithGoroutineSafe())
-	game1111P2cMap.Insert("player_1231", "cs_1111")
+func loadMockInfo(c config.Config) {
+	// 加载游戏列表
+	logx.Info("加载游戏列表")
+	var gameIds []string
+	gameIdsData, err := ioutil.ReadFile(c.MockFolder + "/game_id.json")
+	if err != nil {
+		logx.Errorf("parse game_id.json has some error: %v", err)
+		return
+	}
+	if err := sonic.Unmarshal(gameIdsData, &gameIds); err != nil {
+		return
+	}
 
-	ext.GameVipMap.Insert("game_1231", game1231P2cMap)
-	ext.GameVipMap.Insert("game_1111", game1111P2cMap)
+	// 加载vip玩家信息
+	logx.Info("加载vip玩家信息")
+	for _, gameId := range gameIds {
+		vipPlayerMap := treemap.New(treemap.WithGoroutineSafe())
+		var playerInfos []*model.PlayerInfo
+		playerInfosData, _ := ioutil.ReadFile(c.MockFolder + "/" + gameId + ".json")
+		if err := sonic.Unmarshal(playerInfosData, &playerInfos); err != nil {
+			return
+		}
+		for _, playerInfo := range playerInfos {
+			vipPlayerMap.Insert(playerInfo.PlayerId, playerInfo)
+		}
+		ext.GameVipMap.Insert(gameId, vipPlayerMap)
+	}
 
-	ext.CsInfoMap.Insert("cs_1231", &model.CsInfo{
-		CsId:         "cs_1231",
-		CsNickname:   "客服1231",
-		CsAvatarUrl:  "https://www.baidu.com",
-		CsSignature:  "我是客服1231",
-		OnlineStatus: 0,
-	})
-	ext.CsInfoMap.Insert("cs_1111", &model.CsInfo{
-		CsId:         "cs_1111",
-		CsNickname:   "客服1111",
-		CsAvatarUrl:  "https://www.baidu.com",
-		CsSignature:  "我是客服1111",
-		OnlineStatus: 0,
-	})
-	ext.CsInfoMap.Insert("cs_2222", &model.CsInfo{
-		CsId:         "cs_2222",
-		CsNickname:   "客服2222",
-		CsAvatarUrl:  "https://www.baidu.com",
-		CsSignature:  "我是客服2222",
-		OnlineStatus: 0,
-	})
+	// 加载客服信息
+	logx.Info("加载客服信息")
+	var csInfos []*model.CsInfo
+	csInfosData, err := ioutil.ReadFile(c.MockFolder + "/cs_info.json")
+	if err := sonic.Unmarshal(csInfosData, &csInfos); err != nil {
+		return
+	}
+	for _, csInfo := range csInfos {
+		ext.CsInfoMap.Insert(csInfo.CsId, csInfo)
+	}
 }

+ 20 - 0
core/inner/rpc/mock/cs_info.json

@@ -0,0 +1,20 @@
+[
+  {
+    "cs_id": "cs_1231",
+    "cs_name": "客服_1231",
+    "cs_avatar_url": "https://www.baidu.com",
+    "cs_signature": "我是客服1231"
+  },
+  {
+    "cs_id": "cs_1111",
+    "cs_name": "客服_1111",
+    "cs_avatar_url": "https://www.baidu.com",
+    "cs_signature": "我是客服1111"
+  },
+  {
+    "cs_id": "cs_2222",
+    "cs_name": "客服_2222",
+    "cs_avatar_url": "https://www.baidu.com",
+    "cs_signature": "我是客服2222"
+  }
+]

+ 9 - 0
core/inner/rpc/mock/game_1111.json

@@ -0,0 +1,9 @@
+[
+  {
+    "player_id": "player_1111",
+    "game_id": "game_1111",
+    "cs_id": "cs_1111",
+    "is_vip": 1,
+    "last_chat_ts": 1654155384
+  }
+]

+ 16 - 0
core/inner/rpc/mock/game_1231.json

@@ -0,0 +1,16 @@
+[
+  {
+    "player_id": "player_1231",
+    "game_id": "game_1231",
+    "is_vip": 1,
+    "cs_id": "cs_1231",
+    "last_chat_ts": 1654155384
+  },
+  {
+    "player_id": "player_2222",
+    "game_id": "game_1231",
+    "is_vip": 1,
+    "cs_id": "cs_1231",
+    "last_chat_ts": 1654155384
+  }
+]

+ 4 - 0
core/inner/rpc/mock/game_id.json

@@ -0,0 +1,4 @@
+[
+  "game_1231",
+  "game_1111"
+]

+ 6 - 1
go.mod

@@ -4,6 +4,8 @@ go 1.18
 
 require (
 	github.com/Shopify/sarama v1.33.0
+	github.com/bytedance/sonic v1.3.0
+	github.com/go-redis/redis/v8 v8.11.4
 	github.com/golang-jwt/jwt/v4 v4.4.1
 	github.com/liyue201/gostl v1.0.1
 	github.com/pkg/errors v0.9.1
@@ -17,6 +19,7 @@ require (
 require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 // indirect
 	github.com/coreos/go-semver v0.3.0 // indirect
 	github.com/coreos/go-systemd/v22 v22.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
@@ -26,7 +29,6 @@ require (
 	github.com/eapache/queue v1.1.0 // indirect
 	github.com/go-logr/logr v1.2.3 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
-	github.com/go-redis/redis/v8 v8.11.4 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/mock v1.6.0 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
@@ -47,6 +49,7 @@ require (
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/justinas/alice v1.2.0 // indirect
 	github.com/klauspost/compress v1.15.0 // indirect
+	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
@@ -58,6 +61,7 @@ require (
 	github.com/prometheus/procfs v0.7.3 // indirect
 	github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
 	github.com/spaolacci/murmur3 v1.1.0 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.2 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.2 // indirect
 	go.etcd.io/etcd/client/v3 v3.5.2 // indirect
@@ -68,6 +72,7 @@ require (
 	go.uber.org/automaxprocs v1.4.0 // indirect
 	go.uber.org/multierr v1.8.0 // indirect
 	go.uber.org/zap v1.21.0 // indirect
+	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
 	golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
 	golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 // indirect
 	golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect

+ 22 - 0
go.sum

@@ -71,10 +71,14 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
+github.com/bytedance/sonic v1.3.0 h1:T2rlvNytw6bTmczlAXvGqmuMzIqGJBOsJKYwRPWR7Y8=
+github.com/bytedance/sonic v1.3.0/go.mod h1:V973WhNhGmvHxW6nQmsHEfHaoU9F3zTF+93rH03hcUQ=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
 github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 h1:1sDoSuDPWzhkdzNVxCxtIaKiAe96ESVPv8coGwc1gZ4=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -164,6 +168,8 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
 github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/goccy/go-json v0.9.4 h1:L8MLKG2mvVXiQu07qB6hmfqeSYQdOnqPot2GhsIwIaI=
+github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -292,6 +298,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
 github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U=
 github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -416,7 +424,18 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M=
+github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
+github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
@@ -472,6 +491,8 @@ go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95a
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
 go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -846,6 +867,7 @@ k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAG
 k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
 k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=