From 4ce951dd56e4c19f9401e5acda390d756b3786bd Mon Sep 17 00:00:00 2001 From: oneao Date: Wed, 25 Feb 2026 22:20:16 +0800 Subject: [PATCH] u --- code/allapp/allapp-go/.gitignore | 1 + code/allapp/allapp-go/.idea/dataSources.xml | 29 +++ .../allapp-go/.idea/data_source_mapping.xml | 7 + .../inspectionProfiles/Project_Default.xml | 10 + code/allapp/allapp-go/.idea/protoeditor.xml | 12 + code/allapp/allapp-go/.idea/sqldialects.xml | 6 + code/allapp/allapp-go/api/handler/api.go | 12 + .../allapp/allapp-go/api/middleware/logger.go | 33 +++ code/allapp/allapp-go/api/router/router.go | 14 + code/allapp/allapp-go/cmd/main.go | 52 ++-- code/allapp/allapp-go/config/index.go | 73 +++++- code/allapp/allapp-go/config/jwt.go | 1 - code/allapp/allapp-go/config/logger.go | 152 +++++++++++ code/allapp/allapp-go/config/snow_id.go | 1 - code/allapp/allapp-go/config/types.go | 64 ++--- code/allapp/allapp-go/config/unique_id.go | 9 + code/allapp/allapp-go/go.mod | 9 +- code/allapp/allapp-go/go.sum | 12 + .../allapp-go/resources/application.yaml | 14 +- code/allapp/allapp-go/utils/jwtx/index.go | 86 +++++++ .../allapp/allapp-go/utils/responsex/index.go | 1 + .../utils/uniqueid/DefaultIdGenerator.go | 83 ++++++ .../allapp-go/utils/uniqueid/IIdGenerator.go | 5 + .../allapp-go/utils/uniqueid/ISnowWorker.go | 5 + .../utils/uniqueid/IdGeneratorException.go | 12 + .../utils/uniqueid/IdGeneratorOptions.go | 25 ++ .../allapp-go/utils/uniqueid/IdHelper.go | 29 +++ .../utils/uniqueid/OverCostActionArg.go | 19 ++ .../allapp-go/utils/uniqueid/SnowWorkerM1.go | 243 ++++++++++++++++++ .../allapp-go/utils/uniqueid/SnowWorkerM2.go | 37 +++ 30 files changed, 982 insertions(+), 74 deletions(-) create mode 100644 code/allapp/allapp-go/.gitignore create mode 100644 code/allapp/allapp-go/.idea/dataSources.xml create mode 100644 code/allapp/allapp-go/.idea/data_source_mapping.xml create mode 100644 code/allapp/allapp-go/.idea/inspectionProfiles/Project_Default.xml create mode 100644 code/allapp/allapp-go/.idea/protoeditor.xml create mode 100644 code/allapp/allapp-go/.idea/sqldialects.xml create mode 100644 code/allapp/allapp-go/api/handler/api.go create mode 100644 code/allapp/allapp-go/api/middleware/logger.go create mode 100644 code/allapp/allapp-go/api/router/router.go delete mode 100644 code/allapp/allapp-go/config/jwt.go delete mode 100644 code/allapp/allapp-go/config/snow_id.go create mode 100644 code/allapp/allapp-go/config/unique_id.go create mode 100644 code/allapp/allapp-go/utils/jwtx/index.go create mode 100644 code/allapp/allapp-go/utils/responsex/index.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/DefaultIdGenerator.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/IIdGenerator.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/ISnowWorker.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/IdGeneratorException.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/IdGeneratorOptions.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/IdHelper.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/OverCostActionArg.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/SnowWorkerM1.go create mode 100644 code/allapp/allapp-go/utils/uniqueid/SnowWorkerM2.go diff --git a/code/allapp/allapp-go/.gitignore b/code/allapp/allapp-go/.gitignore new file mode 100644 index 00000000..cd3d2253 --- /dev/null +++ b/code/allapp/allapp-go/.gitignore @@ -0,0 +1 @@ +logs \ No newline at end of file diff --git a/code/allapp/allapp-go/.idea/dataSources.xml b/code/allapp/allapp-go/.idea/dataSources.xml new file mode 100644 index 00000000..323f42ae --- /dev/null +++ b/code/allapp/allapp-go/.idea/dataSources.xml @@ -0,0 +1,29 @@ + + + + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://117.72.182.135:5432/postgres + + + + + + $ProjectFileDir$ + + + redis + true + jdbc.RedisDriver + jdbc:redis://117.72.182.135:6379/0 + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/code/allapp/allapp-go/.idea/data_source_mapping.xml b/code/allapp/allapp-go/.idea/data_source_mapping.xml new file mode 100644 index 00000000..09e8f97a --- /dev/null +++ b/code/allapp/allapp-go/.idea/data_source_mapping.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/code/allapp/allapp-go/.idea/inspectionProfiles/Project_Default.xml b/code/allapp/allapp-go/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..11ef84a0 --- /dev/null +++ b/code/allapp/allapp-go/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/code/allapp/allapp-go/.idea/protoeditor.xml b/code/allapp/allapp-go/.idea/protoeditor.xml new file mode 100644 index 00000000..5b3674a2 --- /dev/null +++ b/code/allapp/allapp-go/.idea/protoeditor.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/code/allapp/allapp-go/.idea/sqldialects.xml b/code/allapp/allapp-go/.idea/sqldialects.xml new file mode 100644 index 00000000..6df4889b --- /dev/null +++ b/code/allapp/allapp-go/.idea/sqldialects.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/allapp/allapp-go/api/handler/api.go b/code/allapp/allapp-go/api/handler/api.go new file mode 100644 index 00000000..bec6efe2 --- /dev/null +++ b/code/allapp/allapp-go/api/handler/api.go @@ -0,0 +1,12 @@ +package handler + +import ( + "allapp/utils/jwtx" + + "github.com/gofiber/fiber/v3" +) + +// Hello handle api status +func Hello(c fiber.Ctx) error { + return c.JSON(fiber.Map{"status": "success", "message": "Hello i'm ok!", "data": nil}) +} diff --git a/code/allapp/allapp-go/api/middleware/logger.go b/code/allapp/allapp-go/api/middleware/logger.go new file mode 100644 index 00000000..29547e63 --- /dev/null +++ b/code/allapp/allapp-go/api/middleware/logger.go @@ -0,0 +1,33 @@ +package middleware + +import ( + "context" + "time" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/log" +) + +func Logger() fiber.Handler { + return func(c fiber.Ctx) error { + ctx := context.WithValue(c.Context(), "request_id", c.RequestID()) + c.SetContext(ctx) + + start := time.Now() + + err := c.Next() + + duration := time.Since(start) + + // 记录日志 + log.WithContext(c.Context()).Infow("API Request", + "method", c.Method(), + "path", c.Path(), + "status", c.Response().StatusCode(), + "duration", duration.String(), + "ip", c.IP(), + ) + + return err + } +} diff --git a/code/allapp/allapp-go/api/router/router.go b/code/allapp/allapp-go/api/router/router.go new file mode 100644 index 00000000..673adfbb --- /dev/null +++ b/code/allapp/allapp-go/api/router/router.go @@ -0,0 +1,14 @@ +package router + +import ( + "allapp/api/handler" + "allapp/config" + + "github.com/gofiber/fiber/v3" +) + +func SetupRouters(app *fiber.App) { + api := app.Group(config.GetConf().Server.BaseUrl) + + api.Get("/", handler.Hello) +} diff --git a/code/allapp/allapp-go/cmd/main.go b/code/allapp/allapp-go/cmd/main.go index 144da7e9..0de5fb63 100644 --- a/code/allapp/allapp-go/cmd/main.go +++ b/code/allapp/allapp-go/cmd/main.go @@ -1,42 +1,32 @@ package main import ( + "allapp/api/middleware" + "allapp/api/router" "allapp/config" - "fmt" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/log" + recoverer "github.com/gofiber/fiber/v3/middleware/recover" + "github.com/gofiber/fiber/v3/middleware/requestid" + "go.uber.org/zap" ) +//func errorHandler(ctx fiber.Ctx, err error) error { +// +//} + func main() { - config.InitConf() + if err := config.InitConfig(); err != nil { + panic(err) + } - fmt.Print(config.GetConf().Server.BaseUrl) + app := fiber.New() + app.Use(recoverer.New(), requestid.New(), middleware.Logger()) - //app := fiber.New() + router.SetupRouters(app) - //logger := middleware.NewLogger(middleware.LoggerConfig{ - // ExtraKeys: []string{"request_id", "abc"}, - //}) - // - //log.SetLogger(logger) - // - //defer logger.Sync() - // - //app.Use(func(c fiber.Ctx) error { - // ctx := context.WithValue(c.Context(), "request_id", "123") - // ctx = context.WithValue(ctx, "user_id", "456") - // ctx = context.WithValue(ctx, "trace_id", "789") - // - // c.SetContext(ctx) - // return c.Next() - //}) - // - //app.Get("/", func(c fiber.Ctx) error { - // log.WithContext(c.Context()).Infow("MSG", - // "request_id", "12345", - // "user_id", "abc123", - // "status", "pending", - // ) - // return c.SendString("Hello, World!") - //}) - // - //log.Fatal(app.Listen(":3000")) + if err := app.Listen(config.GetServerPort()); err != nil { + log.Fatal("server start failed", zap.Error(err)) + } } diff --git a/code/allapp/allapp-go/config/index.go b/code/allapp/allapp-go/config/index.go index 982a3dfe..aa08ee5e 100644 --- a/code/allapp/allapp-go/config/index.go +++ b/code/allapp/allapp-go/config/index.go @@ -4,6 +4,8 @@ import ( "fmt" "os" "path/filepath" + "strings" + "time" "github.com/spf13/viper" ) @@ -12,11 +14,62 @@ var ( conf *Config ) -func InitConf() { +func InitConfig() error { + // 加载配置 + err := readConfigFile() + + if err != nil { + return fmt.Errorf("read config file failed: %w", err) + } + + initLogger() + initUniqueId() + + return nil +} + +func defaultConfig() *Config { + return &Config{ + Server: ServerConfig{ + Port: "8080", + BaseUrl: "/", + WsUrl: "/ws", + }, + JWT: JwtConfig{ + Secret: "qwemwddlalmskadklsdklamlkdsakld", + AccessExpiry: 24 * time.Hour, + }, + UniqueID: UniqueIDConfig{ + DataCenterID: 1, + WorkerID: 1, + }, + Postgres: PostgresConfig{ + Port: 5432, + SslMode: false, + TimeZone: "Asia/Shanghai", + MaxOpenConns: 20, + MaxIdleConns: 10, + ConnMaxLifetime: 30 * time.Minute, + }, + Log: LogConfig{ + Level: "info", + Dir: "logs", + MaxSize: 100, + MaxBackups: 10, + MaxAge: 30, + Compress: true, + }, + } +} + +func readConfigFile() error { // 配置文件的目录 prefix := "resources" env := GetEnv() // 获取当前环境 + // 设置默认值 + conf = defaultConfig() // 先给默认结构体 + // 默认配置文件 confFileRelPath := filepath.Join(prefix, "application.yaml") @@ -42,18 +95,18 @@ func InitConf() { // 如果需要,合并环境特定的配置文件 if err := v.MergeInConfig(); err != nil { - panic(err) + return fmt.Errorf("merge env config failed: %w", err) } - // 将配置文件反序列化到 Config 结构体 - conf = new(Config) if err := v.Unmarshal(conf); err != nil { - panic(err) + return fmt.Errorf("unmarshal config failed: %w", err) } fmt.Println("✅️ 加载配置成功") // 设置环境变量 conf.Env = env + + return nil } // GetEnv 获取 GO_ENV 环境变量,默认返回 "dev" @@ -66,6 +119,16 @@ func GetEnv() string { return e } +// GetConf 获取配置信息 func GetConf() *Config { return conf } + +// GetServerPort 项目启动端口 +func GetServerPort() string { + port := conf.Server.Port + if strings.HasPrefix(port, ":") { + return port + } + return ":" + port +} diff --git a/code/allapp/allapp-go/config/jwt.go b/code/allapp/allapp-go/config/jwt.go deleted file mode 100644 index d912156b..00000000 --- a/code/allapp/allapp-go/config/jwt.go +++ /dev/null @@ -1 +0,0 @@ -package config diff --git a/code/allapp/allapp-go/config/logger.go b/code/allapp/allapp-go/config/logger.go index d912156b..189c0a5d 100644 --- a/code/allapp/allapp-go/config/logger.go +++ b/code/allapp/allapp-go/config/logger.go @@ -1 +1,153 @@ package config + +import ( + "fmt" + "os" + "sync" + "time" + + fiberZap "github.com/gofiber/contrib/v3/zap" + "github.com/gofiber/fiber/v3/log" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" +) + +var ( + mu sync.Mutex + currentDay = make(map[string]string) + currentSync = make(map[string]zapcore.WriteSyncer) +) + +func initLogger() { + dynamicLevel := zap.NewAtomicLevel() + dynamicLevel.SetLevel(LogLevel()) + + logger := fiberZap.NewLogger(fiberZap.LoggerConfig{ + ExtraKeys: []string{"request_id"}, + ZapOptions: []zap.Option{ + zap.AddCaller(), // 打开 caller + zap.AddCallerSkip(2), // 跳过一层 Fiber 调用 + }, + CoreConfigs: []fiberZap.CoreConfig{ + { + Encoder: zapcore.NewConsoleEncoder(consoleEncoderConfig()), + WriteSyncer: zapcore.AddSync(os.Stdout), + LevelEncoder: dynamicLevel, + }, + { + Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), + WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/debug", conf.Log.Dir)), + LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { + return lev == zap.DebugLevel + }), + }, + { + Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), + WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/info", conf.Log.Dir)), + LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { + return lev == zap.InfoLevel + }), + }, + { + Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), + WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/warn", conf.Log.Dir)), + LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { + return lev == zap.WarnLevel + }), + }, + { + Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), + WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/error", conf.Log.Dir)), + LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { + return lev >= zap.ErrorLevel + }), + }, + }, + }) + + log.SetLogger(logger) + + // 退出时同步日志 + defer func() { + _ = logger.Sync() + }() +} + +func getWriteSyncer(basePath string) zapcore.WriteSyncer { + mu.Lock() + defer mu.Unlock() + + today := time.Now().Format("2006-01-02") + if day, ok := currentDay[basePath]; !ok || day != today { + currentDay[basePath] = today + file := fmt.Sprintf("%s/%s.log", basePath, today) + + currentSync[basePath] = zapcore.AddSync(&lumberjack.Logger{ + Filename: file, + MaxSize: conf.Log.MaxSize, + MaxBackups: conf.Log.MaxBackups, + MaxAge: conf.Log.MaxAge, + Compress: conf.Log.Compress, + LocalTime: true, + }) + } + return currentSync[basePath] +} + +func LogLevel() zapcore.Level { + level := conf.Log.Level + + switch level { + case "trace": + return zapcore.DebugLevel + case "debug": + return zapcore.DebugLevel + case "info": + return zapcore.InfoLevel + case "warn": + return zapcore.WarnLevel + case "error": + return zapcore.ErrorLevel + case "dpanic": + return zapcore.DPanicLevel + case "panic": + return zapcore.PanicLevel + case "fatal": + return zapcore.FatalLevel + default: + return zapcore.InfoLevel + } +} + +func consoleEncoderConfig() zapcore.EncoderConfig { + return zapcore.EncoderConfig{ + MessageKey: "msg", + LevelKey: "level", + TimeKey: "ts", + EncodeTime: customTimeEncoder, + EncodeLevel: zapcore.CapitalColorLevelEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + } +} + +func humanEncoderConfig() zapcore.EncoderConfig { + return zapcore.EncoderConfig{ + MessageKey: "message", + LevelKey: "level", + NameKey: "mame", + TimeKey: "ts", + CallerKey: "caller", + FunctionKey: "func", + StacktraceKey: "stacktrace", + LineEnding: "\n", + EncodeTime: customTimeEncoder, + EncodeLevel: zapcore.LowercaseLevelEncoder, + EncodeDuration: zapcore.SecondsDurationEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + } +} + +func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(t.Format("2006-01-02 15:04:05.000")) +} diff --git a/code/allapp/allapp-go/config/snow_id.go b/code/allapp/allapp-go/config/snow_id.go deleted file mode 100644 index d912156b..00000000 --- a/code/allapp/allapp-go/config/snow_id.go +++ /dev/null @@ -1 +0,0 @@ -package config diff --git a/code/allapp/allapp-go/config/types.go b/code/allapp/allapp-go/config/types.go index fbd29424..b2792b1a 100644 --- a/code/allapp/allapp-go/config/types.go +++ b/code/allapp/allapp-go/config/types.go @@ -5,53 +5,53 @@ import "time" type Config struct { Env string - Server ServerConfig `yaml:"server"` - JWT JwtConfig `yaml:"jwt"` - SnowID SnowIDConfig `yaml:"snow_id"` - Postgres PostgresConfig `yaml:"postgres"` - Log LogConfig `yaml:"log"` - Wechat WechatConfig `yaml:"wechat"` + Server ServerConfig `mapstructure:"server"` + JWT JwtConfig `mapstructure:"jwt"` + UniqueID UniqueIDConfig `mapstructure:"unique_id"` + Postgres PostgresConfig `mapstructure:"postgres"` + Log LogConfig `mapstructure:"log"` + Wechat WechatConfig `mapstructure:"wechat"` } type ServerConfig struct { - Port string `yaml:"port" mapstructure:"port"` - BaseUrl string `mapstructure:"base_url"` // 添加mapstructure标签 - WsUrl string `yaml:"ws_url" mapstructure:"ws_url"` + Port string `mapstructure:"port"` + BaseUrl string `mapstructure:"base_url"` + WsUrl string `mapstructure:"ws_url"` } type JwtConfig struct { - Secret string `yaml:"secret"` - AccessExpiry time.Duration `yaml:"access_expiry"` + Secret string `mapstructure:"secret"` + AccessExpiry time.Duration `mapstructure:"access_expiry"` } -type SnowIDConfig struct { - DataCenterID uint16 `yaml:"datacenter_id"` - WorkerID uint16 `yaml:"worker_id"` +type UniqueIDConfig struct { + DataCenterID uint16 `mapstructure:"datacenter_id"` + WorkerID uint16 `mapstructure:"worker_id"` } type PostgresConfig struct { - Host string `yaml:"host"` - Port int `yaml:"port"` - User string `yaml:"user"` - Password string `yaml:"password"` - Dbname string `yaml:"dbname"` - SllMode bool `yaml:"sll_mode"` - TimeZone string `yaml:"timezone"` - MaxOpenConns int32 `yaml:"max_open_conns"` - MaxIdleConns int32 `yaml:"max_idle_conns"` - ConnMaxLifetime time.Duration `yaml:"conn_max_lifetime"` + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + User string `mapstructure:"user"` + Password string `mapstructure:"password"` + Dbname string `mapstructure:"dbname"` + SslMode bool `mapstructure:"ssl_mode"` + TimeZone string `mapstructure:"timezone"` + MaxOpenConns int32 `mapstructure:"max_open_conns"` + MaxIdleConns int32 `mapstructure:"max_idle_conns"` + ConnMaxLifetime time.Duration `mapstructure:"conn_max_lifetime"` } type LogConfig struct { - Level string `yaml:"level"` - Dir string `yaml:"dir"` - MaxSize int `yaml:"max_size"` - MaxBackups int `yaml:"max_backups"` - MaxAge int `yaml:"max_age"` - Compress bool `yaml:"compress"` + Level string `mapstructure:"level"` + Dir string `mapstructure:"dir"` + MaxSize int `mapstructure:"max_size"` + MaxBackups int `mapstructure:"max_backups"` + MaxAge int `mapstructure:"max_age"` + Compress bool `mapstructure:"compress"` } type WechatConfig struct { - AppId string `yaml:"app_id"` - AppSecret string `yaml:"app_secret"` + AppId string `mapstructure:"app_id"` + AppSecret string `mapstructure:"app_secret"` } diff --git a/code/allapp/allapp-go/config/unique_id.go b/code/allapp/allapp-go/config/unique_id.go new file mode 100644 index 00000000..3c270066 --- /dev/null +++ b/code/allapp/allapp-go/config/unique_id.go @@ -0,0 +1,9 @@ +package config + +import "allapp/utils/uniqueid" + +// 初始化雪花id +func initUniqueId() { + options := uniqueid.NewIdGeneratorOptions(conf.UniqueID.WorkerID) + uniqueid.SetIdGenerator(options) +} diff --git a/code/allapp/allapp-go/go.mod b/code/allapp/allapp-go/go.mod index 9aa7f920..d1cbb50e 100644 --- a/code/allapp/allapp-go/go.mod +++ b/code/allapp/allapp-go/go.mod @@ -5,13 +5,17 @@ go 1.25.0 require ( github.com/gofiber/contrib/v3/zap v1.0.0 github.com/gofiber/fiber/v3 v3.1.0 + github.com/golang-jwt/jwt/v5 v5.3.1 + github.com/spf13/viper v1.21.0 go.uber.org/zap v1.27.1 + gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) require ( + github.com/MicahParks/keyfunc/v2 v2.1.0 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/gofiber/schema v1.7.0 // indirect github.com/gofiber/utils/v2 v2.0.2 // indirect github.com/google/uuid v1.6.0 // indirect @@ -20,12 +24,11 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/philhofer/fwd v1.2.0 // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sagikazarmark/locafero v0.12.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/spf13/viper v1.21.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tinylib/msgp v1.6.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect diff --git a/code/allapp/allapp-go/go.sum b/code/allapp/allapp-go/go.sum index cdc6cb64..1ec2f219 100644 --- a/code/allapp/allapp-go/go.sum +++ b/code/allapp/allapp-go/go.sum @@ -1,9 +1,15 @@ +github.com/MicahParks/keyfunc/v2 v2.1.0 h1:6ZXKb9Rp6qp1bDbJefnG7cTH8yMN1IC/4nf+GVjO99k= +github.com/MicahParks/keyfunc/v2 v2.1.0/go.mod h1:rW42fi+xgLJ2FRRXAfNx9ZA8WpD4OeE/yHVMteCkw9k= github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= 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/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/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gofiber/contrib/v3/jwt v1.0.0 h1:PvqaoJiFgkcdNxfFCFffPaoDlL208fnWc9uYSGn0e8s= +github.com/gofiber/contrib/v3/jwt v1.0.0/go.mod h1:N8X1yggexDyIm5+4fWSy5UffXbdZR1dUf7+AgFNM8L8= github.com/gofiber/contrib/v3/zap v1.0.0 h1:8plUZ3VqNhEG3yQD3ItKPd/Qoc5KPW2FkMT/R1UaB8k= github.com/gofiber/contrib/v3/zap v1.0.0/go.mod h1:BgwWh3xoTUq8Tx8R4Zy/pq2DK+p+4rdVT1hdCKT7mV8= github.com/gofiber/fiber/v3 v3.1.0 h1:1p4I820pIa+FGxfwWuQZ5rAyX0WlGZbGT6Hnuxt6hKY= @@ -12,6 +18,8 @@ github.com/gofiber/schema v1.7.0 h1:yNM+FNRZjyYEli9Ey0AXRBrAY9jTnb+kmGs3lJGPvKg= github.com/gofiber/schema v1.7.0/go.mod h1:A/X5Ffyru4p9eBdp99qu+nzviHzQiZ7odLT+TwxWhbk= github.com/gofiber/utils/v2 v2.0.2 h1:ShRRssz0F3AhTlAQcuEj54OEDtWF7+HJDwEi/aa6QLI= github.com/gofiber/utils/v2 v2.0.2/go.mod h1:+9Ub4NqQ+IaJoTliq5LfdmOJAA/Hzwf4pXOxOa3RrJ0= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= 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/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= @@ -26,6 +34,8 @@ github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= 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/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= 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= @@ -60,3 +70,5 @@ golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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= diff --git a/code/allapp/allapp-go/resources/application.yaml b/code/allapp/allapp-go/resources/application.yaml index 516cc13a..cf8f824b 100644 --- a/code/allapp/allapp-go/resources/application.yaml +++ b/code/allapp/allapp-go/resources/application.yaml @@ -1,4 +1,16 @@ server: port: 8086 base_url: /app - ws_url: /ws \ No newline at end of file + ws_url: /ws + +log: + level: "debug" + dir: "./logs" + max_size: 10 + max_backups: 30 + max_age: 7 + compress: true + +jwt: + secret: 3Bde3BGEbYqtqyEUzW3ry8jKFcaPH17fRmTmqE7MDr05Lwj95uruRKrrkb44TJ4s + access_expiry: -1 \ No newline at end of file diff --git a/code/allapp/allapp-go/utils/jwtx/index.go b/code/allapp/allapp-go/utils/jwtx/index.go new file mode 100644 index 00000000..54788e7e --- /dev/null +++ b/code/allapp/allapp-go/utils/jwtx/index.go @@ -0,0 +1,86 @@ +package jwtx + +import ( + "allapp/config" + "context" + "errors" + "sync" + "time" + + "github.com/golang-jwt/jwt/v5" +) + +type CustomClaims struct { + UserID int64 `json:"user_id"` + jwt.RegisteredClaims +} + +// jwtManager 单例管理 +type jwtManager struct { + secret string + tokenExpiry time.Duration +} + +var ( + manager *jwtManager + once sync.Once +) + +// InitJwt 初始化 JWT 单例 +func InitJwt() { + once.Do(func() { + cfg := config.GetConf().JWT + manager = &jwtManager{ + secret: cfg.Secret, + tokenExpiry: cfg.AccessExpiry, + } + }) +} + +// CreateToken 生成 JWT +func CreateToken(ctx context.Context, userID int64) (string, error) { + if manager == nil { + return "", errors.New("jwt manager not initialized") + } + return manager.createToken(userID) +} + +// VerifyToken 校验 token 并返回 claims +func VerifyToken(ctx context.Context, tokenString string) (*CustomClaims, error) { + if tokenString == "" || manager == nil { + return nil, errors.New("token empty or manager not initialized") + } + + token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { + return []byte(manager.secret), nil + }) + + if err != nil || !token.Valid { + return nil, errors.New("invalid token") + } + + claims, ok := token.Claims.(*CustomClaims) + if !ok { + return nil, errors.New("invalid claims") + } + + return claims, nil +} + +// createToken 私有方法 +func (j *jwtManager) createToken(userID int64) (string, error) { + now := time.Now() + claims := &CustomClaims{ + UserID: userID, + RegisteredClaims: jwt.RegisteredClaims{ + IssuedAt: jwt.NewNumericDate(now), + }, + } + + if j.tokenExpiry > 0 { + claims.ExpiresAt = jwt.NewNumericDate(now.Add(j.tokenExpiry)) + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString([]byte(j.secret)) +} diff --git a/code/allapp/allapp-go/utils/responsex/index.go b/code/allapp/allapp-go/utils/responsex/index.go new file mode 100644 index 00000000..a039194b --- /dev/null +++ b/code/allapp/allapp-go/utils/responsex/index.go @@ -0,0 +1 @@ +package responsex diff --git a/code/allapp/allapp-go/utils/uniqueid/DefaultIdGenerator.go b/code/allapp/allapp-go/utils/uniqueid/DefaultIdGenerator.go new file mode 100644 index 00000000..3d2d57f4 --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/DefaultIdGenerator.go @@ -0,0 +1,83 @@ +package uniqueid + +import ( + "strconv" + "time" +) + +type DefaultIdGenerator struct { + Options *IdGeneratorOptions + SnowWorker ISnowWorker + IdGeneratorException IdGeneratorException +} + +func NewDefaultIdGenerator(options *IdGeneratorOptions) *DefaultIdGenerator { + if options == nil { + panic("dig.Options error.") + } + + // 1.BaseTime + minTime := int64(631123200000) // time.Now().AddDate(-30, 0, 0).UnixNano() / 1e6 + if options.BaseTime < minTime || options.BaseTime > time.Now().UnixNano()/1e6 { + panic("BaseTime error.") + } + + // 2.WorkerIdBitLength + if options.WorkerIdBitLength <= 0 { + panic("WorkerIdBitLength error.(range:[1, 21])") + } + if options.WorkerIdBitLength+options.SeqBitLength > 22 { + panic("error:WorkerIdBitLength + SeqBitLength <= 22") + } + + // 3.WorkerId + maxWorkerIdNumber := uint16(1< maxWorkerIdNumber { + panic("WorkerId error. (range:[0, " + strconv.FormatUint(uint64(maxWorkerIdNumber), 10) + "]") + } + + // 4.SeqBitLength + if options.SeqBitLength < 2 || options.SeqBitLength > 21 { + panic("SeqBitLength error. (range:[2, 21])") + } + + // 5.MaxSeqNumber + maxSeqNumber := uint32(1< maxSeqNumber { + panic("MaxSeqNumber error. (range:[1, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") + } + + // 6.MinSeqNumber + if options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber { + panic("MinSeqNumber error. (range:[5, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") + } + + var snowWorker ISnowWorker + switch options.Method { + case 1: + snowWorker = NewSnowWorkerM1(options) + case 2: + snowWorker = NewSnowWorkerM2(options) + default: + snowWorker = NewSnowWorkerM1(options) + } + + if options.Method == 1 { + time.Sleep(time.Duration(500) * time.Microsecond) + } + + return &DefaultIdGenerator{ + Options: options, + SnowWorker: snowWorker, + } +} + +func (dig DefaultIdGenerator) NewLong() int64 { + return dig.SnowWorker.NextId() +} diff --git a/code/allapp/allapp-go/utils/uniqueid/IIdGenerator.go b/code/allapp/allapp-go/utils/uniqueid/IIdGenerator.go new file mode 100644 index 00000000..a0c1e4de --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/IIdGenerator.go @@ -0,0 +1,5 @@ +package uniqueid + +type IIdGenerator interface { + NewLong() uint64 +} diff --git a/code/allapp/allapp-go/utils/uniqueid/ISnowWorker.go b/code/allapp/allapp-go/utils/uniqueid/ISnowWorker.go new file mode 100644 index 00000000..c066e6d6 --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/ISnowWorker.go @@ -0,0 +1,5 @@ +package uniqueid + +type ISnowWorker interface { + NextId() int64 +} diff --git a/code/allapp/allapp-go/utils/uniqueid/IdGeneratorException.go b/code/allapp/allapp-go/utils/uniqueid/IdGeneratorException.go new file mode 100644 index 00000000..c0ae9086 --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/IdGeneratorException.go @@ -0,0 +1,12 @@ +package uniqueid + +import "fmt" + +type IdGeneratorException struct { + message string + error error +} + +func (e IdGeneratorException) IdGeneratorException(message ...interface{}) { + fmt.Println(message) +} diff --git a/code/allapp/allapp-go/utils/uniqueid/IdGeneratorOptions.go b/code/allapp/allapp-go/utils/uniqueid/IdGeneratorOptions.go new file mode 100644 index 00000000..1f4ff6e1 --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/IdGeneratorOptions.go @@ -0,0 +1,25 @@ +package uniqueid + +type IdGeneratorOptions struct { + Method uint16 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 + BaseTime int64 // 基础时间(ms单位),不能超过当前系统时间 + WorkerId uint16 // 机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1 + WorkerIdBitLength byte // 机器码位长,默认值6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过22) + SeqBitLength byte // 序列数位长,默认值6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过22) + MaxSeqNumber uint32 // 最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值0,表示最大序列数取最大值(2^SeqBitLength-1]) + MinSeqNumber uint32 // 最小序列数(含),默认值5,取值范围 [5, MaxSeqNumber],每毫秒的前5个序列数对应编号0-4是保留位,其中1-4是时间回拨相应预留位,0是手工新值预留位 + TopOverCostCount uint32 // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) +} + +func NewIdGeneratorOptions(workerId uint16) *IdGeneratorOptions { + return &IdGeneratorOptions{ + Method: 1, + WorkerId: workerId, + BaseTime: 1582136402000, + WorkerIdBitLength: 6, + SeqBitLength: 6, + MaxSeqNumber: 0, + MinSeqNumber: 5, + TopOverCostCount: 2000, + } +} diff --git a/code/allapp/allapp-go/utils/uniqueid/IdHelper.go b/code/allapp/allapp-go/utils/uniqueid/IdHelper.go new file mode 100644 index 00000000..a76494a8 --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/IdHelper.go @@ -0,0 +1,29 @@ +package uniqueid + +import ( + "sync" +) + +var singletonMutex sync.Mutex +var idGenerator *DefaultIdGenerator + +// SetIdGenerator . +func SetIdGenerator(options *IdGeneratorOptions) { + singletonMutex.Lock() + idGenerator = NewDefaultIdGenerator(options) + singletonMutex.Unlock() +} + +// NextId . +func NextId() int64 { + if idGenerator == nil { + singletonMutex.Lock() + defer singletonMutex.Unlock() + if idGenerator == nil { + options := NewIdGeneratorOptions(1) + idGenerator = NewDefaultIdGenerator(options) + } + } + + return idGenerator.NewLong() +} diff --git a/code/allapp/allapp-go/utils/uniqueid/OverCostActionArg.go b/code/allapp/allapp-go/utils/uniqueid/OverCostActionArg.go new file mode 100644 index 00000000..5b8942cc --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/OverCostActionArg.go @@ -0,0 +1,19 @@ +package uniqueid + +type OverCostActionArg struct { + ActionType int32 + TimeTick int64 + WorkerId uint16 + OverCostCountInOneTerm int32 + GenCountInOneTerm int32 + TermIndex int32 +} + +func (ocaa OverCostActionArg) OverCostActionArg(workerId uint16, timeTick int64, actionType int32, overCostCountInOneTerm int32, genCountWhenOverCost int32, index int32) { + ocaa.ActionType = actionType + ocaa.TimeTick = timeTick + ocaa.WorkerId = workerId + ocaa.OverCostCountInOneTerm = overCostCountInOneTerm + ocaa.GenCountInOneTerm = genCountWhenOverCost + ocaa.TermIndex = index +} diff --git a/code/allapp/allapp-go/utils/uniqueid/SnowWorkerM1.go b/code/allapp/allapp-go/utils/uniqueid/SnowWorkerM1.go new file mode 100644 index 00000000..b9edde7f --- /dev/null +++ b/code/allapp/allapp-go/utils/uniqueid/SnowWorkerM1.go @@ -0,0 +1,243 @@ +package uniqueid + +import ( + "sync" + "time" +) + +// SnowWorkerM1 . +type SnowWorkerM1 struct { + BaseTime int64 //基础时间 + WorkerId uint16 //机器码 + WorkerIdBitLength byte //机器码位长 + SeqBitLength byte //自增序列数位长 + MaxSeqNumber uint32 //最大序列数(含) + MinSeqNumber uint32 //最小序列数(含) + TopOverCostCount uint32 //最大漂移次数 + _TimestampShift byte + _CurrentSeqNumber uint32 + + _LastTimeTick int64 + _TurnBackTimeTick int64 + _TurnBackIndex byte + _IsOverCost bool + _OverCostCountInOneTerm uint32 + _GenCountInOneTerm uint32 + _TermIndex uint32 + + sync.Mutex +} + +// NewSnowWorkerM1 . +func NewSnowWorkerM1(options *IdGeneratorOptions) ISnowWorker { + var workerIdBitLength byte + var seqBitLength byte + var maxSeqNumber uint32 + + // 1.BaseTime + var baseTime int64 + if options.BaseTime != 0 { + baseTime = options.BaseTime + } else { + baseTime = 1582136402000 + } + + // 2.WorkerIdBitLength + if options.WorkerIdBitLength == 0 { + workerIdBitLength = 6 + } else { + workerIdBitLength = options.WorkerIdBitLength + } + + // 3.WorkerId + var workerId = options.WorkerId + + // 4.SeqBitLength + if options.SeqBitLength == 0 { + seqBitLength = 6 + } else { + seqBitLength = options.SeqBitLength + } + + // 5.MaxSeqNumber + if options.MaxSeqNumber <= 0 { + maxSeqNumber = (1 << seqBitLength) - 1 + } else { + maxSeqNumber = options.MaxSeqNumber + } + + // 6.MinSeqNumber + var minSeqNumber = options.MinSeqNumber + + // 7.Others + var topOverCostCount = options.TopOverCostCount + if topOverCostCount == 0 { + topOverCostCount = 2000 + } + + timestampShift := (byte)(workerIdBitLength + seqBitLength) + currentSeqNumber := minSeqNumber + + return &SnowWorkerM1{ + BaseTime: baseTime, + WorkerIdBitLength: workerIdBitLength, + WorkerId: workerId, + SeqBitLength: seqBitLength, + MaxSeqNumber: maxSeqNumber, + MinSeqNumber: minSeqNumber, + TopOverCostCount: topOverCostCount, + _TimestampShift: timestampShift, + _CurrentSeqNumber: currentSeqNumber, + + _LastTimeTick: 0, + _TurnBackTimeTick: 0, + _TurnBackIndex: 0, + _IsOverCost: false, + _OverCostCountInOneTerm: 0, + _GenCountInOneTerm: 0, + _TermIndex: 0, + } +} + +// DoGenIDAction . +func (m1 *SnowWorkerM1) DoGenIdAction(arg *OverCostActionArg) { + +} + +func (m1 *SnowWorkerM1) BeginOverCostAction(useTimeTick int64) { + +} + +func (m1 *SnowWorkerM1) EndOverCostAction(useTimeTick int64) { + if m1._TermIndex > 10000 { + m1._TermIndex = 0 + } +} + +func (m1 *SnowWorkerM1) BeginTurnBackAction(useTimeTick int64) { + +} + +func (m1 *SnowWorkerM1) EndTurnBackAction(useTimeTick int64) { + +} + +func (m1 *SnowWorkerM1) NextOverCostId() int64 { + currentTimeTick := m1.GetCurrentTimeTick() + if currentTimeTick > m1._LastTimeTick { + m1.EndOverCostAction(currentTimeTick) + m1._LastTimeTick = currentTimeTick + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = false + m1._OverCostCountInOneTerm = 0 + m1._GenCountInOneTerm = 0 + return m1.CalcId(m1._LastTimeTick) + } + if m1._OverCostCountInOneTerm >= m1.TopOverCostCount { + m1.EndOverCostAction(currentTimeTick) + m1._LastTimeTick = m1.GetNextTimeTick() + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = false + m1._OverCostCountInOneTerm = 0 + m1._GenCountInOneTerm = 0 + return m1.CalcId(m1._LastTimeTick) + } + if m1._CurrentSeqNumber > m1.MaxSeqNumber { + m1._LastTimeTick++ + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = true + m1._OverCostCountInOneTerm++ + m1._GenCountInOneTerm++ + + return m1.CalcId(m1._LastTimeTick) + } + + m1._GenCountInOneTerm++ + return m1.CalcId(m1._LastTimeTick) +} + +// NextNormalID . +func (m1 *SnowWorkerM1) NextNormalId() int64 { + currentTimeTick := m1.GetCurrentTimeTick() + if currentTimeTick < m1._LastTimeTick { + if m1._TurnBackTimeTick < 1 { + m1._TurnBackTimeTick = m1._LastTimeTick - 1 + m1._TurnBackIndex++ + // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + // 最多4次回拨(防止回拨重叠) + if m1._TurnBackIndex > 4 { + m1._TurnBackIndex = 1 + } + m1.BeginTurnBackAction(m1._TurnBackTimeTick) + } + + // time.Sleep(time.Duration(1) * time.Millisecond) + return m1.CalcTurnBackId(m1._TurnBackTimeTick) + } + + // 时间追平时,_TurnBackTimeTick清零 + if m1._TurnBackTimeTick > 0 { + m1.EndTurnBackAction(m1._TurnBackTimeTick) + m1._TurnBackTimeTick = 0 + } + + if currentTimeTick > m1._LastTimeTick { + m1._LastTimeTick = currentTimeTick + m1._CurrentSeqNumber = m1.MinSeqNumber + return m1.CalcId(m1._LastTimeTick) + } + + if m1._CurrentSeqNumber > m1.MaxSeqNumber { + m1.BeginOverCostAction(currentTimeTick) + m1._TermIndex++ + m1._LastTimeTick++ + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = true + m1._OverCostCountInOneTerm = 1 + m1._GenCountInOneTerm = 1 + + return m1.CalcId(m1._LastTimeTick) + } + + return m1.CalcId(m1._LastTimeTick) +} + +// CalcID . +func (m1 *SnowWorkerM1) CalcId(useTimeTick int64) int64 { + result := int64(useTimeTick< m2.MaxSeqNumber { + m2._CurrentSeqNumber = m2.MinSeqNumber + currentTimeTick = m2.GetNextTimeTick() + } + } else { + m2._CurrentSeqNumber = m2.MinSeqNumber + } + if currentTimeTick < m2._LastTimeTick { + fmt.Println("Time error for {0} milliseconds", strconv.FormatInt(m2._LastTimeTick-currentTimeTick, 10)) + } + m2._LastTimeTick = currentTimeTick + result := int64(currentTimeTick<