From 59de7d12d874a4aa06ce86d03c39b4a9bd2261e8 Mon Sep 17 00:00:00 2001 From: admin <1297598740@qq.com> Date: Wed, 28 Jan 2026 16:49:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E5=8C=96=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E6=9C=8D=E5=8A=A1=E9=AA=A8=E6=9E=B6=EF=BC=8C=E5=8C=85?= =?UTF-8?q?=E5=90=AB=E9=85=8D=E7=BD=AE=E5=8A=A0=E8=BD=BD=E3=80=81=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E8=BF=9E=E6=8E=A5=E3=80=81Redis=E9=9B=86?= =?UTF-8?q?=E6=88=90=E5=8F=8A=E6=B6=88=E6=81=AF=E9=98=9F=E5=88=97=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=A4=84=E7=90=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/server/main.go | 5 ++- internal/config/config.go | 8 +++++ internal/mq/logger.go | 67 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 internal/mq/logger.go diff --git a/cmd/server/main.go b/cmd/server/main.go index 5dee426..7bfec2b 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -5,7 +5,6 @@ import ( "log" "os" "path/filepath" - "time" "accounting-app/internal/cache" "accounting-app/internal/config" @@ -125,8 +124,8 @@ func main() { ctx, redisClient.Client(), db, - 5*time.Second, // Poll interval: 检查延迟任务的间隔 - 2, // Worker count: 并发处理任务的数量 + cfg.MQPollInterval, // Poll interval from config + cfg.MQWorkerCount, // Worker count from config ) if err != nil { log.Printf("Warning: Failed to initialize recurring task system: %v", err) diff --git a/internal/config/config.go b/internal/config/config.go index 17db8b5..869631f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -58,6 +58,10 @@ type Config struct { MaxImageSize int64 AllowedImageTypes string MaxImagesPerTx int + + // Task Queue configuration + MQWorkerCount int + MQPollInterval time.Duration } // Load loads configuration from environment variables @@ -113,6 +117,10 @@ func Load() *Config { MaxImageSize: getEnvInt64("MAX_IMAGE_SIZE", 10*1024*1024), // 10MB AllowedImageTypes: getEnv("ALLOWED_IMAGE_TYPES", "image/jpeg,image/png,image/heic"), MaxImagesPerTx: getEnvInt("MAX_IMAGES_PER_TX", 9), + + // Task Queue + MQWorkerCount: getEnvInt("MQ_WORKER_COUNT", 2), + MQPollInterval: getEnvDuration("MQ_POLL_INTERVAL", 5*time.Second), } // Ensure data directory exists diff --git a/internal/mq/logger.go b/internal/mq/logger.go new file mode 100644 index 0000000..32835b1 --- /dev/null +++ b/internal/mq/logger.go @@ -0,0 +1,67 @@ +package mq + +import ( + "fmt" + "log" +) + +// LogLevel 日志级别 +type LogLevel string + +const ( + LevelInfo LogLevel = "INFO" + LevelError LogLevel = "ERROR" + LevelWarn LogLevel = "WARN" +) + +// Logger 简单的结构化日志封装 +// 格式: [Component] [Level] Message key1=value1 key2=value2 +type Logger struct { + Component string +} + +func NewLogger(component string) *Logger { + return &Logger{Component: component} +} + +func (l *Logger) Info(msg string, keysAndValues ...interface{}) { + l.log(LevelInfo, msg, keysAndValues...) +} + +func (l *Logger) Warn(msg string, keysAndValues ...interface{}) { + l.log(LevelWarn, msg, keysAndValues...) +} + +func (l *Logger) Error(msg string, keysAndValues ...interface{}) { + l.log(LevelError, msg, keysAndValues...) +} + +func (l *Logger) log(level LogLevel, msg string, args ...interface{}) { + // 构建 key=value 字符串 + var kvStr string + for i := 0; i < len(args); i += 2 { + key := args[i] + var val interface{} = "" + if i+1 < len(args) { + val = args[i+1] + } + if kvStr != "" { + kvStr += " " + } + kvStr += logFormatKV(key, val) + } + + if kvStr != "" { + log.Printf("[%s] [%s] %s %s", l.Component, level, msg, kvStr) + } else { + log.Printf("[%s] [%s] %s", l.Component, level, msg) + } +} + +func logFormatKV(key, val interface{}) string { + return logStr(key) + "=" + logStr(val) +} + +func logStr(v interface{}) string { + return fmt.Sprint(v) +}