输出消息改为中文
This commit is contained in:
@@ -88,18 +88,18 @@ func (a *API) Start() {
|
|||||||
go func() {
|
go func() {
|
||||||
// 启动服务器,并检查错误。http.ErrServerClosed 是正常关闭时的错误,无需处理。
|
// 启动服务器,并检查错误。http.ErrServerClosed 是正常关闭时的错误,无需处理。
|
||||||
if err := a.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
if err := a.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||||
a.logger.Fatalf("HTTP server listen: %s", err) // 如果是其他错误,则记录致命错误并退出
|
a.logger.Fatalf("HTTP 服务器监听失败: %s", err) // 如果是其他错误,则记录致命错误并退出
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// 记录服务器已启动的信息
|
// 记录服务器已启动的信息
|
||||||
a.logger.Infof("HTTP server listening on %s", addr)
|
a.logger.Infof("HTTP 服务器正在监听 %s", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop 优雅地停止 HTTP 服务器
|
// Stop 优雅地停止 HTTP 服务器
|
||||||
// 在停止服务器时,会给一个超时时间,确保正在处理的请求能够完成。
|
// 在停止服务器时,会给一个超时时间,确保正在处理的请求能够完成。
|
||||||
func (a *API) Stop() {
|
func (a *API) Stop() {
|
||||||
// 记录服务器正在关闭的信息
|
// 记录服务器正在关闭的信息
|
||||||
a.logger.Info("Shutting down HTTP server...")
|
a.logger.Info("正在关闭 HTTP 服务器...")
|
||||||
|
|
||||||
// 创建一个带有 5 秒超时时间的上下文
|
// 创建一个带有 5 秒超时时间的上下文
|
||||||
// 在此时间内,服务器会尝试完成所有活跃的连接。
|
// 在此时间内,服务器会尝试完成所有活跃的连接。
|
||||||
@@ -110,8 +110,8 @@ func (a *API) Stop() {
|
|||||||
// 如果在超时时间内未能关闭,Shutdown 会返回错误。
|
// 如果在超时时间内未能关闭,Shutdown 会返回错误。
|
||||||
if err := a.httpServer.Shutdown(ctx); err != nil {
|
if err := a.httpServer.Shutdown(ctx); err != nil {
|
||||||
// 如果关闭失败,记录致命错误并退出
|
// 如果关闭失败,记录致命错误并退出
|
||||||
a.logger.Fatalf("HTTP server shutdown failed: %s", err)
|
a.logger.Fatalf("HTTP 服务器关闭失败: %s", err)
|
||||||
}
|
}
|
||||||
// 记录服务器已停止的信息
|
// 记录服务器已停止的信息
|
||||||
a.logger.Info("HTTP server stopped.")
|
a.logger.Info("HTTP 服务器已停止。")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ type LoginResponse struct {
|
|||||||
func (c *Controller) CreateUser(ctx *gin.Context) {
|
func (c *Controller) CreateUser(ctx *gin.Context) {
|
||||||
var req CreateUserRequest
|
var req CreateUserRequest
|
||||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||||
c.logger.Errorf("CreateUser: 参数绑定失败: %v", err)
|
c.logger.Errorf("创建用户: 参数绑定失败: %v", err)
|
||||||
controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
|
controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ func (c *Controller) CreateUser(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := c.userRepo.Create(user); err != nil {
|
if err := c.userRepo.Create(user); err != nil {
|
||||||
c.logger.Errorf("CreateUser: 创建用户失败: %v", err)
|
c.logger.Errorf("创建用户: 创建用户失败: %v", err)
|
||||||
|
|
||||||
// 尝试查询用户,以判断是否是用户名重复导致的错误
|
// 尝试查询用户,以判断是否是用户名重复导致的错误
|
||||||
_, findErr := c.userRepo.FindByUsername(req.Username)
|
_, findErr := c.userRepo.FindByUsername(req.Username)
|
||||||
@@ -92,7 +92,7 @@ func (c *Controller) CreateUser(ctx *gin.Context) {
|
|||||||
func (c *Controller) Login(ctx *gin.Context) {
|
func (c *Controller) Login(ctx *gin.Context) {
|
||||||
var req LoginRequest
|
var req LoginRequest
|
||||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||||
c.logger.Errorf("Login: 参数绑定失败: %v", err)
|
c.logger.Errorf("登录: 参数绑定失败: %v", err)
|
||||||
controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
|
controller.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ func (c *Controller) Login(ctx *gin.Context) {
|
|||||||
controller.SendErrorResponse(ctx, http.StatusUnauthorized, "用户名或密码不正确")
|
controller.SendErrorResponse(ctx, http.StatusUnauthorized, "用户名或密码不正确")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.logger.Errorf("Login: 查询用户失败: %v", err)
|
c.logger.Errorf("登录: 查询用户失败: %v", err)
|
||||||
controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败")
|
controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ func (c *Controller) Login(ctx *gin.Context) {
|
|||||||
// 登录成功,生成 JWT token
|
// 登录成功,生成 JWT token
|
||||||
tokenString, err := c.tokenService.GenerateToken(user.ID)
|
tokenString, err := c.tokenService.GenerateToken(user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Errorf("Login: 生成 token 失败: %v", err)
|
c.logger.Errorf("登录: 生成令牌失败: %v", err)
|
||||||
controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败,无法生成认证信息")
|
controller.SendErrorResponse(ctx, http.StatusInternalServerError, "登录失败,无法生成认证信息")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ func TestCreateUser(t *testing.T) {
|
|||||||
// 初始化 Gin 上下文和记录器
|
// 初始化 Gin 上下文和记录器
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
ctx, _ := gin.CreateTestContext(w)
|
ctx, _ := gin.CreateTestContext(w)
|
||||||
ctx.Request = httptest.NewRequest(http.MethodPost, "/users", nil) // 初始请求,后续会替换 Body
|
ctx.Request = httptest.NewRequest(http.MethodPost, "/users", nil) // URL 路径不重要,因为我们不测试路由
|
||||||
|
|
||||||
// 设置请求体
|
// 设置请求体
|
||||||
jsonBody, _ := json.Marshal(tt.requestBody)
|
jsonBody, _ := json.Marshal(tt.requestBody)
|
||||||
|
|||||||
@@ -17,30 +17,30 @@ func TestGenerateToken(t *testing.T) {
|
|||||||
tokenString, err := service.GenerateToken(userID)
|
tokenString, err := service.GenerateToken(userID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("GenerateToken failed: %v", err)
|
t.Fatalf("生成令牌失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tokenString == "" {
|
if tokenString == "" {
|
||||||
t.Fatal("Generated token string is empty")
|
t.Fatal("生成的令牌字符串为空")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析 token 以确保其有效性及声明
|
// 解析 token 以确保其有效性及声明
|
||||||
claims, err := service.ParseToken(tokenString)
|
claims, err := service.ParseToken(tokenString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ParseToken failed after generation: %v", err)
|
t.Fatalf("生成后解析令牌失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if claims.UserID != userID {
|
if claims.UserID != userID {
|
||||||
t.Errorf("Expected UserID %d, got %d", userID, claims.UserID)
|
t.Errorf("期望用户ID %d, 实际为 %d", userID, claims.UserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查 token 是否未过期 (在合理范围内)
|
// 检查 token 是否未过期 (在合理范围内)
|
||||||
if claims.ExpiresAt == nil || claims.ExpiresAt.Time.Before(time.Now().Add(-time.Minute)) {
|
if claims.ExpiresAt == nil || claims.ExpiresAt.Time.Before(time.Now().Add(-time.Minute)) {
|
||||||
t.Errorf("Token expiration time is invalid or already expired")
|
t.Errorf("令牌过期时间无效或已过期")
|
||||||
}
|
}
|
||||||
|
|
||||||
if claims.Issuer != "pig-farm-controller" {
|
if claims.Issuer != "pig-farm-controller" {
|
||||||
t.Errorf("Expected Issuer \"pig-farm-controller\", got \"%s\"", claims.Issuer)
|
t.Errorf("期望签发者 \"pig-farm-controller\", 实际为 \"%s\"", claims.Issuer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,24 +54,24 @@ func TestParseToken(t *testing.T) {
|
|||||||
// 生成一个有效的 token 用于解析测试
|
// 生成一个有效的 token 用于解析测试
|
||||||
validToken, err := service.GenerateToken(userID)
|
validToken, err := service.GenerateToken(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to generate valid token for parsing test: %v", err)
|
t.Fatalf("为解析测试生成有效令牌失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试用例 1: 有效 token
|
// 测试用例 1: 有效 token
|
||||||
claims, err := service.ParseToken(validToken)
|
claims, err := service.ParseToken(validToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("ParseToken failed for valid token: %v", err)
|
t.Errorf("解析有效令牌失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if claims.UserID != userID {
|
if claims.UserID != userID {
|
||||||
t.Errorf("Expected UserID %d, got %d for valid token", userID, claims.UserID)
|
t.Errorf("解析有效令牌时期望用户ID %d, 实际为 %d", userID, claims.UserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试用例 2: 无效 token (例如, 错误的签名)
|
// 测试用例 2: 无效 token (例如, 错误的签名)
|
||||||
invalidToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsImV4cCI6MTY3ODkwNTYwMCwiaXNzIjoicGlnLWZhcm0tY29udHJvbGxlciJ9.invalid_signature_here"
|
invalidToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsImV4cCI6MTY3ODkwNTYwMCwiaXNzIjoicGlnLWZhcm0tY29udHJvbGxlciJ9.invalid_signature_here"
|
||||||
_, err = service.ParseToken(invalidToken)
|
_, err = service.ParseToken(invalidToken)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("ParseToken unexpectedly succeeded for invalid token")
|
t.Error("解析无效令牌意外成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试用例 3: 过期 token (创建一个过期时间在过去的 token)
|
// 测试用例 3: 过期 token (创建一个过期时间在过去的 token)
|
||||||
@@ -85,11 +85,11 @@ func TestParseToken(t *testing.T) {
|
|||||||
expiredTokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, expiredClaims)
|
expiredTokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, expiredClaims)
|
||||||
expiredTokenString, err := expiredTokenClaims.SignedString(testSecret)
|
expiredTokenString, err := expiredTokenClaims.SignedString(testSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to generate expired token: %v", err)
|
t.Fatalf("生成过期令牌失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = service.ParseToken(expiredTokenString)
|
_, err = service.ParseToken(expiredTokenString)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("ParseToken unexpectedly succeeded for expired token")
|
t.Error("解析过期令牌意外成功")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ func captureOutput(cfg config.LogConfig) (*logs.Logger, *bytes.Buffer) {
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
// 使用一个简单的 Console Encoder 进行测试,方便断言字符串
|
// 使用一个简单的 Console Encoder 进行测试,方便断言字符串
|
||||||
encoderConfig := zap.NewDevelopmentEncoderConfig()
|
encoderConfig := zap.NewDevelopmentEncoderConfig()
|
||||||
encoderConfig.EncodeTime = nil // 忽略时间,避免测试结果不一致
|
encoderConfig.EncodeTime = nil // 忽略时间,避免测试结果不一致
|
||||||
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
|
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 日志级别大写
|
||||||
encoderConfig.EncodeCaller = nil // 忽略调用者信息
|
encoderConfig.EncodeCaller = nil // 忽略调用者信息
|
||||||
encoder := zapcore.NewConsoleEncoder(encoderConfig)
|
encoder := zapcore.NewConsoleEncoder(encoderConfig)
|
||||||
|
|
||||||
writer := zapcore.AddSync(&buf)
|
writer := zapcore.AddSync(&buf)
|
||||||
@@ -39,7 +39,7 @@ func captureOutput(cfg config.LogConfig) (*logs.Logger, *bytes.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewLogger(t *testing.T) {
|
func TestNewLogger(t *testing.T) {
|
||||||
t.Run("Constructor does not panic", func(t *testing.T) {
|
t.Run("构造函数不会 panic", func(t *testing.T) {
|
||||||
// 测试 Console 格式
|
// 测试 Console 格式
|
||||||
cfgConsole := config.LogConfig{Level: "info", Format: "console"}
|
cfgConsole := config.LogConfig{Level: "info", Format: "console"}
|
||||||
assert.NotPanics(t, func() { logs.NewLogger(cfgConsole) })
|
assert.NotPanics(t, func() { logs.NewLogger(cfgConsole) })
|
||||||
@@ -68,7 +68,7 @@ func TestLogger_Write_ForGin(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
// logger.Write 会将 gin 的日志转为 info 级别
|
// logger.Write 会将 gin 的日志转为 info 级别
|
||||||
assert.Contains(t, output, "INFO")
|
assert.Contains(t, output, "INFO", "应包含 INFO 级别")
|
||||||
assert.Contains(t, output, strings.TrimSpace(ginLog))
|
assert.Contains(t, output, strings.TrimSpace(ginLog))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ func TestGormLogger(t *testing.T) {
|
|||||||
return sql, rows
|
return sql, rows
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Slow Query", func(t *testing.T) {
|
t.Run("慢查询", func(t *testing.T) {
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
// 模拟一个耗时超过 200ms 的查询
|
// 模拟一个耗时超过 200ms 的查询
|
||||||
begin := time.Now().Add(-300 * time.Millisecond)
|
begin := time.Now().Add(-300 * time.Millisecond)
|
||||||
@@ -92,37 +92,37 @@ func TestGormLogger(t *testing.T) {
|
|||||||
|
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
assert.Contains(t, output, "WARN", "应包含 WARN 级别")
|
assert.Contains(t, output, "WARN", "应包含 WARN 级别")
|
||||||
assert.Contains(t, output, "[GORM] slow query", "应包含慢查询信息")
|
assert.Contains(t, output, "[GORM] 慢查询", "应包含慢查询信息")
|
||||||
// 修复:不再检查严格的 JSON 格式,只检查关键内容
|
// 修复:不再检查严格的 JSON 格式,只检查关键内容
|
||||||
assert.Contains(t, output, "SELECT * FROM users WHERE id = 1", "应包含 SQL 语句")
|
assert.Contains(t, output, "SELECT * FROM users WHERE id = 1", "应包含 SQL 语句")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Error Query", func(t *testing.T) {
|
t.Run("错误查询", func(t *testing.T) {
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
queryError := errors.New("syntax error")
|
queryError := errors.New("语法错误")
|
||||||
gormLogger.Trace(ctx, time.Now(), fc, queryError)
|
gormLogger.Trace(ctx, time.Now(), fc, queryError)
|
||||||
|
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
assert.Contains(t, output, "ERROR")
|
assert.Contains(t, output, "ERROR", "应包含 ERROR 级别")
|
||||||
assert.Contains(t, output, "[GORM] error: syntax error")
|
assert.Contains(t, output, "[GORM] 错误: 语法错误", "应包含 GORM 错误信息")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Record Not Found Error is Skipped", func(t *testing.T) {
|
t.Run("记录未找到错误被跳过", func(t *testing.T) {
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
queryError := errors.New("record not found") // 模拟 GORM 的 RecordNotFound 错误
|
queryError := errors.New("记录未找到") // 模拟 GORM 的 RecordNotFound 错误
|
||||||
gormLogger.Trace(ctx, time.Now(), fc, queryError)
|
gormLogger.Trace(ctx, time.Now(), fc, queryError)
|
||||||
|
|
||||||
// 在修复 logs.go 中的 bug 后,这里应该为空
|
// 在修复 logs.go 中的 bug 后,这里应该为空
|
||||||
assert.Empty(t, buf.String(), "开启 SkipErrRecordNotFound 后,record not found 错误不应产生任何日志")
|
assert.Empty(t, buf.String(), "开启 SkipErrRecordNotFound 后,record not found 错误不应产生任何日志")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Normal Query", func(t *testing.T) {
|
t.Run("正常查询", func(t *testing.T) {
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
// 模拟一个快速查询
|
// 模拟一个快速查询
|
||||||
gormLogger.Trace(ctx, time.Now(), fc, nil)
|
gormLogger.Trace(ctx, time.Now(), fc, nil)
|
||||||
|
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
assert.Contains(t, output, "DEBUG") // 正常查询是 Debug 级别
|
assert.Contains(t, output, "DEBUG", "正常查询应为 DEBUG 级别")
|
||||||
assert.Contains(t, output, "[GORM] trace")
|
assert.Contains(t, output, "[GORM] 追踪", "应包含 GORM 追踪信息")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (tq *TaskQueue) AddTask(task Task) {
|
|||||||
priority: task.GetPriority(),
|
priority: task.GetPriority(),
|
||||||
}
|
}
|
||||||
heap.Push(tq.queue, item)
|
heap.Push(tq.queue, item)
|
||||||
tq.logger.Infow("任务已添加到队列", "taskID", task.GetID())
|
tq.logger.Infow("任务已添加到队列", "任务ID", task.GetID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNextTask 获取下一个要执行的任务(优先级最高的任务)
|
// GetNextTask 获取下一个要执行的任务(优先级最高的任务)
|
||||||
@@ -80,7 +80,7 @@ func (tq *TaskQueue) GetNextTask() Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
item := heap.Pop(tq.queue).(*taskItem)
|
item := heap.Pop(tq.queue).(*taskItem)
|
||||||
tq.logger.Infow("从队列中获取任务", "taskID", item.task.GetID())
|
tq.logger.Infow("从队列中获取任务", "任务ID", item.task.GetID())
|
||||||
return item.task
|
return item.task
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ func NewExecutor(workers int, logger *logs.Logger) *Executor {
|
|||||||
|
|
||||||
// Start 启动任务执行器
|
// Start 启动任务执行器
|
||||||
func (e *Executor) Start() {
|
func (e *Executor) Start() {
|
||||||
e.logger.Infow("正在启动任务执行器", "workers", e.workers)
|
e.logger.Infow("正在启动任务执行器", "工作协程数", e.workers)
|
||||||
|
|
||||||
// 启动工作协程
|
// 启动工作协程
|
||||||
for i := 0; i < e.workers; i++ {
|
for i := 0; i < e.workers; i++ {
|
||||||
@@ -187,31 +187,31 @@ func (e *Executor) Stop() {
|
|||||||
// SubmitTask 提交任务到执行器
|
// SubmitTask 提交任务到执行器
|
||||||
func (e *Executor) SubmitTask(task Task) {
|
func (e *Executor) SubmitTask(task Task) {
|
||||||
e.taskQueue.AddTask(task)
|
e.taskQueue.AddTask(task)
|
||||||
e.logger.Infow("任务已提交", "taskID", task.GetID())
|
e.logger.Infow("任务已提交", "任务ID", task.GetID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// worker 工作协程
|
// worker 工作协程
|
||||||
func (e *Executor) worker(id int) {
|
func (e *Executor) worker(id int) {
|
||||||
defer e.wg.Done()
|
defer e.wg.Done()
|
||||||
|
|
||||||
e.logger.Infow("工作协程已启动", "workerID", id)
|
e.logger.Infow("工作协程已启动", "工作协程ID", id)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-e.ctx.Done():
|
case <-e.ctx.Done():
|
||||||
e.logger.Infow("工作协程已停止", "workerID", id)
|
e.logger.Infow("工作协程已停止", "工作协程ID", id)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
// 获取下一个任务
|
// 获取下一个任务
|
||||||
task := e.taskQueue.GetNextTask()
|
task := e.taskQueue.GetNextTask()
|
||||||
if task != nil {
|
if task != nil {
|
||||||
e.logger.Infow("工作协程正在执行任务", "workerID", id, "taskID", task.GetID())
|
e.logger.Infow("工作协程正在执行任务", "工作协程ID", id, "任务ID", task.GetID())
|
||||||
|
|
||||||
// 执行任务
|
// 执行任务
|
||||||
if err := task.Execute(); err != nil {
|
if err := task.Execute(); err != nil {
|
||||||
e.logger.Errorw("任务执行失败", "workerID", id, "taskID", task.GetID(), "error", err)
|
e.logger.Errorw("任务执行失败", "工作协程ID", id, "任务ID", task.GetID(), "错误", err)
|
||||||
} else {
|
} else {
|
||||||
e.logger.Infow("任务执行成功", "workerID", id, "taskID", task.GetID())
|
e.logger.Infow("任务执行成功", "工作协程ID", id, "任务ID", task.GetID())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 没有任务时短暂休眠
|
// 没有任务时短暂休眠
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func (m *MockTask) ExecutedCount() int32 {
|
|||||||
return atomic.LoadInt32(&m.executed)
|
return atomic.LoadInt32(&m.executed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Helper function for robust waiting ---
|
// --- 健壮等待的辅助函数 ---
|
||||||
func waitForWaitGroup(t *testing.T, wg *sync.WaitGroup, timeout time.Duration) {
|
func waitForWaitGroup(t *testing.T, wg *sync.WaitGroup, timeout time.Duration) {
|
||||||
waitChan := make(chan struct{})
|
waitChan := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
@@ -70,13 +70,13 @@ func waitForWaitGroup(t *testing.T, wg *sync.WaitGroup, timeout time.Duration) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-waitChan:
|
case <-waitChan:
|
||||||
// Wait succeeded
|
// 等待成功
|
||||||
case <-time.After(timeout):
|
case <-time.After(timeout):
|
||||||
t.Fatal("timed out waiting for tasks to complete")
|
t.Fatal("等待任务完成超时")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- TaskQueue Tests (No changes needed) ---
|
// --- 任务队列测试 (无需更改) ---
|
||||||
|
|
||||||
func TestNewTaskQueue(t *testing.T) {
|
func TestNewTaskQueue(t *testing.T) {
|
||||||
tq := task.NewTaskQueue(testLogger)
|
tq := task.NewTaskQueue(testLogger)
|
||||||
@@ -92,7 +92,7 @@ func TestTaskQueue_AddTask(t *testing.T) {
|
|||||||
assert.Equal(t, 1, tq.GetTaskCount(), "添加任务后,队列中的任务数应为 1")
|
assert.Equal(t, 1, tq.GetTaskCount(), "添加任务后,队列中的任务数应为 1")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... (other TaskQueue tests remain the same)
|
// ... (其他任务队列测试保持不变)
|
||||||
func TestTaskQueue_GetNextTask(t *testing.T) {
|
func TestTaskQueue_GetNextTask(t *testing.T) {
|
||||||
t.Run("从空队列获取任务", func(t *testing.T) {
|
t.Run("从空队列获取任务", func(t *testing.T) {
|
||||||
tq := task.NewTaskQueue(testLogger)
|
tq := task.NewTaskQueue(testLogger)
|
||||||
@@ -157,7 +157,7 @@ func TestTaskQueue_Concurrency(t *testing.T) {
|
|||||||
assert.Equal(t, 0, tq.GetTaskCount(), "并发获取所有任务后,队列应为空")
|
assert.Equal(t, 0, tq.GetTaskCount(), "并发获取所有任务后,队列应为空")
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Executor Tests (Refactored for reliability) ---
|
// --- 执行器测试 (为可靠性重构) ---
|
||||||
|
|
||||||
func TestNewExecutor(t *testing.T) {
|
func TestNewExecutor(t *testing.T) {
|
||||||
executor := task.NewExecutor(5, testLogger)
|
executor := task.NewExecutor(5, testLogger)
|
||||||
@@ -294,7 +294,7 @@ func TestExecutor_StopWithPendingTasks(t *testing.T) {
|
|||||||
case <-task1Started:
|
case <-task1Started:
|
||||||
// task1 已开始,可以安全地停止执行器了
|
// task1 已开始,可以安全地停止执行器了
|
||||||
case <-time.After(1 * time.Second):
|
case <-time.After(1 * time.Second):
|
||||||
t.Fatal("timed out waiting for task1 to start")
|
t.Fatal("等待 task1 启动超时")
|
||||||
}
|
}
|
||||||
|
|
||||||
executor.Stop()
|
executor.Stop()
|
||||||
|
|||||||
Reference in New Issue
Block a user