From 3ea3a3ac6df9fae4c8f307e14233ab32adf970fc Mon Sep 17 00:00:00 2001 From: "DESKTOP-V763RJ7\\Administrator" <835606593@qq.com> Date: Sat, 3 Jan 2026 14:26:09 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E5=88=9D=E6=AC=A1=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 170 +++++- config/config.go | 68 +++ config/loader.go | 42 ++ db/db.go | 48 ++ db/etcd/client.go | 76 +++ db/mongo/client.go | 70 +++ db/mysql/client.go | 85 +++ db/redis/cache_client.go | 50 ++ db/redis/client.go | 53 ++ discover/common/define.go | 42 ++ discover/common/tool.go | 25 + discover/instance.go | 81 +++ discover/listener.go | 130 +++++ discover/server.go | 100 ++++ go.mod | 93 ++++ go.sum | 273 ++++++++++ log/level.go | 23 + log/log.go | 66 +++ log/log_zap.go | 63 +++ net/grpc/grpc_conn/conn.go | 42 ++ net/grpc/grpc_conn/conn_mgr.go | 62 +++ net/grpc/resolver/conn.go | 30 + net/grpc/resolver/etcd_resolver.go | 84 +++ net/grpc/resolver/resolver_mgr.go | 35 ++ net/grpc/service/client_gateway.go | 24 + net/grpc/service/client_scene.go | 33 ++ net/grpc/service/client_user.go | 24 + net/grpc/service/service.go | 88 +++ net/http/http_resp/code.go | 47 ++ net/http/http_resp/response.go | 47 ++ net/socket/server.go | 48 ++ net/socket/websocket/websocket.go | 187 +++++++ net/socket/websocket/wsconn.go | 202 +++++++ proto/sc/sc_common/sc_common.pb.go | 62 +++ proto/sc/sc_pb/action.pb.go | 521 ++++++++++++++++++ proto/sc/sc_pb/define.pb.go | 217 ++++++++ proto/ss/grpc_pb/service_gateway.pb.go | 221 ++++++++ proto/ss/grpc_pb/service_gateway_grpc.pb.go | 141 +++++ proto/ss/grpc_pb/service_scene.pb.go | 574 ++++++++++++++++++++ proto/ss/grpc_pb/service_scene_grpc.pb.go | 212 ++++++++ proto/ss/grpc_pb/service_user.pb.go | 372 +++++++++++++ proto/ss/grpc_pb/service_user.pb.gw.go | 154 ++++++ proto/ss/grpc_pb/service_user_grpc.pb.go | 141 +++++ proto/ss/ss_common/ss_common.pb.go | 151 +++++ utils/jwt.go | 56 ++ utils/number.go | 23 + utils/snowflake.go | 24 + utils/workerpool.go | 41 ++ 48 files changed, 5420 insertions(+), 1 deletion(-) create mode 100644 config/config.go create mode 100644 config/loader.go create mode 100644 db/db.go create mode 100644 db/etcd/client.go create mode 100644 db/mongo/client.go create mode 100644 db/mysql/client.go create mode 100644 db/redis/cache_client.go create mode 100644 db/redis/client.go create mode 100644 discover/common/define.go create mode 100644 discover/common/tool.go create mode 100644 discover/instance.go create mode 100644 discover/listener.go create mode 100644 discover/server.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 log/level.go create mode 100644 log/log.go create mode 100644 log/log_zap.go create mode 100644 net/grpc/grpc_conn/conn.go create mode 100644 net/grpc/grpc_conn/conn_mgr.go create mode 100644 net/grpc/resolver/conn.go create mode 100644 net/grpc/resolver/etcd_resolver.go create mode 100644 net/grpc/resolver/resolver_mgr.go create mode 100644 net/grpc/service/client_gateway.go create mode 100644 net/grpc/service/client_scene.go create mode 100644 net/grpc/service/client_user.go create mode 100644 net/grpc/service/service.go create mode 100644 net/http/http_resp/code.go create mode 100644 net/http/http_resp/response.go create mode 100644 net/socket/server.go create mode 100644 net/socket/websocket/websocket.go create mode 100644 net/socket/websocket/wsconn.go create mode 100644 proto/sc/sc_common/sc_common.pb.go create mode 100644 proto/sc/sc_pb/action.pb.go create mode 100644 proto/sc/sc_pb/define.pb.go create mode 100644 proto/ss/grpc_pb/service_gateway.pb.go create mode 100644 proto/ss/grpc_pb/service_gateway_grpc.pb.go create mode 100644 proto/ss/grpc_pb/service_scene.pb.go create mode 100644 proto/ss/grpc_pb/service_scene_grpc.pb.go create mode 100644 proto/ss/grpc_pb/service_user.pb.go create mode 100644 proto/ss/grpc_pb/service_user.pb.gw.go create mode 100644 proto/ss/grpc_pb/service_user_grpc.pb.go create mode 100644 proto/ss/ss_common/ss_common.pb.go create mode 100644 utils/jwt.go create mode 100644 utils/number.go create mode 100644 utils/snowflake.go create mode 100644 utils/workerpool.go diff --git a/README.md b/README.md index ddea267..83d7ec6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,171 @@ # common -公共代码集合 \ No newline at end of file +公共代码集合 + +--- + +## ✅ 微服务十大核心原则(实战导向) + +> 这些不是理论教条,而是无数团队踩坑后总结出的“生存法则”。 + +--- + +### 1. **单一职责 & 高内聚(Single Responsibility)** +- 每个微服务应围绕 **一个明确的业务能力**(如“用户管理”、“支付”、“通知”)。 +- ❌ 不要按技术分层拆服务(如“所有 DB 服务”、“所有 API 服务”)。 +- ✅ 建议用 **DDD(领域驱动设计)** 划分限界上下文(Bounded Context)。 + +> 📌 口诀:**“一个服务,一个事”** + +--- + +### 2. **自治性(Autonomy)** +- 服务应能 **独立开发、测试、部署、扩展、故障恢复**。 +- 依赖越少越好;跨服务调用必须有 **降级、熔断、超时** 机制。 +- 使用 **契约测试(Contract Testing)** 保证接口兼容(如 Pact)。 + +> 🔧 工具推荐: +> - gRPC + Protobuf(强契约) +> - OpenAPI(REST) +> - WireMock / Pact(契约测试) + +--- + +### 3. **数据私有(Database per Service)** ← 你已掌握! +- 每个服务独占数据存储,**禁止跨服务直连数据库**。 +- 跨服务数据交互靠: + - **同步**:API(gRPC/HTTP) + - **异步**:事件(Kafka / RabbitMQ / Pulsar) + +> 💡 技巧:用 **事件溯源(Event Sourcing) + CQRS** 构建复杂查询视图。 + +--- + +### 4. **无状态(Stateless)** +- 服务实例本身不保存会话或状态(状态存 Redis / DB / Cookie)。 +- 好处:**水平扩展容易**,K8s 可随意扩缩容。 + +> ⚠️ 例外:批处理、流计算等有状态场景可用 StatefulSet,但要谨慎。 + +--- + +### 5. **可观测性(Observability)三件套** +微服务没有可观测性 = 盲人开车! + +| 组件 | 作用 | 工具推荐 | +|------|------|--------| +| **Logging** | 记录结构化日志 | Zap / Logrus + Loki / ELK | +| **Metrics** | 监控性能指标 | Prometheus + Grafana | +| Assistant | 追踪请求链路 | Jaeger / Zipkin / OpenTelemetry | + +> ✅ 必做: +> - 所有日志带 `trace_id` +> - 所有 gRPC 调用自动埋点 +> - 关键路径加自定义指标(如“登录成功率”) + +--- + +### 6. **弹性设计(Resilience)** +网络不可靠!必须假设: +- 其他服务会宕机 +- 网络会延迟或丢包 + +✅ 必备机制: +- **超时(Timeout)**:每个调用设上限(如 1s) +- **重试(Retry)**:带退避策略(指数退避) +- **熔断(Circuit Breaker)**:失败太多就短路(如 Hystrix / Sentinel) +- **限流(Rate Limiting)**:保护自己不被压垮 +- **降级(Fallback)**:返回默认值或缓存数据 + +> 🛠 Go 推荐库: +> - `go-resiliency` +> - `sony/gobreaker` +> - 自研中间件(结合 context + retry) + +--- + +### 7. **API 优先(API-First Design)** +- 先定义 `.proto`(gRPC)或 OpenAPI(REST),再写代码。 +- 客户端 SDK 自动生成(如 `protoc-gen-go`)。 +- 版本管理:**向后兼容优先**,避免频繁改接口。 + +> 📁 目录建议: +> ``` +> api/ +> ├── user/v1/user.proto +> └── order/v1/order.proto +> ``` + +--- + +### 8. **基础设施即代码(IaC) & GitOps** +- 数据库、K8s、网关配置全部代码化(Terraform / Helm / Kustomize)。 +- 所有变更通过 Git PR 触发自动化部署。 +- 环境一致性:dev / staging / prod 配置几乎相同。 + +> ✅ 好处:**“一键重建整个环境”** + +--- + +### 9. **安全内建(Security by Default)** +- **mTLS**:服务间通信加密(Istio / Linkerd) +- **RBAC**:基于角色的访问控制 +- **敏感信息**:用 Vault / K8s Secret 管理,不硬编码 +- **输入校验**:所有 API 参数严格验证(如 `validator.v10`) + +> 🔒 原则:**“零信任网络”** —— 不信任任何内部流量。 + +--- + +### 10. **演进式设计(Evolutionary Architecture)** +- 不追求“一次性完美架构” +- 用 **Strangler Fig Pattern(绞杀者模式)** 逐步替换旧系统 +- 定期做 **架构重构** 和 **技术债清理** + +> 🌱 微服务是“种出来的”,不是“画出来的”。 + +--- + +## 🧱 推荐架构分层(Go 微服务) + +``` +user-service/ +├── api/ # .proto 文件(对外契约) +├── cmd/ # main 入口 +├── internal/ +│ ├── handler/ # gRPC/HTTP handlers(薄层) +│ ├── service/ # 业务逻辑(核心) +│ ├── repository/ # 数据访问(接口 + mysql 实现) +│ └── model/ # 领域模型(与 DB 解耦) +├── pkg/ # 可共享工具(谨慎!) +├── deploy/ # K8s / Docker 配置 +└── go.mod +``` + +> 🔑 关键:`internal/` 禁止被外部 import,强制通过 API 交互。 + +--- + +## 🚫 微服务常见反模式(务必避开!) + +| 反模式 | 后果 | +|-------|------| +| 分布式单体 | 失去微服务所有优势 | +| 共享数据库 | 强耦合,无法独立演进 | +| 同步调用链过长(A→B→C→D) | 故障放大,雪崩风险 | +| 无监控无告警 | 出问题找不到原因 | +| 手动部署 | 发布慢,易出错 | + +--- + +## ✅ 最后建议:从小做起,逐步完善 + +1. **先保证“能跑”**:一个服务 + 独立 DB + gRPC API +2. **加上可观测性**:日志 + Metrics + Tracing +3. **加上弹性机制**:超时 + 重试 +4. **加上 CI/CD**:自动化测试 & 部署 +5. **再考虑事件驱动、CQRS、Service Mesh...** + +> 🌟 **好的微服务架构不是设计出来的,而是在约束和实践中演化出来的。** + +--- \ No newline at end of file diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..87f6516 --- /dev/null +++ b/config/config.go @@ -0,0 +1,68 @@ +package config + +type AppConfig struct { + Name string `yaml:"name"` +} + +type LogConfig struct { + Debug bool `yaml:"debug"` + MaxSize int32 `yaml:"maxSize"` + MaxBackups int32 `yaml:"maxBackups"` + MaxAge int32 `yaml:"maxAge"` + Level string `yaml:"level"` +} + +type MetricConfig struct { + Prometheus *struct { + Address string `yaml:"address"` + Port int32 `yaml:"port"` + } `yaml:"prometheus"` +} + +type DBConfig struct { + Etcd *EtcdConfig `yaml:"etcd"` + MySQL map[string]*MySQLConfig `yaml:"mysql"` + Mongo map[string]*MongoConfig `yaml:"mongo"` + Redis *RedisConfig `yaml:"redis"` +} + +type EtcdConfig struct { + Endpoints []string `yaml:"endpoints"` +} + +type MySQLConfig struct { + Dsn string `yaml:"dsn"` + MaxOpenConn int32 `yaml:"maxOpenConn"` + MaxIdleConn int32 `yaml:"maxIdleConn"` + ConnMaxLifetimeSec int32 `yaml:"connMaxLifetimeSec"` + ConnMaxIdleTimeSec int32 `yaml:"connMaxIdleTimeSec"` + LogLevel string `yaml:"logLevel"` +} + +type MongoConfig struct { + URI string `yaml:"uri"` +} + +type RedisConfig struct { + Addr string `yaml:"addr"` + Password string `yaml:"password"` + DB int `yaml:"db"` +} + +type ServeConfig struct { + Grpc *struct { + Address string `yaml:"address"` + Port int32 `yaml:"port"` + TTL int64 `yaml:"ttl"` + } `yaml:"grpc"` + Socket *struct { + Web *AddressConfig `yaml:"web"` + Raw *AddressConfig `yaml:"raw"` + } `yaml:"socket"` + Http *AddressConfig `yaml:"http"` +} + +type AddressConfig struct { + Address string `yaml:"address"` + Port int32 `yaml:"port"` +} diff --git a/config/loader.go b/config/loader.go new file mode 100644 index 0000000..143e282 --- /dev/null +++ b/config/loader.go @@ -0,0 +1,42 @@ +package config + +import ( + "encoding/json" + "fmt" + "github.com/spf13/viper" + "strings" +) + +const ( + envConfigPrefix = "XH_G" +) + +// LoadConfig 加载并返回应用配置 +func LoadConfig[T any](configDir string, configPtr *T) (*T, error) { + v := viper.New() + + v.SetEnvPrefix(envConfigPrefix) + v.AutomaticEnv() + v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + + env := v.GetString("env") + if env == "" { + env = "dev" + } + + v.SetConfigName(fmt.Sprintf("config.%s", strings.ToLower(env))) + v.AddConfigPath(configDir) + v.SetConfigType("yaml") + + if err := v.ReadInConfig(); err != nil { + return nil, fmt.Errorf("failed to read config: %w", err) + } + + if err := v.Unmarshal(&configPtr); err != nil { + return nil, fmt.Errorf("failed to unmarshal config: %w", err) + } + + marshal, _ := json.Marshal(configPtr) + fmt.Printf("Configuration loading completed: %v\n", string(marshal)) + return configPtr, nil +} diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..5cdbbab --- /dev/null +++ b/db/db.go @@ -0,0 +1,48 @@ +package db + +import ( + "common/config" + "common/db/etcd" + "common/db/mysql" + "common/db/redis" + "common/log" +) + +// ModuleDB 数据库模块 +type ModuleDB struct { +} + +func (p *ModuleDB) Init(cfg *config.DBConfig) error { + // ETCD + if cfg.Etcd != nil { + if err := etcd.Init(cfg.Etcd); err != nil { + return err + } + } + // MYSQL + if cfg.MySQL != nil { + if err := mysql.Init(cfg.MySQL); err != nil { + return err + } + } + // REDIS + if cfg.Redis != nil { + if err := redis.Init(cfg.Redis); err != nil { + return err + } + } + return nil +} + +func (p *ModuleDB) Stop() error { + if err := etcd.Close(); err != nil { + log.Errorf("close etcd failed: %v", err) + } + if err := mysql.Close(); err != nil { + log.Errorf("close mysql failed: %v", err) + } + if err := redis.Close(); err != nil { + log.Errorf("close redis failed: %v", err) + } + return nil +} diff --git a/db/etcd/client.go b/db/etcd/client.go new file mode 100644 index 0000000..ce79301 --- /dev/null +++ b/db/etcd/client.go @@ -0,0 +1,76 @@ +package etcd + +import ( + "common/config" + "context" + "go.etcd.io/etcd/client/v3" + "time" +) + +var instance *Client + +type Client struct { + cli *clientv3.Client +} + +// Init 初始化 +func Init(cfg *config.EtcdConfig) error { + client, err := clientv3.New(clientv3.Config{ + Endpoints: cfg.Endpoints, + DialTimeout: 5 * time.Second, + }) + instance = &Client{ + cli: client, + } + return err +} + +// Close 关闭 +func Close() error { + if instance != nil && instance.cli != nil { + return instance.cli.Close() + } + return nil +} + +func GetClient() *Client { + return instance +} + +// Get 获取数据 +func (c *Client) Get(key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + return c.cli.Get(ctx, key, opts...) +} + +// Put 创建数据 +func (c *Client) Put(key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + return c.cli.Put(ctx, key, val, opts...) +} + +// Grant 创建租约 +func (c *Client) Grant(ttl int64) (*clientv3.LeaseGrantResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + return c.cli.Grant(ctx, ttl) +} + +// KeepAlive 保活租约 +func (c *Client) KeepAlive(id clientv3.LeaseID) (<-chan *clientv3.LeaseKeepAliveResponse, error) { + return c.cli.KeepAlive(context.Background(), id) +} + +// Revoke 撤销租约 +func (c *Client) Revoke(id clientv3.LeaseID) (*clientv3.LeaseRevokeResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + return c.cli.Revoke(ctx, id) +} + +// Watch 监听数据 +func (c *Client) Watch(key string, opts ...clientv3.OpOption) clientv3.WatchChan { + return c.cli.Watch(context.Background(), key, opts...) +} diff --git a/db/mongo/client.go b/db/mongo/client.go new file mode 100644 index 0000000..db3b729 --- /dev/null +++ b/db/mongo/client.go @@ -0,0 +1,70 @@ +package mongo + +import ( + "common/config" + "common/log" + "context" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +type DBName string + +var clients = make(map[DBName]*mongo.Client) + +func Init(cfg map[string]*config.MongoConfig) error { + for name, oneConfig := range cfg { + if client, err := initOneClient(oneConfig); err != nil { + return err + } else { + clients[DBName(name)] = client + } + } + return nil +} + +func initOneClient(cfg *config.MongoConfig) (*mongo.Client, error) { + opts := options.Client(). + ApplyURI(cfg.URI) + + client, err := mongo.Connect(context.Background(), opts) + if err != nil { + return nil, err + } + + return client, nil +} + +// GetClient 返回 mongo.Client,你可以通过 .Database("xxx") 获取具体数据库 +func GetClient(dbName DBName) *mongo.Client { + if c, ok := clients[dbName]; ok { + return c + } + log.Errorf("mongo client %s not found", dbName) + return nil +} + +// GetDB 是便捷方法,直接返回 *mongo.Database(假设 dbName 对应数据库名) +// 如果你的配置中 dbName 和实际数据库名一致,可这样用 +func GetDB(dbName DBName) *mongo.Database { + client := GetClient(dbName) + if client == nil { + return nil + } + // 假设配置中的 key 就是数据库名;若需分离,可在 config 中加字段 + return client.Database(string(dbName)) +} + +func Close() error { + if clients == nil { + return nil + } + for name, client := range clients { + if client != nil { + if err := client.Disconnect(context.Background()); err != nil { + log.Errorf("close mongo client %s error: %v", name, err) + } + } + } + return nil +} diff --git a/db/mysql/client.go b/db/mysql/client.go new file mode 100644 index 0000000..aad686d --- /dev/null +++ b/db/mysql/client.go @@ -0,0 +1,85 @@ +package mysql + +import ( + "common/config" + "common/log" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "time" +) + +type DBName string + +var dbs = make(map[DBName]*gorm.DB) + +func Init(cfg map[string]*config.MySQLConfig) error { + for name, oneConfig := range cfg { + if db, err := initOneDB(oneConfig); err != nil { + return err + } else { + dbs[DBName(name)] = db + } + } + return nil +} + +func initOneDB(cfg *config.MySQLConfig) (*gorm.DB, error) { + db, err := gorm.Open( + mysql.Open(cfg.Dsn), + &gorm.Config{ + TranslateError: true, + Logger: logger.Default.LogMode(parseLogLevel(cfg.LogLevel)), + }, + ) + if err != nil { + return nil, err + } + + sqlDB, err := db.DB() + if err != nil { + return nil, err + } + sqlDB.SetMaxOpenConns(int(cfg.MaxOpenConn)) + sqlDB.SetMaxIdleConns(int(cfg.MaxIdleConn)) + sqlDB.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetimeSec) * time.Second) + sqlDB.SetConnMaxIdleTime(time.Duration(cfg.ConnMaxIdleTimeSec) * time.Second) + + return db, nil +} + +func parseLogLevel(logLevel string) logger.LogLevel { + switch logLevel { + case "silent": + return logger.Silent + case "error": + return logger.Error + case "warn": + return logger.Warn + case "info": + return logger.Info + } + return logger.Info +} + +func GetDB(dbName DBName) *gorm.DB { + if q, ok := dbs[dbName]; ok { + return q + } + log.Errorf("db %s not found", dbName) + return nil +} + +func Close() error { + if dbs == nil { + return nil + } + for name, db := range dbs { + if sqlDB, _ := db.DB(); sqlDB != nil { + if err := sqlDB.Close(); err != nil { + log.Errorf("close db %s error: %v", name, err) + } + } + } + return nil +} diff --git a/db/redis/cache_client.go b/db/redis/cache_client.go new file mode 100644 index 0000000..e5815a7 --- /dev/null +++ b/db/redis/cache_client.go @@ -0,0 +1,50 @@ +package redis + +import ( + "context" + "encoding/json" + "github.com/panjf2000/gnet/v2/pkg/logging" + "github.com/redis/go-redis/v9" + "time" +) + +var cacheInstance *CacheClient + +type CacheClient struct { + cli *redis.Client + logger logging.Logger +} + +func GetCacheClient() *CacheClient { + return cacheInstance +} + +func (c *CacheClient) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) { + bytes, err := json.Marshal(value) + if err != nil { + c.logger.Errorf("Set json.Marshal error: %v, key: %v, value: %v", err, key, value) + return + } + if err = c.cli.Set(ctx, key, bytes, expiration).Err(); err != nil { + c.logger.Errorf("Set redis.Set error: %v, key: %v, value: %v", err, key, value) + } +} + +func (c *CacheClient) Del(ctx context.Context, keys ...string) { + if err := c.cli.Del(ctx, keys...).Err(); err != nil { + c.logger.Errorf("Set redis.Del error: %v, keys: %v", err, keys) + } +} + +// Get 获取数据 +func (c *CacheClient) Get(ctx context.Context, key string, dst interface{}) bool { + data, err := c.cli.Get(ctx, key).Bytes() + if err != nil { + return false + } + if err = json.Unmarshal(data, dst); err != nil { + c.logger.Errorf("Get json.Unmarshal error: %v, key: %v", err, key) + return false + } + return true +} diff --git a/db/redis/client.go b/db/redis/client.go new file mode 100644 index 0000000..459d485 --- /dev/null +++ b/db/redis/client.go @@ -0,0 +1,53 @@ +package redis + +import ( + "common/config" + "common/log" + "context" + "github.com/redis/go-redis/v9" + "time" +) + +var instance *Client + +type Client struct { + cli *redis.Client +} + +func Init(cfg *config.RedisConfig) error { + client := redis.NewClient(&redis.Options{ + Addr: cfg.Addr, + Password: cfg.Password, + DB: cfg.DB, + }) + instance = &Client{ + cli: client, + } + cacheInstance = &CacheClient{ + cli: client, + logger: log.GetLogger().Named("CACHE"), + } + + _, err := client.Ping(context.Background()).Result() + return err +} + +func Close() error { + if instance != nil && instance.cli != nil { + return instance.cli.Close() + } + return nil +} + +func GetClient() *Client { + return instance +} + +func (c *Client) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd { + return c.cli.Set(ctx, key, value, expiration) +} + +// Get 获取数据 +func (c *Client) Get(ctx context.Context, key string) *redis.StringCmd { + return c.cli.Get(ctx, key) +} diff --git a/discover/common/define.go b/discover/common/define.go new file mode 100644 index 0000000..1254f89 --- /dev/null +++ b/discover/common/define.go @@ -0,0 +1,42 @@ +package common + +type ListenerType int + +const ( + ListenerTypeNewServer = 1 // 服务启动 + ListenerTypeCloseServer = 2 // 服务关闭 + ListenerTypeNewInstance = 3 // 副本启动 + ListenerTypeCloseInstance = 4 // 副本关闭 +) + +var ( + KeyDiscover = "xh-discover" + KeyDiscoverService = KeyDiscover + "/service" + KeyDiscoverInstance = KeyDiscover + "/instance" +) + +var ( + KeyDiscoverServiceNameGateway = "gateway" // 网关服 + KeyDiscoverServiceNameScene = "scene" // 场景服 + KeyDiscoverServiceNameUser = "user" // 用户中心 +) + +var ( + KeyDiscoverGateway = KeyDiscoverService + "/" + KeyDiscoverServiceNameGateway // 网关服 + KeyDiscoverScene = KeyDiscoverService + "/" + KeyDiscoverServiceNameScene // 场景服 + KeyDiscoverUser = KeyDiscoverService + "/" + KeyDiscoverServiceNameUser // 用户中心 +) + +// ServiceProvider 服务提供者 +type ServiceProvider struct { + Target string + SID int64 + Addr string +} + +// InstanceProvider 副本提供者 +type InstanceProvider struct { + InstanceID int // 副本ID + UniqueNo int64 // 副本唯一编号 + SID string +} diff --git a/discover/common/tool.go b/discover/common/tool.go new file mode 100644 index 0000000..3a1bbc1 --- /dev/null +++ b/discover/common/tool.go @@ -0,0 +1,25 @@ +package common + +import ( + "common/db/etcd" + "common/log" + clientv3 "go.etcd.io/etcd/client/v3" +) + +// NewLeaseAndKeepAlive 创建租约并保活 +func NewLeaseAndKeepAlive(ttl int64) (clientv3.LeaseID, error) { + lease, err := etcd.GetClient().Grant(ttl) + if err != nil { + return 0, err + } + chKeepAlive, err := etcd.GetClient().KeepAlive(lease.ID) + if err != nil { + return 0, err + } + go func(leaseID clientv3.LeaseID) { + for range chKeepAlive { + } + log.Warnf("Lease %x expired or revoked", leaseID) + }(lease.ID) + return lease.ID, nil +} diff --git a/discover/instance.go b/discover/instance.go new file mode 100644 index 0000000..bf2a639 --- /dev/null +++ b/discover/instance.go @@ -0,0 +1,81 @@ +package discover + +import ( + "common/db/etcd" + "common/discover/common" + "common/log" + "fmt" + clientv3 "go.etcd.io/etcd/client/v3" + "strconv" + "sync" +) + +// 大量读少量写的情况下,读写锁比同步Map更高效 +var ( + instanceMU = sync.RWMutex{} + instanceM = make(map[int64]string) // [uniqueNo]sid + instanceLeaseM = make(map[int64]clientv3.LeaseID) // [uniqueNo] +) + +func init() { + RegisterListener(common.ListenerTypeNewInstance, onInstanceStart) + RegisterListener(common.ListenerTypeCloseInstance, onInstanceStop) +} + +// FindInstanceByUniqueNo 根据唯一标识查询副本 +func FindInstanceByUniqueNo(uniqueNO int64) (sid string) { + instanceMU.RLock() + defer instanceMU.RUnlock() + if c, ok := instanceM[uniqueNO]; ok { + return c + } + return +} + +// RegisterInstance 注册副本 +func RegisterInstance(sid int64, instanceID int32, uniqueNo, ttl int64) error { + serverMU.Lock() + defer serverMU.Unlock() + leaseID, err := common.NewLeaseAndKeepAlive(ttl) + if err != nil { + return err + } + key := fmt.Sprintf("%v/%v/%v", common.KeyDiscoverInstance, instanceID, uniqueNo) + _, err = etcd.GetClient().Put(key, strconv.Itoa(int(sid)), clientv3.WithLease(leaseID)) + if err != nil { + return err + } + instanceLeaseM[uniqueNo] = leaseID + return nil +} + +// UnRegisterInstance 解注册副本 +func UnRegisterInstance(uniqueNo int64) { + serverMU.Lock() + defer serverMU.Unlock() + if leaseID, ok := instanceLeaseM[uniqueNo]; ok { + _, err := etcd.GetClient().Revoke(leaseID) + if err != nil { + log.Errorf("UnRegisterInstance err: %v", err) + } + delete(instanceLeaseM, uniqueNo) + } +} + +// 某个副本启动了 +func onInstanceStart(data any) { + if provider, ok := data.(*common.InstanceProvider); ok { + instanceMU.Lock() + defer instanceMU.Unlock() + instanceM[provider.UniqueNo] = provider.SID + } +} + +// 某个副本关闭了 +func onInstanceStop(data any) { + if provider, ok := data.(*common.InstanceProvider); ok { + instanceMU.Lock() + defer instanceMU.Unlock() + delete(instanceM, provider.UniqueNo) + } +} diff --git a/discover/listener.go b/discover/listener.go new file mode 100644 index 0000000..38fde40 --- /dev/null +++ b/discover/listener.go @@ -0,0 +1,130 @@ +package discover + +import ( + "common/db/etcd" + "common/discover/common" + "common/log" + "common/utils" + "context" + "fmt" + "go.etcd.io/etcd/api/v3/mvccpb" + clientv3 "go.etcd.io/etcd/client/v3" + "strconv" + "strings" + "sync" +) + +var ( + wg = &sync.WaitGroup{} + listenerMU = &sync.RWMutex{} + listener = make(map[common.ListenerType][]func(data any)) + stopFunc context.CancelFunc +) + +// RegisterListener 注册服务变动监听 +func RegisterListener(t common.ListenerType, cb func(data any)) { + listenerMU.Lock() + defer listenerMU.Unlock() + arr := listener[t] + if arr == nil { + arr = make([]func(data any), 0) + } + arr = append(arr, cb) + listener[t] = arr +} + +// 根据类型触发回调 +func onCBByType(t common.ListenerType, data any) { + listenerMU.RLock() + defer listenerMU.RUnlock() + for _, f := range listener[t] { + f(data) + } +} + +func Listen() { + var stopCtx context.Context + stopCtx, stopFunc = context.WithCancel(context.Background()) + wg.Add(1) + go func() { + defer wg.Done() + log.Infof(fmt.Sprintf("Discover start listen...")) + // 服务 + serviceAll, _ := etcd.GetClient().Get(common.KeyDiscoverService, clientv3.WithPrefix()) + for _, kv := range serviceAll.Kvs { + onServerChange(clientv3.EventTypePut, string(kv.Key), string(kv.Value)) + } + chService := etcd.GetClient().Watch(common.KeyDiscoverService, clientv3.WithPrefix(), clientv3.WithRev(serviceAll.Header.Revision+1)) + // 副本 + instanceAll, _ := etcd.GetClient().Get(common.KeyDiscoverInstance, clientv3.WithPrefix()) + for _, kv := range instanceAll.Kvs { + onInstanceChange(clientv3.EventTypePut, string(kv.Key), string(kv.Value), nil) + } + chInstance := etcd.GetClient().Watch(common.KeyDiscoverScene, clientv3.WithPrefix(), clientv3.WithRev(instanceAll.Header.Revision+1), clientv3.WithPrevKV()) + for { + select { + case msg := <-chService: + for _, event := range msg.Events { + onServerChange(event.Type, string(event.Kv.Key), string(event.Kv.Value)) + } + case msg := <-chInstance: + for _, event := range msg.Events { + onInstanceChange(event.Type, string(event.Kv.Key), string(event.Kv.Value), event.PrevKv) + } + case <-stopCtx.Done(): + return + } + } + }() +} + +// 服务发生变化 +func onServerChange(t mvccpb.Event_EventType, key, value string) { + split := strings.Split(key, "/") + if len(split) != 4 { + return + } + switch t { + case clientv3.EventTypePut: + onCBByType(common.ListenerTypeNewServer, &common.ServiceProvider{ + Target: common.KeyDiscoverService + "/" + split[2], + SID: utils.StringToInt64(split[3]), + Addr: value, + }) + case clientv3.EventTypeDelete: + onCBByType(common.ListenerTypeCloseServer, &common.ServiceProvider{ + Target: common.KeyDiscoverService + "/" + split[2], + SID: utils.StringToInt64(split[3]), + }) + } +} + +// 副本发生变化 +func onInstanceChange(t mvccpb.Event_EventType, key, value string, preKv *mvccpb.KeyValue) { + split := strings.Split(key, "/") + if len(split) != 4 { + return + } + instanceID, _ := strconv.Atoi(split[2]) + switch t { + case clientv3.EventTypePut: + onCBByType(common.ListenerTypeNewInstance, &common.InstanceProvider{ + InstanceID: instanceID, + UniqueNo: utils.StringToInt64(split[3]), + SID: value, + }) + case clientv3.EventTypeDelete: + onCBByType(common.ListenerTypeCloseInstance, &common.InstanceProvider{ + InstanceID: instanceID, + UniqueNo: utils.StringToInt64(split[3]), + SID: string(preKv.Value), + }) + } +} + +func Close() { + if stopFunc != nil { + stopFunc() + wg.Wait() + } +} diff --git a/discover/server.go b/discover/server.go new file mode 100644 index 0000000..903a370 --- /dev/null +++ b/discover/server.go @@ -0,0 +1,100 @@ +package discover + +import ( + "common/db/etcd" + "common/discover/common" + "common/log" + "common/net/grpc/grpc_conn" + "fmt" + clientv3 "go.etcd.io/etcd/client/v3" + "google.golang.org/grpc" + "sync" +) + +// 大量读少量写的情况下,读写锁比同步Map更高效 +var ( + serverMU = sync.RWMutex{} + conn = make(map[string]*grpc_conn.GrpcConnectionMgr) + serverLeaseM = make(map[int64]clientv3.LeaseID) +) + +func init() { + RegisterListener(common.ListenerTypeNewServer, onServerStart) + RegisterListener(common.ListenerTypeCloseServer, onServerStop) +} + +// FindServer 根据SID或随机查找服务 +func FindServer(target string, sid ...int64) (*grpc.ClientConn, error) { + serverMU.RLock() + defer serverMU.RUnlock() + if v, ok := conn[target]; ok { + return v.Load(sid...) + } + return nil, fmt.Errorf("cannot find server") +} + +func FindServerAll(target string) map[int64]*grpc.ClientConn { + serverMU.RLock() + defer serverMU.RUnlock() + if v, ok := conn[target]; ok { + return v.LoadAll() + } + return make(map[int64]*grpc.ClientConn) +} + +// RegisterGrpcServer 注册服务提供者 +func RegisterGrpcServer(target string, sid int64, addr string, ttl int64) error { + serverMU.Lock() + defer serverMU.Unlock() + leaseID, err := common.NewLeaseAndKeepAlive(ttl) + if err != nil { + return err + } + _, err = etcd.GetClient().Put(fmt.Sprintf("%v/%v", target, sid), addr, clientv3.WithLease(leaseID)) + if err != nil { + return err + } + serverLeaseM[sid] = leaseID + return nil +} + +// UnRegisterGrpcServer 解注册服务提供者 +func UnRegisterGrpcServer(sid int64) { + serverMU.Lock() + defer serverMU.Unlock() + if leaseID, ok := serverLeaseM[sid]; ok { + _, err := etcd.GetClient().Revoke(leaseID) + if err != nil { + log.Errorf("server.go UnRegisterGrpcServer err: %v", err) + } + delete(serverLeaseM, sid) + } +} + +// 某个服务启动了 +func onServerStart(data any) { + if provider, ok := data.(*common.ServiceProvider); ok { + serverMU.Lock() + defer serverMU.Unlock() + if v, ok := conn[provider.Target]; ok { + v.Store(provider.SID, provider.Addr) + } else { + mgr := grpc_conn.NewGrpcConnectionMgr() + mgr.Store(provider.SID, provider.Addr) + conn[provider.Target] = mgr + } + } +} + +// 某个服务关闭了 +func onServerStop(data any) { + if provider, ok := data.(*common.ServiceProvider); ok { + serverMU.Lock() + defer serverMU.Unlock() + if v, ok := conn[provider.Target]; ok { + if v.Delete(provider.SID) == 0 { + delete(conn, provider.Target) + } + } + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e98c6d1 --- /dev/null +++ b/go.mod @@ -0,0 +1,93 @@ +module common + +go 1.23.1 + +require ( + github.com/bwmarrin/snowflake v0.3.0 + github.com/gin-gonic/gin v1.11.0 + github.com/gobwas/ws v1.4.0 + github.com/golang-jwt/jwt/v5 v5.3.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 + github.com/natefinch/lumberjack v2.0.0+incompatible + github.com/panjf2000/gnet/v2 v2.9.7 + github.com/redis/go-redis/v9 v9.10.0 + github.com/spf13/viper v1.21.0 + go.etcd.io/etcd/api/v3 v3.6.1 + go.etcd.io/etcd/client/v3 v3.6.1 + go.mongodb.org/mongo-driver v1.17.6 + go.uber.org/zap v1.27.0 + google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb + google.golang.org/grpc v1.71.1 + google.golang.org/protobuf v1.36.9 + gorm.io/driver/mysql v1.6.0 + gorm.io/gorm v1.31.1 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/BurntSushi/toml v1.2.0 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect + github.com/panjf2000/ants/v2 v2.11.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.54.0 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.1 // indirect + go.uber.org/mock v0.5.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/arch v0.20.0 // indirect + golang.org/x/crypto v0.40.0 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.35.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a9860ac --- /dev/null +++ b/go.sum @@ -0,0 +1,273 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= +github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= +github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= +github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= +github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= +github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg= +github.com/panjf2000/ants/v2 v2.11.3/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek= +github.com/panjf2000/gnet/v2 v2.9.1 h1:bKewICy/0xnQ9PMzNaswpe/Ah14w1TrRk91LHTcbIlA= +github.com/panjf2000/gnet/v2 v2.9.1/go.mod h1:WQTxDWYuQ/hz3eccH0FN32IVuvZ19HewEWx0l62fx7E= +github.com/panjf2000/gnet/v2 v2.9.7 h1:6zW7Jl3oAfXwSuh1PxHLndoL2MQRWx0AJR6aaQjxUgA= +github.com/panjf2000/gnet/v2 v2.9.7/go.mod h1:WQTxDWYuQ/hz3eccH0FN32IVuvZ19HewEWx0l62fx7E= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= +github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= +github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs= +github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +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/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= +github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/etcd/api/v3 v3.6.1 h1:yJ9WlDih9HT457QPuHt/TH/XtsdN2tubyxyQHSHPsEo= +go.etcd.io/etcd/api/v3 v3.6.1/go.mod h1:lnfuqoGsXMlZdTJlact3IB56o3bWp1DIlXPIGKRArto= +go.etcd.io/etcd/client/pkg/v3 v3.6.1 h1:CxDVv8ggphmamrXM4Of8aCC8QHzDM4tGcVr9p2BSoGk= +go.etcd.io/etcd/client/pkg/v3 v3.6.1/go.mod h1:aTkCp+6ixcVTZmrJGa7/Mc5nMNs59PEgBbq+HCmWyMc= +go.etcd.io/etcd/client/v3 v3.6.1 h1:KelkcizJGsskUXlsxjVrSmINvMMga0VWwFF0tSPGEP0= +go.etcd.io/etcd/client/v3 v3.6.1/go.mod h1:fCbPUdjWNLfx1A6ATo9syUmFVxqHH9bCnPLBZmnLmMY= +go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= +go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= +golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= +gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= +gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= +gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= diff --git a/log/level.go b/log/level.go new file mode 100644 index 0000000..b9c5eea --- /dev/null +++ b/log/level.go @@ -0,0 +1,23 @@ +package log + +import ( + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +var logLevelMap = map[string]zapcore.Level{ + "panic": zap.DPanicLevel, + "fatal": zap.FatalLevel, + "error": zap.ErrorLevel, + "warn": zap.WarnLevel, + "info": zap.InfoLevel, + "debug": zap.DebugLevel, +} + +// GetLogLevel get the logLevel from logLevelName +func GetLogLevel(logLevelName string) zapcore.Level { + if v, ok := logLevelMap[logLevelName]; ok { + return v + } + return zap.DebugLevel +} diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..1587078 --- /dev/null +++ b/log/log.go @@ -0,0 +1,66 @@ +package log + +import "go.uber.org/zap" + +var globalLogger *zap.SugaredLogger + +// SetLogger 设置日志记录器 +func SetLogger(logger *zap.SugaredLogger) { + if logger == nil { + return + } + globalLogger = logger +} + +func GetLogger() *zap.SugaredLogger { + return globalLogger +} + +// Debugf 打印调试模板日志 +func Debugf(format string, a ...interface{}) { + if globalLogger != nil { + globalLogger.Debugf(format, a...) + } +} + +// Infof 打印信息模板日志 +func Infof(format string, a ...interface{}) { + if globalLogger != nil { + globalLogger.Infof(format, a...) + } +} + +// Warnf 打印警告模板日志 +func Warnf(format string, a ...interface{}) { + if globalLogger != nil { + globalLogger.Warnf(format, a...) + } +} + +// Errorf 打印错误模板日志 +func Errorf(format string, a ...interface{}) { + if globalLogger != nil { + globalLogger.Errorf(format, a...) + } +} + +// Panicf 打印Panic模板日志 +func Panicf(format string, a ...interface{}) { + if globalLogger != nil { + globalLogger.Panicf(format, a...) + } +} + +// Fatalf 打印致命错误模板日志 +func Fatalf(format string, a ...interface{}) { + if globalLogger != nil { + globalLogger.Fatalf(format, a...) + } +} + +// Close 关闭日志 +func Close() { + if globalLogger != nil { + _ = globalLogger.Sync() + } +} diff --git a/log/log_zap.go b/log/log_zap.go new file mode 100644 index 0000000..116117a --- /dev/null +++ b/log/log_zap.go @@ -0,0 +1,63 @@ +package log + +import ( + "github.com/natefinch/lumberjack" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "os" +) + +func Init(debug bool, maxSize, maxBackups, maxAge int32, level string) { + // 格式配置 + jsonConfig := zapcore.EncoderConfig{ + MessageKey: "M", + LevelKey: "L", + TimeKey: "T", + NameKey: "N", + CallerKey: "C", + FunctionKey: zapcore.OmitKey, + StacktraceKey: "S", + LineEnding: zapcore.DefaultLineEnding, + EncodeLevel: zapcore.CapitalLevelEncoder, + EncodeTime: zapcore.TimeEncoderOfLayout("01-02 15:04:05.000"), + EncodeDuration: zapcore.SecondsDurationEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + EncodeName: func(loggerName string, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString("[" + loggerName + "]") + }, + ConsoleSeparator: " ", + } + + // 日志输出到控制台和文件 + writeSyncer := []zapcore.WriteSyncer{zapcore.AddSync(os.Stdout)} + if !debug { + writeSyncer = append(writeSyncer, zapcore.AddSync(&lumberjack.Logger{ + Filename: "./logs/log.log", // 日志文件位置 + MaxSize: int(maxSize), // 最大文件大小(MB) + MaxBackups: int(maxBackups), // 保留旧文件的最大个数 + MaxAge: int(maxAge), // 保留旧文件的最大天数 + Compress: false, // 是否压缩/归档旧文件 + LocalTime: true, + })) + } + + var encoder zapcore.Encoder + if debug { + encoder = zapcore.NewConsoleEncoder(jsonConfig) + } else { + encoder = zapcore.NewJSONEncoder(jsonConfig) + } + logger := zap.New(zapcore.NewCore( + encoder, + zapcore.NewMultiWriteSyncer(writeSyncer...), + zap.NewAtomicLevelAt(GetLogLevel(level)), + )) + if debug { + logger = logger.WithOptions( + zap.AddCaller(), + zap.AddCallerSkip(1), + zap.AddStacktrace(zapcore.ErrorLevel), + ) + } + SetLogger(logger.Sugar()) +} diff --git a/net/grpc/grpc_conn/conn.go b/net/grpc/grpc_conn/conn.go new file mode 100644 index 0000000..f68a88f --- /dev/null +++ b/net/grpc/grpc_conn/conn.go @@ -0,0 +1,42 @@ +package grpc_conn + +import ( + "common/log" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" + "time" +) + +type GrpcConnection struct { + sid int64 + conn *grpc.ClientConn +} + +func NewGrpcConnection(sid int64, address string) (*GrpcConnection, error) { + p := &GrpcConnection{ + sid: sid, + } + conn, err := grpc.NewClient( + address, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithKeepaliveParams( + keepalive.ClientParameters{ + Time: 30 * time.Second, // 保活探测包发送的时间间隔 + Timeout: 10 * time.Second, // 保活探测包的超时时间 + PermitWithoutStream: true, + }, + ), + //grpc.WithStatsHandler(&StatsHandler{}), + ) + if err != nil { + log.Errorf("create grpc err: %v, sid: %v, addr: %v", err, sid, address) + return nil, err + } + p.conn = conn + return p, nil +} + +func (g *GrpcConnection) GetConnection() *grpc.ClientConn { + return g.conn +} diff --git a/net/grpc/grpc_conn/conn_mgr.go b/net/grpc/grpc_conn/conn_mgr.go new file mode 100644 index 0000000..2a154e4 --- /dev/null +++ b/net/grpc/grpc_conn/conn_mgr.go @@ -0,0 +1,62 @@ +package grpc_conn + +import ( + "common/log" + "fmt" + "google.golang.org/grpc" + "math/rand" +) + +type GrpcConnectionMgr struct { + poolM map[int64]*GrpcConnection + poolS []*GrpcConnection +} + +func NewGrpcConnectionMgr() *GrpcConnectionMgr { + return &GrpcConnectionMgr{ + poolM: make(map[int64]*GrpcConnection), + poolS: make([]*GrpcConnection, 0), + } +} + +func (p *GrpcConnectionMgr) Store(sid int64, addr string) { + pool, err := NewGrpcConnection(sid, addr) + if err != nil { + log.Errorf("create grpc err: %v, sid: %v, addr: %v", err, sid, addr) + return + } + p.poolM[sid] = pool + p.poolS = append(p.poolS, pool) +} + +func (p *GrpcConnectionMgr) Delete(sid int64) int { + delete(p.poolM, sid) + for i, pool := range p.poolS { + if pool.sid == sid { + p.poolS = append(p.poolS[:i], p.poolS[i+1:]...) + break + } + } + return len(p.poolS) +} + +func (p *GrpcConnectionMgr) Load(sid ...int64) (*grpc.ClientConn, error) { + var pool *GrpcConnection + if len(sid) > 0 && sid[0] > 0 { + pool = p.poolM[sid[0]] + } else { + pool = p.poolS[rand.Intn(len(p.poolS))] + } + if pool == nil { + return nil, fmt.Errorf("cannot find connection") + } + return pool.GetConnection(), nil +} + +func (p *GrpcConnectionMgr) LoadAll() map[int64]*grpc.ClientConn { + sidM := make(map[int64]*grpc.ClientConn) + for sid, pool := range p.poolM { + sidM[sid] = pool.GetConnection() + } + return sidM +} diff --git a/net/grpc/resolver/conn.go b/net/grpc/resolver/conn.go new file mode 100644 index 0000000..b9a97a9 --- /dev/null +++ b/net/grpc/resolver/conn.go @@ -0,0 +1,30 @@ +package resolver + +import ( + "common/log" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" + "time" +) + +func NewGrpcConnection(target string) (*grpc.ClientConn, error) { + cc, err := grpc.NewClient( + target, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin": {}}]}`), + grpc.WithKeepaliveParams( + keepalive.ClientParameters{ + Time: 30 * time.Second, // 保活探测包发送的时间间隔 + Timeout: 10 * time.Second, // 保活探测包的超时时间 + PermitWithoutStream: true, + }, + ), + //grpc.WithStatsHandler(&StatsHandler{}), + ) + if err != nil { + log.Errorf("create grpc err: %v, target: %v", err, target) + return nil, err + } + return cc, nil +} diff --git a/net/grpc/resolver/etcd_resolver.go b/net/grpc/resolver/etcd_resolver.go new file mode 100644 index 0000000..40bdcec --- /dev/null +++ b/net/grpc/resolver/etcd_resolver.go @@ -0,0 +1,84 @@ +package resolver + +import ( + "common/db/etcd" + "common/discover/common" + "common/log" + "context" + "go.etcd.io/etcd/client/v3" + "google.golang.org/grpc/resolver" + "strings" +) + +const etcdSchema = "etcd" + +func init() { + resolver.Register(&etcdBuilder{}) +} + +type etcdBuilder struct{} + +func (*etcdBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { + serviceName := strings.TrimPrefix(target.URL.Path, "/") + r := &etcdResolver{ + serviceName: serviceName, + cc: cc, + } + r.start() + return r, nil +} + +func (*etcdBuilder) Scheme() string { return etcdSchema } + +type etcdResolver struct { + serviceName string + cc resolver.ClientConn + ctx context.Context + cancel context.CancelFunc +} + +func (r *etcdResolver) start() { + r.ctx, r.cancel = context.WithCancel(context.Background()) + r.update() + go r.watch() +} + +func (r *etcdResolver) getPrefix() string { + return common.KeyDiscoverService + "/" + r.serviceName +} + +func (r *etcdResolver) update() { + resp, err := etcd.GetClient().Get(r.getPrefix(), clientv3.WithPrefix()) + if err != nil { + log.Errorf("etcd resolver get error: %v", err) + return + } + + var addrArray []resolver.Address + for _, kv := range resp.Kvs { + addr := string(kv.Value) + if addr != "" { + addrArray = append(addrArray, resolver.Address{Addr: addr}) + } + } + + _ = r.cc.UpdateState(resolver.State{Addresses: addrArray}) +} + +func (r *etcdResolver) watch() { + watchCh := etcd.GetClient().Watch(r.getPrefix(), clientv3.WithPrefix()) + for w := range watchCh { + if w.Err() != nil { + continue + } + r.update() + } +} + +func (r *etcdResolver) ResolveNow(resolver.ResolveNowOptions) { + r.update() +} + +func (r *etcdResolver) Close() { + r.cancel() +} diff --git a/net/grpc/resolver/resolver_mgr.go b/net/grpc/resolver/resolver_mgr.go new file mode 100644 index 0000000..d2371b2 --- /dev/null +++ b/net/grpc/resolver/resolver_mgr.go @@ -0,0 +1,35 @@ +package resolver + +import ( + "google.golang.org/grpc" + "sync" +) + +var ( + mu = sync.RWMutex{} + conn = make(map[string]*grpc.ClientConn) +) + +func GetGrpcClientConn(target string) (*grpc.ClientConn, error) { + mu.RLock() + if c, ok := conn[target]; ok && c != nil { + mu.RUnlock() + return c, nil + } + mu.RUnlock() + + mu.Lock() + defer mu.Unlock() + + if c, ok := conn[target]; ok && c != nil { + return c, nil + } + + newConn, err := NewGrpcConnection(target) + if err != nil { + return nil, err + } + + conn[target] = newConn + return newConn, nil +} diff --git a/net/grpc/service/client_gateway.go b/net/grpc/service/client_gateway.go new file mode 100644 index 0000000..8bed0a6 --- /dev/null +++ b/net/grpc/service/client_gateway.go @@ -0,0 +1,24 @@ +package service + +import ( + "common/discover" + "common/discover/common" + "common/proto/ss/grpc_pb" +) + +func GatewayNewClient(sid ...int64) (grpc_pb.GatewayClient, error) { + c, err := discover.FindServer(common.KeyDiscoverGateway, sid...) + if err != nil { + return nil, err + } + return grpc_pb.NewGatewayClient(c), nil +} + +func GatewayNewBroadcastClient() map[int64]grpc_pb.GatewayClient { + clientM := make(map[int64]grpc_pb.GatewayClient) + connM := discover.FindServerAll(common.KeyDiscoverGateway) + for sid, conn := range connM { + clientM[sid] = grpc_pb.NewGatewayClient(conn) + } + return clientM +} diff --git a/net/grpc/service/client_scene.go b/net/grpc/service/client_scene.go new file mode 100644 index 0000000..b7df99c --- /dev/null +++ b/net/grpc/service/client_scene.go @@ -0,0 +1,33 @@ +package service + +import ( + "common/discover" + "common/discover/common" + "common/net/grpc/resolver" + "common/proto/ss/grpc_pb" +) + +func SceneNewClient(sid ...int64) (grpc_pb.SceneClient, error) { + c, err := discover.FindServer(common.KeyDiscoverScene, sid...) + if err != nil { + return nil, err + } + return grpc_pb.NewSceneClient(c), nil +} + +func SceneNewClientLB() (grpc_pb.SceneClient, error) { + c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameScene) + if err != nil { + return nil, err + } + return grpc_pb.NewSceneClient(c), nil +} + +func SceneNewBroadcastClient() map[int64]grpc_pb.SceneClient { + clientM := make(map[int64]grpc_pb.SceneClient) + connM := discover.FindServerAll(common.KeyDiscoverScene) + for sid, conn := range connM { + clientM[sid] = grpc_pb.NewSceneClient(conn) + } + return clientM +} diff --git a/net/grpc/service/client_user.go b/net/grpc/service/client_user.go new file mode 100644 index 0000000..fd470bb --- /dev/null +++ b/net/grpc/service/client_user.go @@ -0,0 +1,24 @@ +package service + +import ( + "common/discover" + "common/discover/common" + "common/net/grpc/resolver" + "common/proto/ss/grpc_pb" +) + +func UserNewClient(sid ...int64) (grpc_pb.UserClient, error) { + c, err := discover.FindServer(common.KeyDiscoverUser, sid...) + if err != nil { + return nil, err + } + return grpc_pb.NewUserClient(c), nil +} + +func UserNewClientLB() (grpc_pb.UserClient, error) { + c, err := resolver.GetGrpcClientConn("etcd:///" + common.KeyDiscoverServiceNameUser) + if err != nil { + return nil, err + } + return grpc_pb.NewUserClient(c), nil +} diff --git a/net/grpc/service/service.go b/net/grpc/service/service.go new file mode 100644 index 0000000..8c9e4d8 --- /dev/null +++ b/net/grpc/service/service.go @@ -0,0 +1,88 @@ +package service + +import ( + "common/discover" + "common/log" + "common/utils" + "context" + "fmt" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/status" + "net" + "sync" + "time" +) + +type IService interface { + Init(addr string, port int32) + Close() +} + +type Base struct { + Target string + SID int64 + Serve *grpc.Server + EtcdTTL int64 + OnInit func(serve *grpc.Server) + OnClose func() + + wg *sync.WaitGroup +} + +func (s *Base) Init(addr string, port int32) { + s.wg = &sync.WaitGroup{} + s.wg.Add(1) + s.SID = utils.SnowflakeInstance().Generate().Int64() + go func() { + defer s.wg.Done() + defer s.OnClose() + defer discover.UnRegisterGrpcServer(s.SID) + + // 监听端口 + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + log.Errorf("%v ListenPort err: %v", s.Target, err) + return + } + + s.Serve = grpc.NewServer( + grpc.UnaryInterceptor( + func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + defer func() { + if r := recover(); r != nil { + log.Errorf("server Panic: %v", r) + err = status.Error(codes.Internal, fmt.Sprintf("%v", r)) + } + }() + resp, err = handler(ctx, req) + return + }, + ), + grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ + MinTime: 20 * time.Second, + PermitWithoutStream: true, + }), + ) + s.OnInit(s.Serve) + + // 服务注册 + if err = discover.RegisterGrpcServer(s.Target, s.SID, fmt.Sprintf("%v:%d", addr, port), s.EtcdTTL); err != nil { + log.Errorf("%v RegisterGrpcServer err: %v", s.Target, err) + return + } + if err = s.Serve.Serve(lis); err != nil { + log.Errorf("%v Serve err: %v", s.Target, err) + return + } + log.Infof("%v server stop.", s.Target) + }() +} + +func (s *Base) Close() { + if s.Serve != nil { + s.Serve.Stop() + s.wg.Wait() + } +} diff --git a/net/http/http_resp/code.go b/net/http/http_resp/code.go new file mode 100644 index 0000000..6bec18e --- /dev/null +++ b/net/http/http_resp/code.go @@ -0,0 +1,47 @@ +package http_resp + +import ( + "common/proto/ss/ss_common" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + OK = NewCode(0, "OK") + Failed = NewCode(1, "Failed") + TokenInvalid = NewCode(2, "Token无效") + ParamError = NewCode(1001, "参数错误") + NameEmpty = NewCode(1002, "名称不能为空") + NameDuplicate = NewCode(1003, "名称或编号不能重复") + ListEmpty = NewCode(1004, "列表不能为空") + RepeatCommit = NewCode(1005, "请勿重复提交") +) + +type Code struct { + code int + error string +} + +func NewCode(code int, error string) *Code { + return &Code{ + code: code, + error: error, + } +} + +func (c *Code) Code() int { + return c.code +} + +func (c *Code) Error() string { + return c.error +} + +func (c *Code) Wrap() error { + st := status.New(codes.Unknown, c.Error()) + st, _ = st.WithDetails(&ss_common.ErrorInfo{ + Code: int32(c.Code()), + Msg: c.Error(), + }) + return st.Err() +} diff --git a/net/http/http_resp/response.go b/net/http/http_resp/response.go new file mode 100644 index 0000000..25d5995 --- /dev/null +++ b/net/http/http_resp/response.go @@ -0,0 +1,47 @@ +package http_resp + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +type RespJsonData struct { + Code int `json:"code"` + Msg string `json:"msg"` + Data interface{} `json:"data,omitempty"` +} + +func Success(data interface{}) *RespJsonData { + return &RespJsonData{ + Code: OK.Code(), + Msg: OK.Error(), + Data: data, + } +} + +func Error(code *Code) *RespJsonData { + return &RespJsonData{ + Code: code.Code(), + Msg: code.Error(), + } +} + +func JsonOK(c *gin.Context, data *RespJsonData) { + c.JSON(http.StatusOK, data) +} + +func JsonBadRequest(c *gin.Context) { + c.JSON(http.StatusBadRequest, Error(ParamError)) +} + +func JsonMethodNotAllowed(c *gin.Context) { + c.JSON(http.StatusMethodNotAllowed, Error(NewCode(Failed.Code(), "Method Not Allowed"))) +} + +func JsonNotFound(c *gin.Context) { + c.JSON(http.StatusNotFound, Error(NewCode(Failed.Code(), "Endpoint Not Found"))) +} + +func AbortUnauthorized(c *gin.Context) { + c.AbortWithStatusJSON(http.StatusUnauthorized, Error(NewCode(Failed.Code(), "Invalid Authorization"))) +} diff --git a/net/socket/server.go b/net/socket/server.go new file mode 100644 index 0000000..488d16b --- /dev/null +++ b/net/socket/server.go @@ -0,0 +1,48 @@ +package socket + +import ( + "time" +) + +type Action int + +const ( + // None indicates that no action should occur following an event. + None Action = iota + // Close closes the connection. + Close + // Shutdown shutdowns the engine. + Shutdown +) + +type OpCode byte + +const ( + OpContinuation OpCode = 0x0 + OpText OpCode = 0x1 + OpBinary OpCode = 0x2 + OpClose OpCode = 0x8 + OpPing OpCode = 0x9 + OpPong OpCode = 0xa +) + +// ISocketServer 由应用层实现 +type ISocketServer interface { + OnOpen(ISocketConn) ([]byte, Action) // 开启连接 + OnHandShake(ISocketConn, []byte, func(ISocketConn, []byte)) Action // 开始握手 + OnMessage(ISocketConn, []byte) Action // 收到消息 + OnPong(ISocketConn) + OnClose(ISocketConn, error) Action // 关闭连接 + OnTick() (time.Duration, Action) +} + +// ISocketConn 由网络层实现 +type ISocketConn interface { + GetParam(key string) interface{} + SetParam(key string, values interface{}) + RemoteAddr() string + Ping() error // 需要隔一段时间调用一下,建议20s + Write(data []byte) error + Close() error + IsClose() bool +} diff --git a/net/socket/websocket/websocket.go b/net/socket/websocket/websocket.go new file mode 100644 index 0000000..b918bec --- /dev/null +++ b/net/socket/websocket/websocket.go @@ -0,0 +1,187 @@ +package websocket + +import ( + "bytes" + "common/net/socket" + "context" + "github.com/panjf2000/gnet/v2" + "github.com/panjf2000/gnet/v2/pkg/logging" + "sync" + "time" +) + +// WSServer 实现GNet库接口 +type WSServer struct { + eng gnet.Engine + i socket.ISocketServer + logger logging.Logger // 日志 + upgradeTimeout time.Duration // 升级超时时间 + unUpgradeConn sync.Map +} + +func NewWSServer(i socket.ISocketServer, logger logging.Logger, upgradeTimeout time.Duration) *WSServer { + if i == nil { + return nil + } + return &WSServer{ + i: i, + logger: logger, + upgradeTimeout: upgradeTimeout, + unUpgradeConn: sync.Map{}, + } +} + +func (s *WSServer) Run(addr string, multicore bool, numEventLoop int, tcpNoDelay gnet.TCPSocketOpt, readBufferCap, writeBufferCap int, lockOSThread bool, reusePort, ticker bool, logger logging.Logger) error { + return gnet.Run( + s, + addr, + gnet.WithMulticore(multicore), + gnet.WithNumEventLoop(numEventLoop), + gnet.WithTCPNoDelay(tcpNoDelay), + gnet.WithReadBufferCap(readBufferCap), + gnet.WithWriteBufferCap(writeBufferCap), + gnet.WithLockOSThread(lockOSThread), + gnet.WithReusePort(reusePort), + gnet.WithTicker(ticker), + gnet.WithLogger(logger), + ) +} + +func (s *WSServer) Stop() error { + return s.eng.Stop(context.Background()) +} + +func (s *WSServer) OnBoot(eng gnet.Engine) gnet.Action { + s.eng = eng + return gnet.None +} + +func (s *WSServer) OnShutdown(_ gnet.Engine) { +} + +func (s *WSServer) OnOpen(c gnet.Conn) ([]byte, gnet.Action) { + ws := &WSConn{ + Conn: c, + isUpgrade: false, + openTime: time.Now().Unix(), + buf: bytes.Buffer{}, + logger: s.logger, + wsMessageBuf: wsMessageBuf{ + curHeader: nil, + cachedBuf: bytes.Buffer{}, + }, + param: make(map[string]interface{}), + remoteAddr: c.RemoteAddr().String(), + } + c.SetContext(ws) + s.unUpgradeConn.Store(c.RemoteAddr().String(), ws) + d, a := s.i.OnOpen(ws) + return d, (gnet.Action)(a) +} + +// OnClose fires when a connection has been closed. +// The parameter err is the last known connection error. +func (s *WSServer) OnClose(c gnet.Conn, err error) (action gnet.Action) { + s.unUpgradeConn.Delete(c.RemoteAddr().String()) + ws, ok := c.Context().(*WSConn) + if ok { + ws.isClose = true + ws.logger.Warnf("connection close, err: %v", err) + return gnet.Action(s.i.OnClose(ws, err)) + } + return +} + +// OnTraffic fires when a local socket receives data from the peer. +func (s *WSServer) OnTraffic(c gnet.Conn) gnet.Action { + ws := c.Context().(*WSConn) + if action := ws.readBytesBuf(c); action != gnet.None { + return action + } + + if !ws.isUpgrade { + data, action := ws.upgrade() + if len(data) > 0 { + s.unUpgradeConn.Delete(c.RemoteAddr().String()) + action = gnet.Action(s.i.OnHandShake(ws, data, s.OnHandShakeFinish)) + } + return action + } + + if msg, err := ws.readWsMessages(); err != nil { + ws.logger.Errorf("read ws messages err: %v", err) + return gnet.Close + } else if msg != nil { + for _, m := range msg { + if socket.OpCode(m.OpCode) == socket.OpPong { + s.i.OnPong(ws) + continue + } + if socket.OpCode(m.OpCode) == socket.OpClose { + return gnet.Close + } + if socket.OpCode(m.OpCode) == socket.OpPing { + continue + } + a := s.i.OnMessage(ws, m.Payload) + if gnet.Action(a) != gnet.None { + return gnet.Action(a) + } + } + } + return gnet.None +} + +// OnTick fires immediately after the engine starts and will fire again +// following the duration specified by the delay return value. +func (s *WSServer) OnTick() (delay time.Duration, action gnet.Action) { + now := time.Now().Unix() + + delConn := make([]string, 0) + s.unUpgradeConn.Range(func(key, value interface{}) bool { + k, ok := key.(string) + if !ok { + return true + } + + v, ok := value.(*WSConn) + if !ok { + return true + } + if now-v.openTime >= int64(s.upgradeTimeout.Seconds()) { + delConn = append(delConn, k) + } + return true + }) + + for _, k := range delConn { + wsConn, _ := s.unUpgradeConn.LoadAndDelete(k) + if wsConn == nil { + continue + } + + v, ok := wsConn.(*WSConn) + if !ok { + continue + } + if err := v.Close(); err != nil { + v.logger.Errorf("upgrade ws time out close socket error: %v", err) + } + } + d, a := s.i.OnTick() + delay = d + action = gnet.Action(a) + + return +} + +// OnHandShakeFinish 握手完成 +func (s *WSServer) OnHandShakeFinish(conn socket.ISocketConn, hsResp []byte) { + ws := conn.(*WSConn) + if err := ws.Conn.AsyncWrite(hsResp, nil); err != nil { + ws.logger.Errorf("OnHandShakeFinish err: %v", err) + if err = ws.Close(); err != nil { + ws.logger.Errorf("OnHandShakeFinish Close error: %v", err) + } + } +} diff --git a/net/socket/websocket/wsconn.go b/net/socket/websocket/wsconn.go new file mode 100644 index 0000000..4e2fdcb --- /dev/null +++ b/net/socket/websocket/wsconn.go @@ -0,0 +1,202 @@ +package websocket + +import ( + "bufio" + "bytes" + "errors" + "github.com/gobwas/ws" + "github.com/gobwas/ws/wsutil" + "github.com/panjf2000/gnet/v2" + "github.com/panjf2000/gnet/v2/pkg/logging" + "io" + "net/url" +) + +// WSConn 实现ISocketConn接口 +type WSConn struct { + gnet.Conn + buf bytes.Buffer + logger logging.Logger + isUpgrade bool // 是否已经升级 + upgradeResp []byte // 升级响应 + isClose bool + param map[string]interface{} + openTime int64 // 开启连接的时间 + remoteAddr string // 远程ID地址 + wsMessageBuf +} + +type wsMessageBuf struct { + curHeader *ws.Header + cachedBuf bytes.Buffer +} + +type readWrite struct { + io.Reader + io.Writer +} + +func (w *WSConn) readBytesBuf(c gnet.Conn) gnet.Action { + size := c.InboundBuffered() + if size <= 0 { + return gnet.None + } + buf := make([]byte, size) + + read, err := c.Read(buf) + if err != nil { + if w.logger != nil { + w.logger.Errorf("ws read bytes buf error", err) + } + return gnet.Close + } + + if read < size { + if w.logger != nil { + w.logger.Errorf("read bytes len err! size: %d read: %d", size, read) + } + return gnet.Close + } + w.buf.Write(buf) + return gnet.None +} + +func (w *WSConn) upgrade() (data []byte, action gnet.Action) { + buf := &w.buf + tmpReader := bytes.NewReader(buf.Bytes()) + oldLen := tmpReader.Len() + result := &bytes.Buffer{} + tempWriter := bufio.NewWriter(result) + + var err error = nil + up := ws.Upgrader{ + OnRequest: w.OnRequest, + } + _, err = up.Upgrade(readWrite{tmpReader, tempWriter}) + skipN := oldLen - tmpReader.Len() + if err != nil { + if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { //数据不完整 + return + } + buf.Next(skipN) + if w.logger != nil { + w.logger.Errorf("ws upgrade err: %v", err.Error()) + } + + action = gnet.Close + return + } + buf.Next(skipN) + //if w.logger != nil { + // w.logger.Infof("ws upgrade success conn upgrade websocket protocol!") + //} + _ = tempWriter.Flush() + data = result.Bytes() + w.isUpgrade = true + return +} + +func (w *WSConn) readWsMessages() (messages []wsutil.Message, err error) { + in := &w.buf + for { + if w.curHeader == nil { + if in.Len() < ws.MinHeaderSize { //头长度至少是2 + return + } + var head ws.Header + //有可能不完整,构建新的 reader 读取 head 读取成功才实际对 in 进行读操作 + tmpReader := bytes.NewReader(in.Bytes()) + oldLen := tmpReader.Len() + head, err = ws.ReadHeader(tmpReader) + skipN := oldLen - tmpReader.Len() + if err != nil { + if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { //数据不完整 + return messages, nil + } + in.Next(skipN) + return nil, err + } + _, err = io.CopyN(&w.cachedBuf, in, int64(skipN)) + if err != nil { + return + } + + w.curHeader = &head + } + dataLen := (int)(w.curHeader.Length) + if dataLen > 0 { + if in.Len() >= dataLen { + _, err = io.CopyN(&w.cachedBuf, in, int64(dataLen)) + if err != nil { + return + } + } else { //数据不完整 + if w.logger != nil { + w.logger.Debugf("ws read ws message incomplete data", in.Len(), dataLen) + } + return + } + } + if w.curHeader.Fin { //当前 header 已经是一个完整消息 + messages, err = wsutil.ReadClientMessage(&w.cachedBuf, messages) + if err != nil { + return nil, err + } + w.cachedBuf.Reset() + } + w.curHeader = nil + } +} + +func (w *WSConn) OnRequest(u []byte) error { + parsedURL, err := url.Parse(string(u)) + if err != nil { + return err + } + for key, value := range parsedURL.Query() { + w.SetParam(key, value[0]) + } + return nil +} + +func (w *WSConn) GetParam(key string) interface{} { + return w.param[key] +} + +func (w *WSConn) SetParam(key string, values interface{}) { + w.param[key] = values +} + +func (w *WSConn) RemoteAddr() string { + return w.remoteAddr +} + +func (w *WSConn) Write(data []byte) error { + return w.write(data, ws.OpBinary) +} + +func (w *WSConn) Ping() (err error) { + return w.write(make([]byte, 0), ws.OpPing) +} + +func (w *WSConn) Close() (err error) { + defer func(Conn gnet.Conn) { + err = Conn.Close() + }(w.Conn) + return w.write(make([]byte, 0), ws.OpClose) +} + +func (w *WSConn) IsClose() bool { + return w.isClose +} + +func (w *WSConn) write(data []byte, opCode ws.OpCode) error { + if w.isClose { + return errors.New("connection has close") + } + buf := bytes.Buffer{} + if err := wsutil.WriteServerMessage(&buf, opCode, data); err != nil { + return err + } + return w.Conn.AsyncWrite(buf.Bytes(), nil) +} diff --git a/proto/sc/sc_common/sc_common.pb.go b/proto/sc/sc_common/sc_common.pb.go new file mode 100644 index 0000000..dccafd4 --- /dev/null +++ b/proto/sc/sc_common/sc_common.pb.go @@ -0,0 +1,62 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: sc_common.proto + +package sc_common + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" +) + +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) +) + +var File_sc_common_proto protoreflect.FileDescriptor + +var file_sc_common_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x73, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x42, 0x1b, 0x5a, 0x19, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x73, 0x63, 0x2f, 0x73, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var file_sc_common_proto_goTypes = []interface{}{} +var file_sc_common_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_sc_common_proto_init() } +func file_sc_common_proto_init() { + if File_sc_common_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_sc_common_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_sc_common_proto_goTypes, + DependencyIndexes: file_sc_common_proto_depIdxs, + }.Build() + File_sc_common_proto = out.File + file_sc_common_proto_rawDesc = nil + file_sc_common_proto_goTypes = nil + file_sc_common_proto_depIdxs = nil +} diff --git a/proto/sc/sc_pb/action.pb.go b/proto/sc/sc_pb/action.pb.go new file mode 100644 index 0000000..8775099 --- /dev/null +++ b/proto/sc/sc_pb/action.pb.go @@ -0,0 +1,521 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: action.proto + +package sc_pb + +import ( + _ "common/proto/sc/sc_common" + 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) +) + +// MESSAGE_ID_ACTION +type ActionID int32 + +const ( + ActionID_ACTION_ID_MOVE ActionID = 0 // 移动 + ActionID_ACTION_ID_ATTACK ActionID = 1 // 攻击 +) + +// Enum value maps for ActionID. +var ( + ActionID_name = map[int32]string{ + 0: "ACTION_ID_MOVE", + 1: "ACTION_ID_ATTACK", + } + ActionID_value = map[string]int32{ + "ACTION_ID_MOVE": 0, + "ACTION_ID_ATTACK": 1, + } +) + +func (x ActionID) Enum() *ActionID { + p := new(ActionID) + *p = x + return p +} + +func (x ActionID) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ActionID) Descriptor() protoreflect.EnumDescriptor { + return file_action_proto_enumTypes[0].Descriptor() +} + +func (ActionID) Type() protoreflect.EnumType { + return &file_action_proto_enumTypes[0] +} + +func (x ActionID) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ActionID.Descriptor instead. +func (ActionID) EnumDescriptor() ([]byte, []int) { + return file_action_proto_rawDescGZIP(), []int{0} +} + +// MESSAGE_ID_ENTER_INSTANCE +type C2S_EnterInstance struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InstanceID int32 `protobuf:"varint,1,opt,name=InstanceID,proto3" json:"InstanceID,omitempty"` +} + +func (x *C2S_EnterInstance) Reset() { + *x = C2S_EnterInstance{} + if protoimpl.UnsafeEnabled { + mi := &file_action_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *C2S_EnterInstance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*C2S_EnterInstance) ProtoMessage() {} + +func (x *C2S_EnterInstance) ProtoReflect() protoreflect.Message { + mi := &file_action_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 C2S_EnterInstance.ProtoReflect.Descriptor instead. +func (*C2S_EnterInstance) Descriptor() ([]byte, []int) { + return file_action_proto_rawDescGZIP(), []int{0} +} + +func (x *C2S_EnterInstance) GetInstanceID() int32 { + if x != nil { + return x.InstanceID + } + return 0 +} + +type S2C_EnterInstance struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Info *PositionInfo `protobuf:"bytes,1,opt,name=Info,proto3" json:"Info,omitempty"` +} + +func (x *S2C_EnterInstance) Reset() { + *x = S2C_EnterInstance{} + if protoimpl.UnsafeEnabled { + mi := &file_action_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *S2C_EnterInstance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*S2C_EnterInstance) ProtoMessage() {} + +func (x *S2C_EnterInstance) ProtoReflect() protoreflect.Message { + mi := &file_action_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 S2C_EnterInstance.ProtoReflect.Descriptor instead. +func (*S2C_EnterInstance) Descriptor() ([]byte, []int) { + return file_action_proto_rawDescGZIP(), []int{1} +} + +func (x *S2C_EnterInstance) GetInfo() *PositionInfo { + if x != nil { + return x.Info + } + return nil +} + +type C2S_Action struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sequence uint32 `protobuf:"varint,1,opt,name=Sequence,proto3" json:"Sequence,omitempty"` // 指令序号 + Timestamp int64 `protobuf:"varint,2,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"` // 时间戳(毫秒) + Action ActionID `protobuf:"varint,3,opt,name=Action,proto3,enum=ActionID" json:"Action,omitempty"` // 指令ID + DirX int32 `protobuf:"zigzag32,4,opt,name=DirX,proto3" json:"DirX,omitempty"` // 移动-X方向(×100 缩放) + DirY int32 `protobuf:"zigzag32,5,opt,name=DirY,proto3" json:"DirY,omitempty"` // 移动-Y方向(×100 缩放) + SkillID int32 `protobuf:"varint,6,opt,name=SkillID,proto3" json:"SkillID,omitempty"` // 攻击-技能ID +} + +func (x *C2S_Action) Reset() { + *x = C2S_Action{} + if protoimpl.UnsafeEnabled { + mi := &file_action_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *C2S_Action) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*C2S_Action) ProtoMessage() {} + +func (x *C2S_Action) ProtoReflect() protoreflect.Message { + mi := &file_action_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 C2S_Action.ProtoReflect.Descriptor instead. +func (*C2S_Action) Descriptor() ([]byte, []int) { + return file_action_proto_rawDescGZIP(), []int{2} +} + +func (x *C2S_Action) GetSequence() uint32 { + if x != nil { + return x.Sequence + } + return 0 +} + +func (x *C2S_Action) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *C2S_Action) GetAction() ActionID { + if x != nil { + return x.Action + } + return ActionID_ACTION_ID_MOVE +} + +func (x *C2S_Action) GetDirX() int32 { + if x != nil { + return x.DirX + } + return 0 +} + +func (x *C2S_Action) GetDirY() int32 { + if x != nil { + return x.DirY + } + return 0 +} + +func (x *C2S_Action) GetSkillID() int32 { + if x != nil { + return x.SkillID + } + return 0 +} + +// MESSAGE_ID_POSITION +type PositionInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + USN int64 `protobuf:"varint,1,opt,name=USN,proto3" json:"USN,omitempty"` + X int32 `protobuf:"zigzag32,2,opt,name=X,proto3" json:"X,omitempty"` + Y int32 `protobuf:"zigzag32,3,opt,name=Y,proto3" json:"Y,omitempty"` +} + +func (x *PositionInfo) Reset() { + *x = PositionInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_action_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PositionInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PositionInfo) ProtoMessage() {} + +func (x *PositionInfo) ProtoReflect() protoreflect.Message { + mi := &file_action_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 PositionInfo.ProtoReflect.Descriptor instead. +func (*PositionInfo) Descriptor() ([]byte, []int) { + return file_action_proto_rawDescGZIP(), []int{3} +} + +func (x *PositionInfo) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +func (x *PositionInfo) GetX() int32 { + if x != nil { + return x.X + } + return 0 +} + +func (x *PositionInfo) GetY() int32 { + if x != nil { + return x.Y + } + return 0 +} + +type S2C_Position struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Info []*PositionInfo `protobuf:"bytes,1,rep,name=Info,proto3" json:"Info,omitempty"` +} + +func (x *S2C_Position) Reset() { + *x = S2C_Position{} + if protoimpl.UnsafeEnabled { + mi := &file_action_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *S2C_Position) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*S2C_Position) ProtoMessage() {} + +func (x *S2C_Position) ProtoReflect() protoreflect.Message { + mi := &file_action_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 S2C_Position.ProtoReflect.Descriptor instead. +func (*S2C_Position) Descriptor() ([]byte, []int) { + return file_action_proto_rawDescGZIP(), []int{4} +} + +func (x *S2C_Position) GetInfo() []*PositionInfo { + if x != nil { + return x.Info + } + return nil +} + +var File_action_proto protoreflect.FileDescriptor + +var file_action_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, + 0x73, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x33, 0x0a, 0x11, 0x43, 0x32, 0x53, 0x5f, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x49, 0x44, 0x22, 0x36, 0x0a, 0x11, 0x53, 0x32, 0x43, 0x5f, 0x45, 0x6e, 0x74, 0x65, + 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x49, 0x6e, 0x66, + 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xab, 0x01, 0x0a, + 0x0a, 0x43, 0x32, 0x53, 0x5f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x53, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x53, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x21, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, + 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x69, 0x72, 0x58, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x11, 0x52, 0x04, 0x44, 0x69, 0x72, 0x58, 0x12, 0x12, 0x0a, 0x04, + 0x44, 0x69, 0x72, 0x59, 0x18, 0x05, 0x20, 0x01, 0x28, 0x11, 0x52, 0x04, 0x44, 0x69, 0x72, 0x59, + 0x12, 0x18, 0x0a, 0x07, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x44, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x07, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x44, 0x22, 0x3c, 0x0a, 0x0c, 0x50, 0x6f, + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x53, + 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x55, 0x53, 0x4e, 0x12, 0x0c, 0x0a, 0x01, + 0x58, 0x18, 0x02, 0x20, 0x01, 0x28, 0x11, 0x52, 0x01, 0x58, 0x12, 0x0c, 0x0a, 0x01, 0x59, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x01, 0x59, 0x22, 0x31, 0x0a, 0x0c, 0x53, 0x32, 0x43, 0x5f, + 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x2a, 0x34, 0x0a, 0x08, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x49, 0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, + 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x44, 0x5f, 0x41, 0x54, 0x54, 0x41, 0x43, 0x4b, 0x10, + 0x01, 0x42, 0x17, 0x5a, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x73, 0x63, 0x2f, 0x73, 0x63, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_action_proto_rawDescOnce sync.Once + file_action_proto_rawDescData = file_action_proto_rawDesc +) + +func file_action_proto_rawDescGZIP() []byte { + file_action_proto_rawDescOnce.Do(func() { + file_action_proto_rawDescData = protoimpl.X.CompressGZIP(file_action_proto_rawDescData) + }) + return file_action_proto_rawDescData +} + +var file_action_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_action_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_action_proto_goTypes = []interface{}{ + (ActionID)(0), // 0: ActionID + (*C2S_EnterInstance)(nil), // 1: C2S_EnterInstance + (*S2C_EnterInstance)(nil), // 2: S2C_EnterInstance + (*C2S_Action)(nil), // 3: C2S_Action + (*PositionInfo)(nil), // 4: PositionInfo + (*S2C_Position)(nil), // 5: S2C_Position +} +var file_action_proto_depIdxs = []int32{ + 4, // 0: S2C_EnterInstance.Info:type_name -> PositionInfo + 0, // 1: C2S_Action.Action:type_name -> ActionID + 4, // 2: S2C_Position.Info:type_name -> PositionInfo + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_action_proto_init() } +func file_action_proto_init() { + if File_action_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_action_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*C2S_EnterInstance); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_action_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*S2C_EnterInstance); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_action_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*C2S_Action); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_action_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PositionInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_action_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*S2C_Position); 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_action_proto_rawDesc, + NumEnums: 1, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_action_proto_goTypes, + DependencyIndexes: file_action_proto_depIdxs, + EnumInfos: file_action_proto_enumTypes, + MessageInfos: file_action_proto_msgTypes, + }.Build() + File_action_proto = out.File + file_action_proto_rawDesc = nil + file_action_proto_goTypes = nil + file_action_proto_depIdxs = nil +} diff --git a/proto/sc/sc_pb/define.pb.go b/proto/sc/sc_pb/define.pb.go new file mode 100644 index 0000000..3ef780c --- /dev/null +++ b/proto/sc/sc_pb/define.pb.go @@ -0,0 +1,217 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: define.proto + +package sc_pb + +import ( + _ "common/proto/sc/sc_common" + 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 MessageID int32 + +const ( + MessageID_MESSAGE_ID_INVALID MessageID = 0 + MessageID_MESSAGE_ID_ENTER_INSTANCE MessageID = 1 // 进入副本 + MessageID_MESSAGE_ID_ACTION MessageID = 2 // 指令 + MessageID_MESSAGE_ID_POSITION MessageID = 3 // 位置更新 +) + +// Enum value maps for MessageID. +var ( + MessageID_name = map[int32]string{ + 0: "MESSAGE_ID_INVALID", + 1: "MESSAGE_ID_ENTER_INSTANCE", + 2: "MESSAGE_ID_ACTION", + 3: "MESSAGE_ID_POSITION", + } + MessageID_value = map[string]int32{ + "MESSAGE_ID_INVALID": 0, + "MESSAGE_ID_ENTER_INSTANCE": 1, + "MESSAGE_ID_ACTION": 2, + "MESSAGE_ID_POSITION": 3, + } +) + +func (x MessageID) Enum() *MessageID { + p := new(MessageID) + *p = x + return p +} + +func (x MessageID) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MessageID) Descriptor() protoreflect.EnumDescriptor { + return file_define_proto_enumTypes[0].Descriptor() +} + +func (MessageID) Type() protoreflect.EnumType { + return &file_define_proto_enumTypes[0] +} + +func (x MessageID) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MessageID.Descriptor instead. +func (MessageID) EnumDescriptor() ([]byte, []int) { + return file_define_proto_rawDescGZIP(), []int{0} +} + +type Message struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ID MessageID `protobuf:"varint,1,opt,name=ID,proto3,enum=MessageID" json:"ID,omitempty"` + Payload []byte `protobuf:"bytes,2,opt,name=Payload,proto3" json:"Payload,omitempty"` +} + +func (x *Message) Reset() { + *x = Message{} + if protoimpl.UnsafeEnabled { + mi := &file_define_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Message) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Message) ProtoMessage() {} + +func (x *Message) ProtoReflect() protoreflect.Message { + mi := &file_define_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 Message.ProtoReflect.Descriptor instead. +func (*Message) Descriptor() ([]byte, []int) { + return file_define_proto_rawDescGZIP(), []int{0} +} + +func (x *Message) GetID() MessageID { + if x != nil { + return x.ID + } + return MessageID_MESSAGE_ID_INVALID +} + +func (x *Message) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +var File_define_proto protoreflect.FileDescriptor + +var file_define_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, + 0x73, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x3f, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x02, 0x49, 0x44, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0a, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x49, 0x44, 0x52, 0x02, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x2a, 0x72, 0x0a, 0x09, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x12, 0x16, 0x0a, + 0x12, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x49, 0x4e, 0x56, 0x41, + 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, + 0x5f, 0x49, 0x44, 0x5f, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, + 0x43, 0x45, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, + 0x49, 0x44, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x4d, + 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, + 0x4f, 0x4e, 0x10, 0x03, 0x42, 0x17, 0x5a, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x2f, 0x73, 0x63, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_define_proto_rawDescOnce sync.Once + file_define_proto_rawDescData = file_define_proto_rawDesc +) + +func file_define_proto_rawDescGZIP() []byte { + file_define_proto_rawDescOnce.Do(func() { + file_define_proto_rawDescData = protoimpl.X.CompressGZIP(file_define_proto_rawDescData) + }) + return file_define_proto_rawDescData +} + +var file_define_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_define_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_define_proto_goTypes = []interface{}{ + (MessageID)(0), // 0: MessageID + (*Message)(nil), // 1: Message +} +var file_define_proto_depIdxs = []int32{ + 0, // 0: Message.ID:type_name -> MessageID + 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 + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_define_proto_init() } +func file_define_proto_init() { + if File_define_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_define_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Message); 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_define_proto_rawDesc, + NumEnums: 1, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_define_proto_goTypes, + DependencyIndexes: file_define_proto_depIdxs, + EnumInfos: file_define_proto_enumTypes, + MessageInfos: file_define_proto_msgTypes, + }.Build() + File_define_proto = out.File + file_define_proto_rawDesc = nil + file_define_proto_goTypes = nil + file_define_proto_depIdxs = nil +} diff --git a/proto/ss/grpc_pb/service_gateway.pb.go b/proto/ss/grpc_pb/service_gateway.pb.go new file mode 100644 index 0000000..9c5cd79 --- /dev/null +++ b/proto/ss/grpc_pb/service_gateway.pb.go @@ -0,0 +1,221 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: service_gateway.proto + +package grpc_pb + +import ( + _ "common/proto/ss/ss_common" + 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 ToClientReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + USN int64 `protobuf:"varint,1,opt,name=USN,proto3" json:"USN,omitempty"` + MessageID int32 `protobuf:"varint,2,opt,name=MessageID,proto3" json:"MessageID,omitempty"` + Payload []byte `protobuf:"bytes,3,opt,name=Payload,proto3" json:"Payload,omitempty"` +} + +func (x *ToClientReq) Reset() { + *x = ToClientReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_gateway_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ToClientReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ToClientReq) ProtoMessage() {} + +func (x *ToClientReq) ProtoReflect() protoreflect.Message { + mi := &file_service_gateway_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 ToClientReq.ProtoReflect.Descriptor instead. +func (*ToClientReq) Descriptor() ([]byte, []int) { + return file_service_gateway_proto_rawDescGZIP(), []int{0} +} + +func (x *ToClientReq) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +func (x *ToClientReq) GetMessageID() int32 { + if x != nil { + return x.MessageID + } + return 0 +} + +func (x *ToClientReq) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +type ToClientResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ToClientResp) Reset() { + *x = ToClientResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_gateway_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ToClientResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ToClientResp) ProtoMessage() {} + +func (x *ToClientResp) ProtoReflect() protoreflect.Message { + mi := &file_service_gateway_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 ToClientResp.ProtoReflect.Descriptor instead. +func (*ToClientResp) Descriptor() ([]byte, []int) { + return file_service_gateway_proto_rawDescGZIP(), []int{1} +} + +var File_service_gateway_proto protoreflect.FileDescriptor + +var file_service_gateway_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x57, 0x0a, 0x0b, 0x54, 0x6f, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x53, 0x4e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x55, 0x53, 0x4e, 0x12, 0x1c, 0x0a, 0x09, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x22, 0x0e, 0x0a, 0x0c, 0x54, 0x6f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x32, 0x36, 0x0a, 0x07, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2b, 0x0a, 0x08, + 0x54, 0x6f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x0c, 0x2e, 0x54, 0x6f, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x54, 0x6f, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x28, 0x01, 0x42, 0x19, 0x5a, 0x17, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_service_gateway_proto_rawDescOnce sync.Once + file_service_gateway_proto_rawDescData = file_service_gateway_proto_rawDesc +) + +func file_service_gateway_proto_rawDescGZIP() []byte { + file_service_gateway_proto_rawDescOnce.Do(func() { + file_service_gateway_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_gateway_proto_rawDescData) + }) + return file_service_gateway_proto_rawDescData +} + +var file_service_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_service_gateway_proto_goTypes = []interface{}{ + (*ToClientReq)(nil), // 0: ToClientReq + (*ToClientResp)(nil), // 1: ToClientResp +} +var file_service_gateway_proto_depIdxs = []int32{ + 0, // 0: Gateway.ToClient:input_type -> ToClientReq + 1, // 1: Gateway.ToClient:output_type -> ToClientResp + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_service_gateway_proto_init() } +func file_service_gateway_proto_init() { + if File_service_gateway_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_service_gateway_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ToClientReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_gateway_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ToClientResp); 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_service_gateway_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_service_gateway_proto_goTypes, + DependencyIndexes: file_service_gateway_proto_depIdxs, + MessageInfos: file_service_gateway_proto_msgTypes, + }.Build() + File_service_gateway_proto = out.File + file_service_gateway_proto_rawDesc = nil + file_service_gateway_proto_goTypes = nil + file_service_gateway_proto_depIdxs = nil +} diff --git a/proto/ss/grpc_pb/service_gateway_grpc.pb.go b/proto/ss/grpc_pb/service_gateway_grpc.pb.go new file mode 100644 index 0000000..118285e --- /dev/null +++ b/proto/ss/grpc_pb/service_gateway_grpc.pb.go @@ -0,0 +1,141 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.25.1 +// source: service_gateway.proto + +package grpc_pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// GatewayClient is the client API for Gateway service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GatewayClient interface { + // 发送消息到客户端 + ToClient(ctx context.Context, opts ...grpc.CallOption) (Gateway_ToClientClient, error) +} + +type gatewayClient struct { + cc grpc.ClientConnInterface +} + +func NewGatewayClient(cc grpc.ClientConnInterface) GatewayClient { + return &gatewayClient{cc} +} + +func (c *gatewayClient) ToClient(ctx context.Context, opts ...grpc.CallOption) (Gateway_ToClientClient, error) { + stream, err := c.cc.NewStream(ctx, &Gateway_ServiceDesc.Streams[0], "/Gateway/ToClient", opts...) + if err != nil { + return nil, err + } + x := &gatewayToClientClient{stream} + return x, nil +} + +type Gateway_ToClientClient interface { + Send(*ToClientReq) error + CloseAndRecv() (*ToClientResp, error) + grpc.ClientStream +} + +type gatewayToClientClient struct { + grpc.ClientStream +} + +func (x *gatewayToClientClient) Send(m *ToClientReq) error { + return x.ClientStream.SendMsg(m) +} + +func (x *gatewayToClientClient) CloseAndRecv() (*ToClientResp, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(ToClientResp) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// GatewayServer is the server API for Gateway service. +// All implementations must embed UnimplementedGatewayServer +// for forward compatibility +type GatewayServer interface { + // 发送消息到客户端 + ToClient(Gateway_ToClientServer) error + mustEmbedUnimplementedGatewayServer() +} + +// UnimplementedGatewayServer must be embedded to have forward compatible implementations. +type UnimplementedGatewayServer struct { +} + +func (UnimplementedGatewayServer) ToClient(Gateway_ToClientServer) error { + return status.Errorf(codes.Unimplemented, "method ToClient not implemented") +} +func (UnimplementedGatewayServer) mustEmbedUnimplementedGatewayServer() {} + +// UnsafeGatewayServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GatewayServer will +// result in compilation errors. +type UnsafeGatewayServer interface { + mustEmbedUnimplementedGatewayServer() +} + +func RegisterGatewayServer(s grpc.ServiceRegistrar, srv GatewayServer) { + s.RegisterService(&Gateway_ServiceDesc, srv) +} + +func _Gateway_ToClient_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GatewayServer).ToClient(&gatewayToClientServer{stream}) +} + +type Gateway_ToClientServer interface { + SendAndClose(*ToClientResp) error + Recv() (*ToClientReq, error) + grpc.ServerStream +} + +type gatewayToClientServer struct { + grpc.ServerStream +} + +func (x *gatewayToClientServer) SendAndClose(m *ToClientResp) error { + return x.ServerStream.SendMsg(m) +} + +func (x *gatewayToClientServer) Recv() (*ToClientReq, error) { + m := new(ToClientReq) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Gateway_ServiceDesc is the grpc.ServiceDesc for Gateway service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Gateway_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "Gateway", + HandlerType: (*GatewayServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ToClient", + Handler: _Gateway_ToClient_Handler, + ClientStreams: true, + }, + }, + Metadata: "service_gateway.proto", +} diff --git a/proto/ss/grpc_pb/service_scene.pb.go b/proto/ss/grpc_pb/service_scene.pb.go new file mode 100644 index 0000000..bf8d47e --- /dev/null +++ b/proto/ss/grpc_pb/service_scene.pb.go @@ -0,0 +1,574 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: service_scene.proto + +package grpc_pb + +import ( + _ "common/proto/ss/ss_common" + 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 EnterReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + USN int64 `protobuf:"varint,1,opt,name=USN,proto3" json:"USN,omitempty"` // 用户ID + GatewaySID int64 `protobuf:"varint,2,opt,name=GatewaySID,proto3" json:"GatewaySID,omitempty"` // 网关服务ID + InstanceID int32 `protobuf:"varint,3,opt,name=InstanceID,proto3" json:"InstanceID,omitempty"` // 副本ID +} + +func (x *EnterReq) Reset() { + *x = EnterReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_scene_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnterReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnterReq) ProtoMessage() {} + +func (x *EnterReq) ProtoReflect() protoreflect.Message { + mi := &file_service_scene_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 EnterReq.ProtoReflect.Descriptor instead. +func (*EnterReq) Descriptor() ([]byte, []int) { + return file_service_scene_proto_rawDescGZIP(), []int{0} +} + +func (x *EnterReq) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +func (x *EnterReq) GetGatewaySID() int64 { + if x != nil { + return x.GatewaySID + } + return 0 +} + +func (x *EnterReq) GetInstanceID() int32 { + if x != nil { + return x.InstanceID + } + return 0 +} + +type EnterResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SceneSID int64 `protobuf:"varint,1,opt,name=SceneSID,proto3" json:"SceneSID,omitempty"` // 场景服务ID + UniqueNo int64 `protobuf:"varint,2,opt,name=UniqueNo,proto3" json:"UniqueNo,omitempty"` // 副本唯一编号 + MessageID int32 `protobuf:"varint,3,opt,name=MessageID,proto3" json:"MessageID,omitempty"` // 发送给客户端的消息ID + Payload []byte `protobuf:"bytes,4,opt,name=Payload,proto3" json:"Payload,omitempty"` // 消息负载 +} + +func (x *EnterResp) Reset() { + *x = EnterResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_scene_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnterResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnterResp) ProtoMessage() {} + +func (x *EnterResp) ProtoReflect() protoreflect.Message { + mi := &file_service_scene_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 EnterResp.ProtoReflect.Descriptor instead. +func (*EnterResp) Descriptor() ([]byte, []int) { + return file_service_scene_proto_rawDescGZIP(), []int{1} +} + +func (x *EnterResp) GetSceneSID() int64 { + if x != nil { + return x.SceneSID + } + return 0 +} + +func (x *EnterResp) GetUniqueNo() int64 { + if x != nil { + return x.UniqueNo + } + return 0 +} + +func (x *EnterResp) GetMessageID() int32 { + if x != nil { + return x.MessageID + } + return 0 +} + +func (x *EnterResp) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +type LeaveReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + USN int64 `protobuf:"varint,1,opt,name=USN,proto3" json:"USN,omitempty"` // 用户ID + GatewaySID int64 `protobuf:"varint,2,opt,name=GatewaySID,proto3" json:"GatewaySID,omitempty"` // 网关服务ID + InstanceID int32 `protobuf:"varint,3,opt,name=InstanceID,proto3" json:"InstanceID,omitempty"` // 副本ID + UniqueNo int64 `protobuf:"varint,4,opt,name=UniqueNo,proto3" json:"UniqueNo,omitempty"` // 副本唯一编号 +} + +func (x *LeaveReq) Reset() { + *x = LeaveReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_scene_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LeaveReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LeaveReq) ProtoMessage() {} + +func (x *LeaveReq) ProtoReflect() protoreflect.Message { + mi := &file_service_scene_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 LeaveReq.ProtoReflect.Descriptor instead. +func (*LeaveReq) Descriptor() ([]byte, []int) { + return file_service_scene_proto_rawDescGZIP(), []int{2} +} + +func (x *LeaveReq) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +func (x *LeaveReq) GetGatewaySID() int64 { + if x != nil { + return x.GatewaySID + } + return 0 +} + +func (x *LeaveReq) GetInstanceID() int32 { + if x != nil { + return x.InstanceID + } + return 0 +} + +func (x *LeaveReq) GetUniqueNo() int64 { + if x != nil { + return x.UniqueNo + } + return 0 +} + +type LeaveResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *LeaveResp) Reset() { + *x = LeaveResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_scene_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LeaveResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LeaveResp) ProtoMessage() {} + +func (x *LeaveResp) ProtoReflect() protoreflect.Message { + mi := &file_service_scene_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 LeaveResp.ProtoReflect.Descriptor instead. +func (*LeaveResp) Descriptor() ([]byte, []int) { + return file_service_scene_proto_rawDescGZIP(), []int{3} +} + +type ActionReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UniqueNo int64 `protobuf:"varint,1,opt,name=UniqueNo,proto3" json:"UniqueNo,omitempty"` // 副本唯一编号 + USN int64 `protobuf:"varint,2,opt,name=USN,proto3" json:"USN,omitempty"` // 用户ID + Action int32 `protobuf:"varint,3,opt,name=Action,proto3" json:"Action,omitempty"` // 指令ID + DirX int32 `protobuf:"zigzag32,4,opt,name=DirX,proto3" json:"DirX,omitempty"` // 移动-X方向(×1000 缩放) + DirY int32 `protobuf:"zigzag32,5,opt,name=DirY,proto3" json:"DirY,omitempty"` // 移动-Y方向(×1000 缩放) + SkillID int32 `protobuf:"varint,6,opt,name=SkillID,proto3" json:"SkillID,omitempty"` // 攻击-技能ID +} + +func (x *ActionReq) Reset() { + *x = ActionReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_scene_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ActionReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ActionReq) ProtoMessage() {} + +func (x *ActionReq) ProtoReflect() protoreflect.Message { + mi := &file_service_scene_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 ActionReq.ProtoReflect.Descriptor instead. +func (*ActionReq) Descriptor() ([]byte, []int) { + return file_service_scene_proto_rawDescGZIP(), []int{4} +} + +func (x *ActionReq) GetUniqueNo() int64 { + if x != nil { + return x.UniqueNo + } + return 0 +} + +func (x *ActionReq) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +func (x *ActionReq) GetAction() int32 { + if x != nil { + return x.Action + } + return 0 +} + +func (x *ActionReq) GetDirX() int32 { + if x != nil { + return x.DirX + } + return 0 +} + +func (x *ActionReq) GetDirY() int32 { + if x != nil { + return x.DirY + } + return 0 +} + +func (x *ActionReq) GetSkillID() int32 { + if x != nil { + return x.SkillID + } + return 0 +} + +type ActionResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ActionResp) Reset() { + *x = ActionResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_scene_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ActionResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ActionResp) ProtoMessage() {} + +func (x *ActionResp) ProtoReflect() protoreflect.Message { + mi := &file_service_scene_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 ActionResp.ProtoReflect.Descriptor instead. +func (*ActionResp) Descriptor() ([]byte, []int) { + return file_service_scene_proto_rawDescGZIP(), []int{5} +} + +var File_service_scene_proto protoreflect.FileDescriptor + +var file_service_scene_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5c, 0x0a, 0x08, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x53, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x03, 0x55, 0x53, 0x4e, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, + 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x53, 0x49, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x49, 0x44, 0x22, 0x7b, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x53, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x08, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x53, 0x49, 0x44, 0x12, 0x1a, 0x0a, + 0x08, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x22, 0x78, 0x0a, 0x08, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, + 0x03, 0x55, 0x53, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x55, 0x53, 0x4e, 0x12, + 0x1e, 0x0a, 0x0a, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x49, 0x44, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x49, 0x44, 0x12, + 0x1e, 0x0a, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x44, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x44, 0x12, + 0x1a, 0x0a, 0x08, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4e, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x08, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4e, 0x6f, 0x22, 0x0b, 0x0a, 0x09, 0x4c, + 0x65, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x93, 0x01, 0x0a, 0x09, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, + 0x4e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, + 0x4e, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x53, 0x4e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x03, 0x55, 0x53, 0x4e, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x44, 0x69, 0x72, 0x58, 0x18, 0x04, 0x20, 0x01, 0x28, 0x11, 0x52, 0x04, 0x44, 0x69, 0x72, 0x58, + 0x12, 0x12, 0x0a, 0x04, 0x44, 0x69, 0x72, 0x59, 0x18, 0x05, 0x20, 0x01, 0x28, 0x11, 0x52, 0x04, + 0x44, 0x69, 0x72, 0x59, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x44, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x49, 0x44, 0x22, 0x0c, + 0x0a, 0x0a, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x32, 0x72, 0x0a, 0x05, + 0x53, 0x63, 0x65, 0x6e, 0x65, 0x12, 0x20, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x09, + 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x0a, 0x2e, 0x45, 0x6e, 0x74, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x20, 0x0a, 0x05, 0x4c, 0x65, 0x61, 0x76, 0x65, + 0x12, 0x09, 0x2e, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x0a, 0x2e, 0x4c, 0x65, + 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x25, 0x0a, 0x06, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, + 0x0b, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x28, 0x01, + 0x42, 0x19, 0x5a, 0x17, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x73, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_service_scene_proto_rawDescOnce sync.Once + file_service_scene_proto_rawDescData = file_service_scene_proto_rawDesc +) + +func file_service_scene_proto_rawDescGZIP() []byte { + file_service_scene_proto_rawDescOnce.Do(func() { + file_service_scene_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_scene_proto_rawDescData) + }) + return file_service_scene_proto_rawDescData +} + +var file_service_scene_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_service_scene_proto_goTypes = []interface{}{ + (*EnterReq)(nil), // 0: EnterReq + (*EnterResp)(nil), // 1: EnterResp + (*LeaveReq)(nil), // 2: LeaveReq + (*LeaveResp)(nil), // 3: LeaveResp + (*ActionReq)(nil), // 4: ActionReq + (*ActionResp)(nil), // 5: ActionResp +} +var file_service_scene_proto_depIdxs = []int32{ + 0, // 0: Scene.Enter:input_type -> EnterReq + 2, // 1: Scene.Leave:input_type -> LeaveReq + 4, // 2: Scene.Action:input_type -> ActionReq + 1, // 3: Scene.Enter:output_type -> EnterResp + 3, // 4: Scene.Leave:output_type -> LeaveResp + 5, // 5: Scene.Action:output_type -> ActionResp + 3, // [3:6] is the sub-list for method output_type + 0, // [0:3] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_service_scene_proto_init() } +func file_service_scene_proto_init() { + if File_service_scene_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_service_scene_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnterReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_scene_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnterResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_scene_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeaveReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_scene_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeaveResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_scene_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ActionReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_scene_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ActionResp); 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_service_scene_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_service_scene_proto_goTypes, + DependencyIndexes: file_service_scene_proto_depIdxs, + MessageInfos: file_service_scene_proto_msgTypes, + }.Build() + File_service_scene_proto = out.File + file_service_scene_proto_rawDesc = nil + file_service_scene_proto_goTypes = nil + file_service_scene_proto_depIdxs = nil +} diff --git a/proto/ss/grpc_pb/service_scene_grpc.pb.go b/proto/ss/grpc_pb/service_scene_grpc.pb.go new file mode 100644 index 0000000..b2063a3 --- /dev/null +++ b/proto/ss/grpc_pb/service_scene_grpc.pb.go @@ -0,0 +1,212 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.25.1 +// source: service_scene.proto + +package grpc_pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// SceneClient is the client API for Scene service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SceneClient interface { + Enter(ctx context.Context, in *EnterReq, opts ...grpc.CallOption) (*EnterResp, error) + Leave(ctx context.Context, in *LeaveReq, opts ...grpc.CallOption) (*LeaveResp, error) + Action(ctx context.Context, opts ...grpc.CallOption) (Scene_ActionClient, error) +} + +type sceneClient struct { + cc grpc.ClientConnInterface +} + +func NewSceneClient(cc grpc.ClientConnInterface) SceneClient { + return &sceneClient{cc} +} + +func (c *sceneClient) Enter(ctx context.Context, in *EnterReq, opts ...grpc.CallOption) (*EnterResp, error) { + out := new(EnterResp) + err := c.cc.Invoke(ctx, "/Scene/Enter", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sceneClient) Leave(ctx context.Context, in *LeaveReq, opts ...grpc.CallOption) (*LeaveResp, error) { + out := new(LeaveResp) + err := c.cc.Invoke(ctx, "/Scene/Leave", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sceneClient) Action(ctx context.Context, opts ...grpc.CallOption) (Scene_ActionClient, error) { + stream, err := c.cc.NewStream(ctx, &Scene_ServiceDesc.Streams[0], "/Scene/Action", opts...) + if err != nil { + return nil, err + } + x := &sceneActionClient{stream} + return x, nil +} + +type Scene_ActionClient interface { + Send(*ActionReq) error + CloseAndRecv() (*ActionResp, error) + grpc.ClientStream +} + +type sceneActionClient struct { + grpc.ClientStream +} + +func (x *sceneActionClient) Send(m *ActionReq) error { + return x.ClientStream.SendMsg(m) +} + +func (x *sceneActionClient) CloseAndRecv() (*ActionResp, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(ActionResp) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// SceneServer is the server API for Scene service. +// All implementations must embed UnimplementedSceneServer +// for forward compatibility +type SceneServer interface { + Enter(context.Context, *EnterReq) (*EnterResp, error) + Leave(context.Context, *LeaveReq) (*LeaveResp, error) + Action(Scene_ActionServer) error + mustEmbedUnimplementedSceneServer() +} + +// UnimplementedSceneServer must be embedded to have forward compatible implementations. +type UnimplementedSceneServer struct { +} + +func (UnimplementedSceneServer) Enter(context.Context, *EnterReq) (*EnterResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Enter not implemented") +} +func (UnimplementedSceneServer) Leave(context.Context, *LeaveReq) (*LeaveResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Leave not implemented") +} +func (UnimplementedSceneServer) Action(Scene_ActionServer) error { + return status.Errorf(codes.Unimplemented, "method Action not implemented") +} +func (UnimplementedSceneServer) mustEmbedUnimplementedSceneServer() {} + +// UnsafeSceneServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SceneServer will +// result in compilation errors. +type UnsafeSceneServer interface { + mustEmbedUnimplementedSceneServer() +} + +func RegisterSceneServer(s grpc.ServiceRegistrar, srv SceneServer) { + s.RegisterService(&Scene_ServiceDesc, srv) +} + +func _Scene_Enter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EnterReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SceneServer).Enter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/Scene/Enter", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SceneServer).Enter(ctx, req.(*EnterReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Scene_Leave_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LeaveReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SceneServer).Leave(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/Scene/Leave", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SceneServer).Leave(ctx, req.(*LeaveReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Scene_Action_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SceneServer).Action(&sceneActionServer{stream}) +} + +type Scene_ActionServer interface { + SendAndClose(*ActionResp) error + Recv() (*ActionReq, error) + grpc.ServerStream +} + +type sceneActionServer struct { + grpc.ServerStream +} + +func (x *sceneActionServer) SendAndClose(m *ActionResp) error { + return x.ServerStream.SendMsg(m) +} + +func (x *sceneActionServer) Recv() (*ActionReq, error) { + m := new(ActionReq) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Scene_ServiceDesc is the grpc.ServiceDesc for Scene service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Scene_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "Scene", + HandlerType: (*SceneServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Enter", + Handler: _Scene_Enter_Handler, + }, + { + MethodName: "Leave", + Handler: _Scene_Leave_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Action", + Handler: _Scene_Action_Handler, + ClientStreams: true, + }, + }, + Metadata: "service_scene.proto", +} diff --git a/proto/ss/grpc_pb/service_user.pb.go b/proto/ss/grpc_pb/service_user.pb.go new file mode 100644 index 0000000..adfb2c2 --- /dev/null +++ b/proto/ss/grpc_pb/service_user.pb.go @@ -0,0 +1,372 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: service_user.proto + +package grpc_pb + +import ( + _ "common/proto/ss/ss_common" + _ "google.golang.org/genproto/googleapis/api/annotations" + 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 LoginReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Phone string `protobuf:"bytes,1,opt,name=Phone,json=phone,proto3" json:"Phone,omitempty"` // 手机号 + Code string `protobuf:"bytes,2,opt,name=Code,json=code,proto3" json:"Code,omitempty"` // 验证码 +} + +func (x *LoginReq) Reset() { + *x = LoginReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginReq) ProtoMessage() {} + +func (x *LoginReq) ProtoReflect() protoreflect.Message { + mi := &file_service_user_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 LoginReq.ProtoReflect.Descriptor instead. +func (*LoginReq) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{0} +} + +func (x *LoginReq) GetPhone() string { + if x != nil { + return x.Phone + } + return "" +} + +func (x *LoginReq) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +type LoginResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + USN int64 `protobuf:"varint,1,opt,name=USN,json=usn,proto3" json:"USN,omitempty"` // 用户ID + Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"` // 用户名 +} + +func (x *LoginResp) Reset() { + *x = LoginResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginResp) ProtoMessage() {} + +func (x *LoginResp) ProtoReflect() protoreflect.Message { + mi := &file_service_user_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 LoginResp.ProtoReflect.Descriptor instead. +func (*LoginResp) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{1} +} + +func (x *LoginResp) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +func (x *LoginResp) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type GetUserInfoReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + USN int64 `protobuf:"varint,1,opt,name=USN,json=usn,proto3" json:"USN,omitempty"` +} + +func (x *GetUserInfoReq) Reset() { + *x = GetUserInfoReq{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetUserInfoReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserInfoReq) ProtoMessage() {} + +func (x *GetUserInfoReq) ProtoReflect() protoreflect.Message { + mi := &file_service_user_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 GetUserInfoReq.ProtoReflect.Descriptor instead. +func (*GetUserInfoReq) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{2} +} + +func (x *GetUserInfoReq) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +type GetUserInfoResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + USN int64 `protobuf:"varint,1,opt,name=USN,json=usn,proto3" json:"USN,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"` +} + +func (x *GetUserInfoResp) Reset() { + *x = GetUserInfoResp{} + if protoimpl.UnsafeEnabled { + mi := &file_service_user_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetUserInfoResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserInfoResp) ProtoMessage() {} + +func (x *GetUserInfoResp) ProtoReflect() protoreflect.Message { + mi := &file_service_user_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 GetUserInfoResp.ProtoReflect.Descriptor instead. +func (*GetUserInfoResp) Descriptor() ([]byte, []int) { + return file_service_user_proto_rawDescGZIP(), []int{3} +} + +func (x *GetUserInfoResp) GetUSN() int64 { + if x != nil { + return x.USN + } + return 0 +} + +func (x *GetUserInfoResp) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +var File_service_user_proto protoreflect.FileDescriptor + +var file_service_user_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x12, + 0x14, 0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x31, 0x0a, 0x09, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x53, 0x4e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x73, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x22, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x12, 0x10, + 0x0a, 0x03, 0x55, 0x53, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x73, 0x6e, + 0x22, 0x37, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x53, 0x4e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x03, 0x75, 0x73, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x71, 0x0a, 0x04, 0x55, 0x73, 0x65, + 0x72, 0x12, 0x20, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x09, 0x2e, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x0a, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x0f, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x71, 0x1a, 0x10, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x73, 0x70, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x3a, 0x01, 0x2a, + 0x22, 0x0a, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x42, 0x19, 0x5a, 0x17, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x2f, + 0x67, 0x72, 0x70, 0x63, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_service_user_proto_rawDescOnce sync.Once + file_service_user_proto_rawDescData = file_service_user_proto_rawDesc +) + +func file_service_user_proto_rawDescGZIP() []byte { + file_service_user_proto_rawDescOnce.Do(func() { + file_service_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_user_proto_rawDescData) + }) + return file_service_user_proto_rawDescData +} + +var file_service_user_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_service_user_proto_goTypes = []interface{}{ + (*LoginReq)(nil), // 0: LoginReq + (*LoginResp)(nil), // 1: LoginResp + (*GetUserInfoReq)(nil), // 2: GetUserInfoReq + (*GetUserInfoResp)(nil), // 3: GetUserInfoResp +} +var file_service_user_proto_depIdxs = []int32{ + 0, // 0: User.Login:input_type -> LoginReq + 2, // 1: User.GetUserInfo:input_type -> GetUserInfoReq + 1, // 2: User.Login:output_type -> LoginResp + 3, // 3: User.GetUserInfo:output_type -> GetUserInfoResp + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_service_user_proto_init() } +func file_service_user_proto_init() { + if File_service_user_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_service_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetUserInfoReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_service_user_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetUserInfoResp); 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_service_user_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_service_user_proto_goTypes, + DependencyIndexes: file_service_user_proto_depIdxs, + MessageInfos: file_service_user_proto_msgTypes, + }.Build() + File_service_user_proto = out.File + file_service_user_proto_rawDesc = nil + file_service_user_proto_goTypes = nil + file_service_user_proto_depIdxs = nil +} diff --git a/proto/ss/grpc_pb/service_user.pb.gw.go b/proto/ss/grpc_pb/service_user.pb.gw.go new file mode 100644 index 0000000..367d62d --- /dev/null +++ b/proto/ss/grpc_pb/service_user.pb.gw.go @@ -0,0 +1,154 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: service_user.proto + +/* +Package grpc_pb is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package grpc_pb + +import ( + "context" + "errors" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) + +func request_User_GetUserInfo_0(ctx context.Context, marshaler runtime.Marshaler, client UserClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetUserInfoReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.GetUserInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_User_GetUserInfo_0(ctx context.Context, marshaler runtime.Marshaler, server UserServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetUserInfoReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetUserInfo(ctx, &protoReq) + return msg, metadata, err +} + +// RegisterUserHandlerServer registers the http handlers for service User to "mux". +// UnaryRPC :call UserServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterUserHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. +func RegisterUserHandlerServer(ctx context.Context, mux *runtime.ServeMux, server UserServer) error { + mux.Handle(http.MethodPost, pattern_User_GetUserInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/.User/GetUserInfo", runtime.WithHTTPPathPattern("/user/info")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_User_GetUserInfo_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_User_GetUserInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + + return nil +} + +// RegisterUserHandlerFromEndpoint is same as RegisterUserHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterUserHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.NewClient(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + return RegisterUserHandler(ctx, mux, conn) +} + +// RegisterUserHandler registers the http handlers for service User to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterUserHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterUserHandlerClient(ctx, mux, NewUserClient(conn)) +} + +// RegisterUserHandlerClient registers the http handlers for service User +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "UserClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "UserClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "UserClient" to call the correct interceptors. This client ignores the HTTP middlewares. +func RegisterUserHandlerClient(ctx context.Context, mux *runtime.ServeMux, client UserClient) error { + mux.Handle(http.MethodPost, pattern_User_GetUserInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/.User/GetUserInfo", runtime.WithHTTPPathPattern("/user/info")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_User_GetUserInfo_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_User_GetUserInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + return nil +} + +var ( + pattern_User_GetUserInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"user", "info"}, "")) +) + +var ( + forward_User_GetUserInfo_0 = runtime.ForwardResponseMessage +) diff --git a/proto/ss/grpc_pb/service_user_grpc.pb.go b/proto/ss/grpc_pb/service_user_grpc.pb.go new file mode 100644 index 0000000..a539483 --- /dev/null +++ b/proto/ss/grpc_pb/service_user_grpc.pb.go @@ -0,0 +1,141 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.25.1 +// source: service_user.proto + +package grpc_pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// UserClient is the client API for User service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type UserClient interface { + Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginResp, error) + GetUserInfo(ctx context.Context, in *GetUserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error) +} + +type userClient struct { + cc grpc.ClientConnInterface +} + +func NewUserClient(cc grpc.ClientConnInterface) UserClient { + return &userClient{cc} +} + +func (c *userClient) Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginResp, error) { + out := new(LoginResp) + err := c.cc.Invoke(ctx, "/User/Login", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *userClient) GetUserInfo(ctx context.Context, in *GetUserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error) { + out := new(GetUserInfoResp) + err := c.cc.Invoke(ctx, "/User/GetUserInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// UserServer is the server API for User service. +// All implementations must embed UnimplementedUserServer +// for forward compatibility +type UserServer interface { + Login(context.Context, *LoginReq) (*LoginResp, error) + GetUserInfo(context.Context, *GetUserInfoReq) (*GetUserInfoResp, error) + mustEmbedUnimplementedUserServer() +} + +// UnimplementedUserServer must be embedded to have forward compatible implementations. +type UnimplementedUserServer struct { +} + +func (UnimplementedUserServer) Login(context.Context, *LoginReq) (*LoginResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") +} +func (UnimplementedUserServer) GetUserInfo(context.Context, *GetUserInfoReq) (*GetUserInfoResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetUserInfo not implemented") +} +func (UnimplementedUserServer) mustEmbedUnimplementedUserServer() {} + +// UnsafeUserServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to UserServer will +// result in compilation errors. +type UnsafeUserServer interface { + mustEmbedUnimplementedUserServer() +} + +func RegisterUserServer(s grpc.ServiceRegistrar, srv UserServer) { + s.RegisterService(&User_ServiceDesc, srv) +} + +func _User_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LoginReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).Login(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/User/Login", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).Login(ctx, req.(*LoginReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _User_GetUserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetUserInfoReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).GetUserInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/User/GetUserInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).GetUserInfo(ctx, req.(*GetUserInfoReq)) + } + return interceptor(ctx, in, info, handler) +} + +// User_ServiceDesc is the grpc.ServiceDesc for User service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var User_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "User", + HandlerType: (*UserServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Login", + Handler: _User_Login_Handler, + }, + { + MethodName: "GetUserInfo", + Handler: _User_GetUserInfo_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "service_user.proto", +} diff --git a/proto/ss/ss_common/ss_common.pb.go b/proto/ss/ss_common/ss_common.pb.go new file mode 100644 index 0000000..5881aae --- /dev/null +++ b/proto/ss/ss_common/ss_common.pb.go @@ -0,0 +1,151 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.1 +// source: ss_common.proto + +package ss_common + +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 ErrorInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code int32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"` + Msg string `protobuf:"bytes,2,opt,name=Msg,proto3" json:"Msg,omitempty"` +} + +func (x *ErrorInfo) Reset() { + *x = ErrorInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_ss_common_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ErrorInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorInfo) ProtoMessage() {} + +func (x *ErrorInfo) ProtoReflect() protoreflect.Message { + mi := &file_ss_common_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 ErrorInfo.ProtoReflect.Descriptor instead. +func (*ErrorInfo) Descriptor() ([]byte, []int) { + return file_ss_common_proto_rawDescGZIP(), []int{0} +} + +func (x *ErrorInfo) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *ErrorInfo) GetMsg() string { + if x != nil { + return x.Msg + } + return "" +} + +var File_ss_common_proto protoreflect.FileDescriptor + +var file_ss_common_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x31, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, + 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x4d, 0x73, 0x67, 0x42, 0x1b, 0x5a, 0x19, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x2f, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_ss_common_proto_rawDescOnce sync.Once + file_ss_common_proto_rawDescData = file_ss_common_proto_rawDesc +) + +func file_ss_common_proto_rawDescGZIP() []byte { + file_ss_common_proto_rawDescOnce.Do(func() { + file_ss_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_ss_common_proto_rawDescData) + }) + return file_ss_common_proto_rawDescData +} + +var file_ss_common_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_ss_common_proto_goTypes = []interface{}{ + (*ErrorInfo)(nil), // 0: ErrorInfo +} +var file_ss_common_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_ss_common_proto_init() } +func file_ss_common_proto_init() { + if File_ss_common_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_ss_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ErrorInfo); 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_ss_common_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_ss_common_proto_goTypes, + DependencyIndexes: file_ss_common_proto_depIdxs, + MessageInfos: file_ss_common_proto_msgTypes, + }.Build() + File_ss_common_proto = out.File + file_ss_common_proto_rawDesc = nil + file_ss_common_proto_goTypes = nil + file_ss_common_proto_depIdxs = nil +} diff --git a/utils/jwt.go b/utils/jwt.go new file mode 100644 index 0000000..e358b4a --- /dev/null +++ b/utils/jwt.go @@ -0,0 +1,56 @@ +package utils + +import ( + "context" + "errors" + "github.com/golang-jwt/jwt/v5" + "google.golang.org/grpc/metadata" + "strconv" + "time" +) + +type Claims struct { + USN int64 `json:"usn"` + jwt.RegisteredClaims +} + +func GenToken(usn int64, secret string, expires time.Duration) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims{ + USN: usn, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(expires)), + }, + }) + return token.SignedString([]byte(secret)) +} + +func ParseToken(tokenString string, secret string) (*Claims, error) { + if tokenString == "" { + return nil, errors.New("invalid token") + } + claims := &Claims{} + token, err := jwt.ParseWithClaims(tokenString, claims, func(_ *jwt.Token) (interface{}, error) { + return []byte(secret), nil + }) + if err != nil { + return nil, err + } + if !token.Valid { + return nil, errors.New("invalid token") + } + return claims, nil +} + +func ShouldBindUsn(ctx context.Context, usn *int64) bool { + if md, ok := metadata.FromIncomingContext(ctx); ok { + usnArr := md.Get("X-Usn") + if len(usnArr) == 0 || usnArr[0] == "" { + return false + } + s, _ := strconv.Atoi(usnArr[0]) + if s > 0 { + *usn = int64(s) + } + } + return *usn > 0 +} diff --git a/utils/number.go b/utils/number.go new file mode 100644 index 0000000..ce618ee --- /dev/null +++ b/utils/number.go @@ -0,0 +1,23 @@ +package utils + +import ( + "math/rand" + "strconv" +) + +// RandInt 生成 [min, max] 范围内的随机整数 +func RandInt(min, max int) int { + if min > max { + min, max = max, min + } + return rand.Intn(max-min+1) + min +} + +// StringToInt64 converts a string to int64, returns 0 if failed +func StringToInt64(s string) int64 { + i, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return 0 + } + return i +} diff --git a/utils/snowflake.go b/utils/snowflake.go new file mode 100644 index 0000000..24c4ca3 --- /dev/null +++ b/utils/snowflake.go @@ -0,0 +1,24 @@ +package utils + +import ( + "github.com/bwmarrin/snowflake" + "log" +) + +var instance *snowflake.Node + +func InitSnowflake(node int64) *snowflake.Node { + n, err := snowflake.NewNode(node) + if err != nil { + log.Fatalf("create snowflake's node failed: %v", err) + } + instance = n + return instance +} + +func SnowflakeInstance() *snowflake.Node { + if instance == nil { + log.Fatal("snowflake's not init") + } + return instance +} diff --git a/utils/workerpool.go b/utils/workerpool.go new file mode 100644 index 0000000..7ba9f37 --- /dev/null +++ b/utils/workerpool.go @@ -0,0 +1,41 @@ +package utils + +import ( + "sync" +) + +// DefaultMaxWorkers 默认并发数 +const DefaultMaxWorkers = 32 + +// WorkerPool 并发执行一批任务。 +func WorkerPool(tasks []interface{}, taskFunc func(interface{}), maxWorkers ...int) { + if len(tasks) == 0 { + return + } + + workers := DefaultMaxWorkers + if len(maxWorkers) > 0 && maxWorkers[0] > 0 { + workers = maxWorkers[0] + } + if workers > len(tasks) { + workers = len(tasks) + } + + jobs := make(chan interface{}, len(tasks)) + var wg sync.WaitGroup + for i := 0; i < workers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for task := range jobs { + taskFunc(task) + } + }() + } + for _, task := range tasks { + jobs <- task + } + + close(jobs) + wg.Wait() +}