feat: 初始化后端服务骨架,包含配置加载、数据库连接、Redis集成及消息队列任务处理。

This commit is contained in:
2026-01-28 16:49:58 +08:00
parent 5a0ae912d5
commit 59de7d12d8
3 changed files with 77 additions and 3 deletions

View File

@@ -5,7 +5,6 @@ import (
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"time"
"accounting-app/internal/cache" "accounting-app/internal/cache"
"accounting-app/internal/config" "accounting-app/internal/config"
@@ -125,8 +124,8 @@ func main() {
ctx, ctx,
redisClient.Client(), redisClient.Client(),
db, db,
5*time.Second, // Poll interval: 检查延迟任务的间隔 cfg.MQPollInterval, // Poll interval from config
2, // Worker count: 并发处理任务的数量 cfg.MQWorkerCount, // Worker count from config
) )
if err != nil { if err != nil {
log.Printf("Warning: Failed to initialize recurring task system: %v", err) log.Printf("Warning: Failed to initialize recurring task system: %v", err)

View File

@@ -58,6 +58,10 @@ type Config struct {
MaxImageSize int64 MaxImageSize int64
AllowedImageTypes string AllowedImageTypes string
MaxImagesPerTx int MaxImagesPerTx int
// Task Queue configuration
MQWorkerCount int
MQPollInterval time.Duration
} }
// Load loads configuration from environment variables // Load loads configuration from environment variables
@@ -113,6 +117,10 @@ func Load() *Config {
MaxImageSize: getEnvInt64("MAX_IMAGE_SIZE", 10*1024*1024), // 10MB MaxImageSize: getEnvInt64("MAX_IMAGE_SIZE", 10*1024*1024), // 10MB
AllowedImageTypes: getEnv("ALLOWED_IMAGE_TYPES", "image/jpeg,image/png,image/heic"), AllowedImageTypes: getEnv("ALLOWED_IMAGE_TYPES", "image/jpeg,image/png,image/heic"),
MaxImagesPerTx: getEnvInt("MAX_IMAGES_PER_TX", 9), 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 // Ensure data directory exists

67
internal/mq/logger.go Normal file
View File

@@ -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)
}