Skip to content

Commit 229ce7f

Browse files
committed
add syn
1 parent ab49927 commit 229ce7f

File tree

6 files changed

+287
-2
lines changed

6 files changed

+287
-2
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package handler
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/zgsm-ai/codebase-indexer/internal/logic"
8+
"github.com/zgsm-ai/codebase-indexer/internal/response"
9+
"github.com/zgsm-ai/codebase-indexer/internal/svc"
10+
)
11+
12+
// completedTasksHandler 已完成任务处理器
13+
type completedTasksHandler struct {
14+
svcCtx *svc.ServiceContext
15+
}
16+
17+
// CompletedTasksHandler 创建已完成任务处理器
18+
func CompletedTasksHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
19+
return func(w http.ResponseWriter, r *http.Request) {
20+
handler := &completedTasksHandler{svcCtx: svcCtx}
21+
handler.ServeHTTP(w, r)
22+
}
23+
}
24+
25+
// ServeHTTP 处理HTTP请求
26+
func (h *completedTasksHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
27+
// 验证请求方法
28+
if r.Method != http.MethodGet {
29+
response.Error(w, fmt.Errorf("method not allowed"))
30+
return
31+
}
32+
33+
// 查询已完成任务
34+
completedTasksLogic := logic.NewCompletedTasksLogic(r.Context(), h.svcCtx)
35+
resp, err := completedTasksLogic.GetCompletedTasks()
36+
if err != nil {
37+
response.Error(w, err)
38+
return
39+
}
40+
41+
response.Json(w, resp)
42+
}

internal/handler/routes.go

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/logic/completed_tasks.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package logic
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"github.com/zgsm-ai/codebase-indexer/internal/svc"
9+
"github.com/zgsm-ai/codebase-indexer/internal/types"
10+
)
11+
12+
// CompletedTasksLogic 已完成任务查询逻辑
13+
type CompletedTasksLogic struct {
14+
ctx context.Context
15+
svcCtx *svc.ServiceContext
16+
}
17+
18+
// NewCompletedTasksLogic 创建已完成任务查询逻辑
19+
func NewCompletedTasksLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CompletedTasksLogic {
20+
return &CompletedTasksLogic{
21+
ctx: ctx,
22+
svcCtx: svcCtx,
23+
}
24+
}
25+
26+
// GetCompletedTasks 获取已完成任务
27+
func (l *CompletedTasksLogic) GetCompletedTasks() (*types.CompletedTasksResponse, error) {
28+
// 检查Redis连接
29+
if err := l.checkRedisConnection(); err != nil {
30+
return nil, fmt.Errorf("Redis服务不可用,请稍后再试")
31+
}
32+
33+
// 扫描已完成任务
34+
tasks, err := l.scanCompletedTasks()
35+
if err != nil {
36+
return nil, fmt.Errorf("查询已完成任务时发生内部错误: %w", err)
37+
}
38+
39+
return &types.CompletedTasksResponse{
40+
Code: 0,
41+
Message: "ok",
42+
Success: true,
43+
Data: &types.CompletedTasksData{
44+
TotalTasks: len(tasks),
45+
Tasks: tasks,
46+
},
47+
}, nil
48+
}
49+
50+
// checkRedisConnection 检查Redis连接
51+
func (l *CompletedTasksLogic) checkRedisConnection() error {
52+
ctx, cancel := context.WithTimeout(l.ctx, 5*time.Second)
53+
defer cancel()
54+
55+
return l.svcCtx.StatusManager.CheckConnection(ctx)
56+
}
57+
58+
// scanCompletedTasks 扫描已完成的任务
59+
func (l *CompletedTasksLogic) scanCompletedTasks() ([]types.CompletedTaskInfo, error) {
60+
return l.svcCtx.StatusManager.ScanCompletedTasks(l.ctx)
61+
}

internal/logic/embedding_task.go

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ func (l *TaskLogic) extractFileListFromShenmaSync(content []byte, fileName strin
431431
CodebasePath string `json:"codebasePath"`
432432
CodebaseName string `json:"codebaseName"`
433433
ExtraMetadata map[string]interface{} `json:"extraMetadata"`
434-
FileList map[string]string `json:"fileList"`
434+
FileList interface{} `json:"fileList"` // 使用interface{}来兼容两种格式
435435
Timestamp int64 `json:"timestamp"`
436436
}
437437

@@ -473,9 +473,49 @@ func (l *TaskLogic) extractFileListFromShenmaSync(content []byte, fileName strin
473473
metadata.ClientId = tempMetadata.ClientId
474474
metadata.CodebasePath = tempMetadata.CodebasePath
475475
metadata.CodebaseName = tempMetadata.CodebaseName
476-
metadata.FileList = tempMetadata.FileList
477476
metadata.Timestamp = tempMetadata.Timestamp
478477

478+
// 处理FileList的两种格式
479+
switch fileList := tempMetadata.FileList.(type) {
480+
case map[string]interface{}:
481+
// 格式1: "fileList":{"pkg/codegraph/analyzer/package_classifier/cpp_classifier.go":"add"}
482+
l.Logger.Infof("检测到对象格式的fileList")
483+
for filePath, operation := range fileList {
484+
if opStr, ok := operation.(string); ok {
485+
metadata.FileList[filePath] = opStr
486+
} else {
487+
l.Logger.Errorf("fileList中文件 %s 的操作类型不是字符串: %v", filePath, operation)
488+
}
489+
}
490+
case []interface{}:
491+
// 格式2: "fileList":[{"path":"pkg/codegraph/proto/codegraphpb/types.pb.go","targetPath":"","hash":"1755050845505","status":"modify","requestId":""}]
492+
l.Logger.Infof("检测到数组格式的fileList")
493+
for _, item := range fileList {
494+
if itemMap, ok := item.(map[string]interface{}); ok {
495+
if path, ok := itemMap["path"].(string); ok {
496+
// 优先使用status字段,如果没有则使用其他字段作为操作类型
497+
var operation string
498+
if status, ok := itemMap["status"].(string); ok {
499+
operation = status
500+
} else if operate, ok := itemMap["operate"].(string); ok {
501+
operation = operate
502+
} else {
503+
operation = "unknown"
504+
l.Logger.Errorf("fileList数组项中未找到status或operate字段: %v", itemMap)
505+
}
506+
metadata.FileList[path] = operation
507+
} else {
508+
l.Logger.Errorf("fileList数组项中缺少path字段: %v", itemMap)
509+
}
510+
} else {
511+
l.Logger.Errorf("fileList数组项不是map类型: %v", item)
512+
}
513+
}
514+
default:
515+
l.Logger.Errorf("不支持的fileList格式: %T", tempMetadata.FileList)
516+
return
517+
}
518+
479519
l.Logger.Infof("从 %s 中提取到 %d 个文件:", fileName, len(metadata.FileList))
480520

481521
// 打印fileList中的文件

internal/store/redis/status_manager.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,102 @@ func (sm *StatusManager) ResetPendingAndProcessingTasksToFailed(ctx context.Cont
284284
logx.Infof("Successfully reset %d pending/processing tasks to failed", updatedCount)
285285
return nil
286286
}
287+
288+
// ScanCompletedTasks 扫描已完成的任务
289+
func (sm *StatusManager) ScanCompletedTasks(ctx context.Context) ([]types.CompletedTaskInfo, error) {
290+
var completedTasks []types.CompletedTaskInfo
291+
292+
// 使用SCAN命令避免阻塞
293+
iter := sm.client.Scan(ctx, 0, "request:id:*", 0).Iterator()
294+
for iter.Next(ctx) {
295+
key := iter.Val()
296+
297+
// 获取任务状态数据
298+
data, err := sm.client.Get(ctx, key).Result()
299+
if err != nil {
300+
if err == redis.Nil {
301+
continue // 键可能已过期
302+
}
303+
return nil, fmt.Errorf("failed to get task data for key %s: %w", key, err)
304+
}
305+
306+
// 解析任务状态
307+
var status types.FileStatusResponseData
308+
if err := json.Unmarshal([]byte(data), &status); err != nil {
309+
continue // 跳过格式错误的数据
310+
}
311+
312+
// 过滤已完成的任务状态
313+
if sm.isCompletedStatus(status.Process) {
314+
taskInfo, err := sm.parseCompletedTaskInfo(key, status)
315+
if err != nil {
316+
continue
317+
}
318+
completedTasks = append(completedTasks, taskInfo)
319+
}
320+
}
321+
322+
if err := iter.Err(); err != nil {
323+
return nil, fmt.Errorf("redis scan error: %w", err)
324+
}
325+
326+
// 按完成时间排序(最新的在前)
327+
sort.Slice(completedTasks, func(i, j int) bool {
328+
return completedTasks[i].CompletedTime.After(completedTasks[j].CompletedTime)
329+
})
330+
331+
return completedTasks, nil
332+
}
333+
334+
// isCompletedStatus 检查是否为已完成的状态
335+
func (sm *StatusManager) isCompletedStatus(status string) bool {
336+
return status == "complete" || status == "success" || status == "failed" || status == "cancelled" || status == "timeout"
337+
}
338+
339+
// parseCompletedTaskInfo 解析已完成任务信息
340+
func (sm *StatusManager) parseCompletedTaskInfo(key string, status types.FileStatusResponseData) (types.CompletedTaskInfo, error) {
341+
// 从key中提取任务ID
342+
taskId := strings.TrimPrefix(key, "request:id:")
343+
344+
// 解析任务状态数据中的时间信息
345+
var completedTime time.Time
346+
347+
// 设置当前时间为完成时间
348+
completedTime = time.Now()
349+
350+
// 尝试从文件列表中提取客户端ID
351+
var clientId string
352+
var fileCount int
353+
var successCount, failedCount int
354+
355+
if len(status.FileList) > 0 {
356+
// 统计文件状态
357+
for _, file := range status.FileList {
358+
fileCount++
359+
if file.Status == "complete" || file.Status == "success" {
360+
successCount++
361+
} else if file.Status == "failed" {
362+
failedCount++
363+
}
364+
}
365+
}
366+
367+
// 计算成功率
368+
var successRate float64
369+
if fileCount > 0 {
370+
successRate = float64(successCount) / float64(fileCount) * 100
371+
}
372+
373+
return types.CompletedTaskInfo{
374+
TaskId: taskId,
375+
ClientId: clientId,
376+
Status: status.Process,
377+
Process: status.Process,
378+
TotalProgress: status.TotalProgress,
379+
CompletedTime: completedTime,
380+
FileCount: fileCount,
381+
SuccessCount: successCount,
382+
FailedCount: failedCount,
383+
SuccessRate: successRate,
384+
}, nil
385+
}

internal/types/completed_tasks.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package types
2+
3+
import "time"
4+
5+
// CompletedTaskInfo 已完成任务信息
6+
type CompletedTaskInfo struct {
7+
TaskId string `json:"taskId"` // 任务ID
8+
ClientId string `json:"clientId"` // 客户端ID
9+
Status string `json:"status"` // 任务状态
10+
Process string `json:"process"` // 处理进程
11+
TotalProgress int `json:"totalProgress"` // 总进度
12+
CompletedTime time.Time `json:"completedTime"` // 完成时间
13+
FileCount int `json:"fileCount"` // 文件总数
14+
SuccessCount int `json:"successCount"` // 成功文件数
15+
FailedCount int `json:"failedCount"` // 失败文件数
16+
SuccessRate float64 `json:"successRate"` // 成功率
17+
}
18+
19+
// CompletedTasksResponse 已完成任务查询响应
20+
type CompletedTasksResponse struct {
21+
Code int `json:"code"` // 响应码
22+
Message string `json:"message"` // 响应消息
23+
Success bool `json:"success"` // 是否成功
24+
Data *CompletedTasksData `json:"data"` // 任务数据
25+
}
26+
27+
// CompletedTasksData 已完成任务数据
28+
type CompletedTasksData struct {
29+
TotalTasks int `json:"totalTasks"` // 任务总数
30+
Tasks []CompletedTaskInfo `json:"tasks"` // 任务列表
31+
}

0 commit comments

Comments
 (0)