diff --git a/.gitignore b/.gitignore index 0f5fa2d27..2213eedc1 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ release/deployment/helm-chart/umbrella/Chart.lock **/kitex_remote_config.json .coda/ +.coco backend/script/errorx/.env .cursor/ AGENTS.md \ No newline at end of file diff --git a/backend/infra/platestwrite/latest_write_tracker.go b/backend/infra/platestwrite/latest_write_tracker.go index dd4707b02..24e1df987 100644 --- a/backend/infra/platestwrite/latest_write_tracker.go +++ b/backend/infra/platestwrite/latest_write_tracker.go @@ -136,4 +136,7 @@ const ( ResourceTypeTarget ResourceType = "eval_target" ResourceTypeTargetVersion ResourceType = "eval_target_version" ResourceTypeEvaluator ResourceType = "evaluator" + + ResourceTypeExptInsightAnalysisRecord ResourceType = "expt_insight_analysis_record" + ResourceTypeExptInsightAnalysisFeedback ResourceType = "expt_insight_analysis_feedback" ) diff --git a/backend/modules/evaluation/application/experiment_app.go b/backend/modules/evaluation/application/experiment_app.go index 0084651ee..88778c254 100644 --- a/backend/modules/evaluation/application/experiment_app.go +++ b/backend/modules/evaluation/application/experiment_app.go @@ -1129,12 +1129,21 @@ func (e *experimentApplication) InsightAnalysisExperiment(ctx context.Context, r if err != nil { return nil, err } + + var startTime, endTime *int64 + if got.StartAt != nil { + startTime = gptr.Of(got.StartAt.UnixMilli()) + } + if got.EndAt != nil { + endTime = gptr.Of(got.EndAt.UnixMilli()) + } + recordID, err := e.CreateAnalysisRecord(ctx, &entity.ExptInsightAnalysisRecord{ SpaceID: req.GetWorkspaceID(), ExptID: req.GetExptID(), CreatedBy: session.UserID, Status: entity.InsightAnalysisStatus_Running, - }, session) + }, session, gptr.Indirect(startTime), gptr.Indirect(endTime)) if err != nil { return nil, err } @@ -1151,7 +1160,6 @@ func (e *experimentApplication) ListExptInsightAnalysisRecord(ctx context.Contex UserID: strconv.FormatInt(gptr.Indirect(req.Session.UserID), 10), } } - err = e.auth.Authorization(ctx, &rpc.AuthorizationParam{ ObjectID: strconv.FormatInt(req.WorkspaceID, 10), SpaceID: req.WorkspaceID, @@ -1160,6 +1168,9 @@ func (e *experimentApplication) ListExptInsightAnalysisRecord(ctx context.Contex if err != nil { return nil, err } + + // First record contains the upvote/downvote count info for display purpose, + // Other records' feedback is not necessary for this list api records, total, err := e.ListAnalysisRecord(ctx, req.GetWorkspaceID(), req.GetExptID(), entity.NewPage(int(req.GetPageNumber()), int(req.GetPageSize())), session) if err != nil { return nil, err diff --git a/backend/modules/evaluation/application/experiment_app_test.go b/backend/modules/evaluation/application/experiment_app_test.go index 7512843de..99416658f 100644 --- a/backend/modules/evaluation/application/experiment_app_test.go +++ b/backend/modules/evaluation/application/experiment_app_test.go @@ -10,6 +10,7 @@ import ( "reflect" "strconv" "testing" + "time" "github.com/bytedance/gg/gptr" "github.com/stretchr/testify/assert" @@ -3736,11 +3737,15 @@ func TestInsightAnalysisExperiment(t *testing.T) { t.Run("成功创建洞察分析", func(t *testing.T) { // Mock the manager.Get call - mockManager.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&entity.Experiment{CreatedBy: "test-user"}, nil) + mockManager.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&entity.Experiment{ + CreatedBy: "test-user", + StartAt: &[]time.Time{time.Now()}[0], + EndAt: &[]time.Time{time.Now()}[0], + }, nil) // Mock the auth.AuthorizationWithoutSPI call mockAuth.EXPECT().AuthorizationWithoutSPI(gomock.Any(), gomock.Any()).Return(nil) // Mock the CreateAnalysisRecord call - mockInsightService.EXPECT().CreateAnalysisRecord(gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(123), nil) + mockInsightService.EXPECT().CreateAnalysisRecord(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(123), nil) _, err := app.InsightAnalysisExperiment(ctx, req) assert.NoError(t, err) @@ -3764,9 +3769,13 @@ func TestInsightAnalysisExperiment(t *testing.T) { }) t.Run("创建分析记录失败", func(t *testing.T) { - mockManager.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&entity.Experiment{CreatedBy: "test-user"}, nil) + mockManager.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&entity.Experiment{ + CreatedBy: "test-user", + StartAt: &[]time.Time{time.Now()}[0], + EndAt: &[]time.Time{time.Now()}[0], + }, nil) mockAuth.EXPECT().AuthorizationWithoutSPI(gomock.Any(), gomock.Any()).Return(nil) - mockInsightService.EXPECT().CreateAnalysisRecord(gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(0), errors.New("create analysis record error")) + mockInsightService.EXPECT().CreateAnalysisRecord(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(0), errors.New("create analysis record error")) _, err := app.InsightAnalysisExperiment(ctx, req) assert.Error(t, err) diff --git a/backend/modules/evaluation/application/wire_gen.go b/backend/modules/evaluation/application/wire_gen.go index 701d4b2ae..7a90a96f2 100644 --- a/backend/modules/evaluation/application/wire_gen.go +++ b/backend/modules/evaluation/application/wire_gen.go @@ -156,7 +156,7 @@ func InitExperimentApplication(ctx context.Context, idgen2 idgen.IIDGenerator, d iExptInsightAnalysisRecordDAO := mysql.NewExptInsightAnalysisRecordDAO(db2) iExptInsightAnalysisFeedbackCommentDAO := mysql.NewExptInsightAnalysisFeedbackCommentDAO(db2) iExptInsightAnalysisFeedbackVoteDAO := mysql.NewExptInsightAnalysisFeedbackVoteDAO(db2) - iExptInsightAnalysisRecordRepo := experiment.NewExptInsightAnalysisRecordRepo(iExptInsightAnalysisRecordDAO, iExptInsightAnalysisFeedbackCommentDAO, iExptInsightAnalysisFeedbackVoteDAO, idgen2) + iExptInsightAnalysisRecordRepo := experiment.NewExptInsightAnalysisRecordRepo(iExptInsightAnalysisRecordDAO, iExptInsightAnalysisFeedbackCommentDAO, iExptInsightAnalysisFeedbackVoteDAO, idgen2, iLatestWriteTracker) iAgentAdapter := agent.NewAgentAdapter() iNotifyRPCAdapter := notify.NewNotifyRPCAdapter() iExptInsightAnalysisService := service.NewInsightAnalysisService(iExptInsightAnalysisRecordRepo, exptEventPublisher, objectStorage, iAgentAdapter, iExptResultExportService, iNotifyRPCAdapter, iUserProvider, iExperimentRepo) @@ -235,7 +235,7 @@ func InitEvalTargetApplication(ctx context.Context, idgen2 idgen.IIDGenerator, d return evalTargetService } -func InitEvalOpenAPIApplication(ctx context.Context, configFactory conf.IConfigLoaderFactory, rmqFactory mq.IFactory, cmdable redis.Cmdable, idgen2 idgen.IIDGenerator, db2 db.Provider, client promptmanageservice.Client, executeClient promptexecuteservice.Client, authClient authservice.Client, meter metrics.Meter, dataClient datasetservice.Client, userClient userservice.Client, llmClient llmruntimeservice.Client, tagClient tagservice.Client, limiterFactory limiter.IRateLimiterFactory, objectStorage fileserver.ObjectStorage, auditClient audit.IAuditService, benefitService benefit.IBenefitService, ckProvider ck.Provider) (IEvalOpenAPIApplication, error) { +func InitEvalOpenAPIApplication(ctx context.Context, configFactory conf.IConfigLoaderFactory, rmqFactory mq.IFactory, cmdable redis.Cmdable, idgen2 idgen.IIDGenerator, db2 db.Provider, client promptmanageservice.Client, executeClient promptexecuteservice.Client, authClient authservice.Client, meter metrics.Meter, dataClient datasetservice.Client, userClient userservice.Client, llmClient llmruntimeservice.Client, tagClient tagservice.Client, limiterFactory limiter.IRateLimiterFactory, objectStorage fileserver.ObjectStorage, auditClient audit.IAuditService, benefitService benefit.IBenefitService, ckProvider ck.Provider) (evaluation.EvalOpenAPIService, error) { iEvalAsyncDAO := dao.NewEvalAsyncDAO(cmdable) iEvalAsyncRepo := experiment.NewEvalAsyncRepo(iEvalAsyncDAO) exptEventPublisher, err := producer.NewExptEventPublisher(ctx, configFactory, rmqFactory) @@ -326,13 +326,13 @@ func InitEvalOpenAPIApplication(ctx context.Context, configFactory conf.IConfigL iExptInsightAnalysisRecordDAO := mysql.NewExptInsightAnalysisRecordDAO(db2) iExptInsightAnalysisFeedbackCommentDAO := mysql.NewExptInsightAnalysisFeedbackCommentDAO(db2) iExptInsightAnalysisFeedbackVoteDAO := mysql.NewExptInsightAnalysisFeedbackVoteDAO(db2) - iExptInsightAnalysisRecordRepo := experiment.NewExptInsightAnalysisRecordRepo(iExptInsightAnalysisRecordDAO, iExptInsightAnalysisFeedbackCommentDAO, iExptInsightAnalysisFeedbackVoteDAO, idgen2) + iExptInsightAnalysisRecordRepo := experiment.NewExptInsightAnalysisRecordRepo(iExptInsightAnalysisRecordDAO, iExptInsightAnalysisFeedbackCommentDAO, iExptInsightAnalysisFeedbackVoteDAO, idgen2, iLatestWriteTracker) iAgentAdapter := agent.NewAgentAdapter() iNotifyRPCAdapter := notify.NewNotifyRPCAdapter() iExptInsightAnalysisService := service.NewInsightAnalysisService(iExptInsightAnalysisRecordRepo, exptEventPublisher, objectStorage, iAgentAdapter, iExptResultExportService, iNotifyRPCAdapter, iUserProvider, iExperimentRepo) iExperimentApplication := NewExperimentApplication(exptAggrResultService, exptResultService, iExptManager, exptSchedulerEvent, exptItemEvalEvent, idgen2, componentIConfiger, iAuthProvider, userInfoService, iEvalTargetService, evaluationSetItemService, iExptAnnotateService, iTagRPCAdapter, iExptResultExportService, iExptInsightAnalysisService) - v3 := NewEvalOpenAPIApplication(iEvalAsyncRepo, exptEventPublisher, iEvalTargetService, iAuthProvider, iEvaluationSetService, evaluationSetVersionService, evaluationSetItemService, evaluationSetSchemaService, openAPIEvaluationMetrics, userInfoService, iExperimentApplication, iExptManager, exptResultService, exptAggrResultService, evaluatorService) - return v3, nil + evalOpenAPIService := NewEvalOpenAPIApplication(iEvalAsyncRepo, exptEventPublisher, iEvalTargetService, iAuthProvider, iEvaluationSetService, evaluationSetVersionService, evaluationSetItemService, evaluationSetSchemaService, openAPIEvaluationMetrics, userInfoService, iExperimentApplication, iExptManager, exptResultService, exptAggrResultService, evaluatorService) + return evalOpenAPIService, nil } // wire.go: diff --git a/backend/modules/evaluation/domain/component/rpc/mocks/trace_agent.go b/backend/modules/evaluation/domain/component/rpc/mocks/trace_agent.go index 509b8a761..8ba43466c 100644 --- a/backend/modules/evaluation/domain/component/rpc/mocks/trace_agent.go +++ b/backend/modules/evaluation/domain/component/rpc/mocks/trace_agent.go @@ -42,18 +42,18 @@ func (m *MockIAgentAdapter) EXPECT() *MockIAgentAdapterMockRecorder { } // CallTraceAgent mocks base method. -func (m *MockIAgentAdapter) CallTraceAgent(ctx context.Context, spaceID int64, url string) (int64, error) { +func (m *MockIAgentAdapter) CallTraceAgent(ctx context.Context, spaceID int64, url string, startTime, endTime int64) (int64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CallTraceAgent", ctx, spaceID, url) + ret := m.ctrl.Call(m, "CallTraceAgent", ctx, spaceID, url, startTime, endTime) ret0, _ := ret[0].(int64) ret1, _ := ret[1].(error) return ret0, ret1 } // CallTraceAgent indicates an expected call of CallTraceAgent. -func (mr *MockIAgentAdapterMockRecorder) CallTraceAgent(ctx, spaceID, url any) *gomock.Call { +func (mr *MockIAgentAdapterMockRecorder) CallTraceAgent(ctx, spaceID, url, startTime, endTime any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CallTraceAgent", reflect.TypeOf((*MockIAgentAdapter)(nil).CallTraceAgent), ctx, spaceID, url) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CallTraceAgent", reflect.TypeOf((*MockIAgentAdapter)(nil).CallTraceAgent), ctx, spaceID, url, startTime, endTime) } // GetReport mocks base method. diff --git a/backend/modules/evaluation/domain/component/rpc/trace_agent.go b/backend/modules/evaluation/domain/component/rpc/trace_agent.go index 658736cae..97e30910c 100644 --- a/backend/modules/evaluation/domain/component/rpc/trace_agent.go +++ b/backend/modules/evaluation/domain/component/rpc/trace_agent.go @@ -11,6 +11,6 @@ import ( //go:generate mockgen -destination=mocks/trace_agent.go -package=mocks . IAgentAdapter type IAgentAdapter interface { - CallTraceAgent(ctx context.Context, spaceID int64, url string) (int64, error) + CallTraceAgent(ctx context.Context, spaceID int64, url string, startTime, endTime int64) (int64, error) GetReport(ctx context.Context, spaceID, reportID int64) (report string, status entity.ReportStatus, err error) } diff --git a/backend/modules/evaluation/domain/entity/event.go b/backend/modules/evaluation/domain/entity/event.go index 05d309766..3e8b6bc95 100644 --- a/backend/modules/evaluation/domain/entity/event.go +++ b/backend/modules/evaluation/domain/entity/event.go @@ -120,9 +120,11 @@ type ExportCSVEvent struct { ExperimentID int64 SpaceID int64 - Session *Session - ExportScene ExportScene - CreatedAt int64 + Session *Session + ExportScene ExportScene + CreatedAt int64 + ExptStartTime int64 // Unix Time + ExptEndTime int64 // Unix Time } type ExportScene int diff --git a/backend/modules/evaluation/domain/entity/expt_insight_analysis_record.go b/backend/modules/evaluation/domain/entity/expt_insight_analysis_record.go index ff35af7c8..bfb50f901 100644 --- a/backend/modules/evaluation/domain/entity/expt_insight_analysis_record.go +++ b/backend/modules/evaluation/domain/entity/expt_insight_analysis_record.go @@ -14,6 +14,10 @@ const ( InsightAnalysisStatus_Failed InsightAnalysisStatus = 3 ) +const ( + InsightAnalysisRunningTimeout = 2 * time.Hour +) + type ExptInsightAnalysisRecord struct { ID int64 SpaceID int64 diff --git a/backend/modules/evaluation/domain/service/insight_analysis.go b/backend/modules/evaluation/domain/service/insight_analysis.go index e345fd7be..623dca355 100644 --- a/backend/modules/evaluation/domain/service/insight_analysis.go +++ b/backend/modules/evaluation/domain/service/insight_analysis.go @@ -10,8 +10,8 @@ import ( ) type IExptInsightAnalysisService interface { - CreateAnalysisRecord(ctx context.Context, record *entity.ExptInsightAnalysisRecord, session *entity.Session) (int64, error) - GenAnalysisReport(ctx context.Context, spaceID, exptID, recordID, CreateAt int64) error + CreateAnalysisRecord(ctx context.Context, record *entity.ExptInsightAnalysisRecord, session *entity.Session, startTime, endTime int64) (int64, error) + GenAnalysisReport(ctx context.Context, spaceID, exptID, recordID, CreateAt, startTime, endTime int64) error GetAnalysisRecordByID(ctx context.Context, spaceID, exptID, recordID int64, session *entity.Session) (*entity.ExptInsightAnalysisRecord, error) ListAnalysisRecord(ctx context.Context, spaceID, exptID int64, page entity.Page, session *entity.Session) ([]*entity.ExptInsightAnalysisRecord, int64, error) DeleteAnalysisRecord(ctx context.Context, spaceID, exptID, recordID int64) error diff --git a/backend/modules/evaluation/domain/service/insight_analysis_impl.go b/backend/modules/evaluation/domain/service/insight_analysis_impl.go index 9f5869464..ec45b6b27 100644 --- a/backend/modules/evaluation/domain/service/insight_analysis_impl.go +++ b/backend/modules/evaluation/domain/service/insight_analysis_impl.go @@ -55,18 +55,20 @@ func NewInsightAnalysisService(repo repo.IExptInsightAnalysisRecordRepo, } } -func (e ExptInsightAnalysisServiceImpl) CreateAnalysisRecord(ctx context.Context, record *entity.ExptInsightAnalysisRecord, session *entity.Session) (int64, error) { +func (e ExptInsightAnalysisServiceImpl) CreateAnalysisRecord(ctx context.Context, record *entity.ExptInsightAnalysisRecord, session *entity.Session, startTime, endTime int64) (int64, error) { recordID, err := e.repo.CreateAnalysisRecord(ctx, record) if err != nil { return 0, err } exportEvent := &entity.ExportCSVEvent{ - ExportID: recordID, - ExperimentID: record.ExptID, - SpaceID: record.SpaceID, - ExportScene: entity.ExportSceneInsightAnalysis, - CreatedAt: time.Now().Unix(), + ExportID: recordID, + ExperimentID: record.ExptID, + SpaceID: record.SpaceID, + ExportScene: entity.ExportSceneInsightAnalysis, + CreatedAt: time.Now().Unix(), + ExptStartTime: startTime, + ExptEndTime: endTime, } err = e.exptPublisher.PublishExptExportCSVEvent(ctx, exportEvent, gptr.Of(time.Second*3)) if err != nil { @@ -76,7 +78,7 @@ func (e ExptInsightAnalysisServiceImpl) CreateAnalysisRecord(ctx context.Context return recordID, nil } -func (e ExptInsightAnalysisServiceImpl) GenAnalysisReport(ctx context.Context, spaceID, exptID, recordID, CreateAt int64) (err error) { +func (e ExptInsightAnalysisServiceImpl) GenAnalysisReport(ctx context.Context, spaceID, exptID, recordID, CreateAt, startTime, endTime int64) (err error) { analysisRecord, err := e.repo.GetAnalysisRecordByID(ctx, spaceID, exptID, recordID) if err != nil { return err @@ -125,7 +127,7 @@ func (e ExptInsightAnalysisServiceImpl) GenAnalysisReport(ctx context.Context, s return err } - reportID, err := e.agentAdapter.CallTraceAgent(ctx, spaceID, url) + reportID, err := e.agentAdapter.CallTraceAgent(ctx, spaceID, url, startTime, endTime) if err != nil { return err } @@ -135,11 +137,13 @@ func (e ExptInsightAnalysisServiceImpl) GenAnalysisReport(ctx context.Context, s // 发送时间检查分析报告生成状态 exportEvent := &entity.ExportCSVEvent{ - ExportID: recordID, - ExperimentID: exptID, - SpaceID: spaceID, - ExportScene: entity.ExportSceneInsightAnalysis, - CreatedAt: CreateAt, + ExportID: recordID, + ExperimentID: exptID, + SpaceID: spaceID, + ExportScene: entity.ExportSceneInsightAnalysis, + CreatedAt: CreateAt, + ExptStartTime: startTime, + ExptEndTime: endTime, } err = e.exptPublisher.PublishExptExportCSVEvent(ctx, exportEvent, gptr.Of(time.Minute*3)) if err != nil { @@ -154,6 +158,14 @@ func (e ExptInsightAnalysisServiceImpl) checkAnalysisReportGenStatus(ctx context if err != nil { return err } + + // 超过3小时,未生成分析报告,认为是失败 + if status == entity.ReportStatus_Running && record.CreatedAt.Add(entity.InsightAnalysisRunningTimeout).Unix() <= time.Now().Unix() { + record.Status = entity.InsightAnalysisStatus_Failed + logs.CtxWarn(ctx, "checkAnalysisReportGenStatus found timeout event, expt_id: %v, record_id: %v", record.ExptID, record.ID) + return e.repo.UpdateAnalysisRecord(ctx, record) + } + if status == entity.ReportStatus_Failed { record.Status = entity.InsightAnalysisStatus_Failed return e.repo.UpdateAnalysisRecord(ctx, record) @@ -195,6 +207,15 @@ func (e ExptInsightAnalysisServiceImpl) GetAnalysisRecordByID(ctx context.Contex return nil, err } + if analysisRecord.Status == entity.InsightAnalysisStatus_Running && analysisRecord.CreatedAt.Add(entity.InsightAnalysisRunningTimeout).Unix() < time.Now().Unix() { + analysisRecord.Status = entity.InsightAnalysisStatus_Failed + err = e.repo.UpdateAnalysisRecord(ctx, analysisRecord) + if err != nil { + logs.CtxError(ctx, "GetAnalysisRecordByID: UpdateAnalysisRecord failed: %v", err) + } + return analysisRecord, err + } + if analysisRecord.Status == entity.InsightAnalysisStatus_Running || analysisRecord.Status == entity.InsightAnalysisStatus_Failed { return analysisRecord, nil @@ -254,7 +275,40 @@ func (e ExptInsightAnalysisServiceImpl) notifyAnalysisComplete(ctx context.Conte } func (e ExptInsightAnalysisServiceImpl) ListAnalysisRecord(ctx context.Context, spaceID, exptID int64, page entity.Page, session *entity.Session) ([]*entity.ExptInsightAnalysisRecord, int64, error) { - return e.repo.ListAnalysisRecord(ctx, spaceID, exptID, page) + analysisRecords, total, err := e.repo.ListAnalysisRecord(ctx, spaceID, exptID, page) + if err != nil { + return nil, 0, err + } + if total == 0 { + return analysisRecords, total, nil + } + + firstAnalysisRecord := analysisRecords[0] + + upvoteCount, downvoteCount, err := e.repo.CountFeedbackVote(ctx, spaceID, exptID, firstAnalysisRecord.ID) + if err != nil { + // side path, don't block the main flow + logs.CtxWarn(ctx, "CountFeedbackVote failed for space_id: %v, expt_id: %v, record_id: %v, err=%v", spaceID, exptID, firstAnalysisRecord.ID, err) + return analysisRecords, total, nil + } + + curUserFeedbackVote, err := e.repo.GetFeedbackVoteByUser(ctx, spaceID, exptID, firstAnalysisRecord.ID, session.UserID) + if err != nil { + // side path, don't block the main flow + logs.CtxWarn(ctx, "GetFeedbackVoteByUser failed for space_id: %v, expt_id: %v, record_id: %v, err=%v", spaceID, exptID, firstAnalysisRecord.ID, err) + return analysisRecords, total, nil + } + firstAnalysisRecord.ExptInsightAnalysisFeedback = entity.ExptInsightAnalysisFeedback{ + UpvoteCount: upvoteCount, + DownvoteCount: downvoteCount, + CurrentUserVoteType: entity.None, + } + firstAnalysisRecord.ExptInsightAnalysisFeedback.CurrentUserVoteType = entity.None + if curUserFeedbackVote != nil { + firstAnalysisRecord.ExptInsightAnalysisFeedback.CurrentUserVoteType = curUserFeedbackVote.VoteType + } + + return analysisRecords, total, nil } func (e ExptInsightAnalysisServiceImpl) DeleteAnalysisRecord(ctx context.Context, spaceID, exptID, recordID int64) error { diff --git a/backend/modules/evaluation/domain/service/insight_analysis_impl_test.go b/backend/modules/evaluation/domain/service/insight_analysis_impl_test.go index d4b434070..dbf918b6e 100644 --- a/backend/modules/evaluation/domain/service/insight_analysis_impl_test.go +++ b/backend/modules/evaluation/domain/service/insight_analysis_impl_test.go @@ -134,7 +134,7 @@ func TestExptInsightAnalysisServiceImpl_CreateAnalysisRecord(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.setup() - result, err := service.CreateAnalysisRecord(ctx, tt.record, tt.session) + result, err := service.CreateAnalysisRecord(ctx, tt.record, tt.session, 0, 0) if tt.wantErr { assert.Error(t, err) } else { @@ -172,7 +172,7 @@ func TestExptInsightAnalysisServiceImpl_GenAnalysisReport(t *testing.T) { }, nil) mocks.exptResultExportService.EXPECT().DoExportCSV(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mocks.fileClient.EXPECT().SignDownloadReq(gomock.Any(), gomock.Any(), gomock.Any()).Return("http://test-url.com", make(map[string][]string), nil) - mocks.agentAdapter.EXPECT().CallTraceAgent(gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(123), nil) + mocks.agentAdapter.EXPECT().CallTraceAgent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(123), nil) mocks.publisher.EXPECT().PublishExptExportCSVEvent(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mocks.repo.EXPECT().UpdateAnalysisRecord(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }, @@ -266,7 +266,7 @@ func TestExptInsightAnalysisServiceImpl_GenAnalysisReport(t *testing.T) { }, nil) mocks.exptResultExportService.EXPECT().DoExportCSV(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mocks.fileClient.EXPECT().SignDownloadReq(gomock.Any(), gomock.Any(), gomock.Any()).Return("http://test-url.com", make(map[string][]string), nil) - mocks.agentAdapter.EXPECT().CallTraceAgent(gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(0), errors.New("agent error")) + mocks.agentAdapter.EXPECT().CallTraceAgent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(0), errors.New("agent error")) mocks.repo.EXPECT().UpdateAnalysisRecord(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, record *entity.ExptInsightAnalysisRecord, opts ...db.Option) error { assert.Equal(t, entity.InsightAnalysisStatus_Failed, record.Status) return nil @@ -289,7 +289,7 @@ func TestExptInsightAnalysisServiceImpl_GenAnalysisReport(t *testing.T) { }, nil) mocks.exptResultExportService.EXPECT().DoExportCSV(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) mocks.fileClient.EXPECT().SignDownloadReq(gomock.Any(), gomock.Any(), gomock.Any()).Return("http://test-url.com", make(map[string][]string), nil) - mocks.agentAdapter.EXPECT().CallTraceAgent(gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(123), nil) + mocks.agentAdapter.EXPECT().CallTraceAgent(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(int64(123), nil) mocks.publisher.EXPECT().PublishExptExportCSVEvent(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("publish error")) mocks.repo.EXPECT().UpdateAnalysisRecord(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, record *entity.ExptInsightAnalysisRecord, opts ...db.Option) error { assert.Equal(t, entity.InsightAnalysisStatus_Failed, record.Status) @@ -325,7 +325,7 @@ func TestExptInsightAnalysisServiceImpl_GenAnalysisReport(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.setup() - err := service.GenAnalysisReport(ctx, tt.spaceID, tt.exptID, tt.recordID, tt.createAt) + err := service.GenAnalysisReport(ctx, tt.spaceID, tt.exptID, tt.recordID, tt.createAt, 0, 0) if tt.wantErr { assert.Error(t, err) } else { diff --git a/backend/modules/evaluation/domain/service/mocks/insight_analysis.go b/backend/modules/evaluation/domain/service/mocks/insight_analysis.go index 78d1223d8..7c8ad5c62 100644 --- a/backend/modules/evaluation/domain/service/mocks/insight_analysis.go +++ b/backend/modules/evaluation/domain/service/mocks/insight_analysis.go @@ -36,18 +36,18 @@ func (m *MockIExptInsightAnalysisService) EXPECT() *MockIExptInsightAnalysisServ } // CreateAnalysisRecord mocks base method. -func (m *MockIExptInsightAnalysisService) CreateAnalysisRecord(arg0 context.Context, arg1 *entity.ExptInsightAnalysisRecord, arg2 *entity.Session) (int64, error) { +func (m *MockIExptInsightAnalysisService) CreateAnalysisRecord(arg0 context.Context, arg1 *entity.ExptInsightAnalysisRecord, arg2 *entity.Session, arg3, arg4 int64) (int64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateAnalysisRecord", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "CreateAnalysisRecord", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(int64) ret1, _ := ret[1].(error) return ret0, ret1 } // CreateAnalysisRecord indicates an expected call of CreateAnalysisRecord. -func (mr *MockIExptInsightAnalysisServiceMockRecorder) CreateAnalysisRecord(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockIExptInsightAnalysisServiceMockRecorder) CreateAnalysisRecord(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAnalysisRecord", reflect.TypeOf((*MockIExptInsightAnalysisService)(nil).CreateAnalysisRecord), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAnalysisRecord", reflect.TypeOf((*MockIExptInsightAnalysisService)(nil).CreateAnalysisRecord), arg0, arg1, arg2, arg3, arg4) } // DeleteAnalysisRecord mocks base method. @@ -79,17 +79,17 @@ func (mr *MockIExptInsightAnalysisServiceMockRecorder) FeedbackExptInsightAnalys } // GenAnalysisReport mocks base method. -func (m *MockIExptInsightAnalysisService) GenAnalysisReport(arg0 context.Context, arg1, arg2, arg3, arg4 int64) error { +func (m *MockIExptInsightAnalysisService) GenAnalysisReport(arg0 context.Context, arg1, arg2, arg3, arg4, arg5, arg6 int64) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GenAnalysisReport", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "GenAnalysisReport", arg0, arg1, arg2, arg3, arg4, arg5, arg6) ret0, _ := ret[0].(error) return ret0 } // GenAnalysisReport indicates an expected call of GenAnalysisReport. -func (mr *MockIExptInsightAnalysisServiceMockRecorder) GenAnalysisReport(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockIExptInsightAnalysisServiceMockRecorder) GenAnalysisReport(arg0, arg1, arg2, arg3, arg4, arg5, arg6 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenAnalysisReport", reflect.TypeOf((*MockIExptInsightAnalysisService)(nil).GenAnalysisReport), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenAnalysisReport", reflect.TypeOf((*MockIExptInsightAnalysisService)(nil).GenAnalysisReport), arg0, arg1, arg2, arg3, arg4, arg5, arg6) } // GetAnalysisRecordByID mocks base method. diff --git a/backend/modules/evaluation/infra/mq/rocket/consumer/expt_export.go b/backend/modules/evaluation/infra/mq/rocket/consumer/expt_export.go index 07e44f0fa..b3a3603b8 100644 --- a/backend/modules/evaluation/infra/mq/rocket/consumer/expt_export.go +++ b/backend/modules/evaluation/infra/mq/rocket/consumer/expt_export.go @@ -53,7 +53,7 @@ func (e *ExptExportConsumer) HandleMessage(ctx context.Context, ext *mq.MessageE func (e *ExptExportConsumer) handleEvent(ctx context.Context, event *entity.ExportCSVEvent) (err error) { switch event.ExportScene { case entity.ExportSceneInsightAnalysis: - err = e.exptInsightAnalysisService.GenAnalysisReport(ctx, event.SpaceID, event.ExperimentID, event.ExportID, event.CreatedAt) + err = e.exptInsightAnalysisService.GenAnalysisReport(ctx, event.SpaceID, event.ExperimentID, event.ExportID, event.CreatedAt, event.ExptStartTime, event.ExptEndTime) if err != nil { logs.CtxError(ctx, "ExptExportConsumer GenAnalysisReport fail, expt_id:%v, err: %v", event.ExperimentID, err) return nil diff --git a/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record.go b/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record.go index de1355145..ff0c48ea2 100644 --- a/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record.go +++ b/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record.go @@ -5,9 +5,11 @@ package experiment import ( "context" + "fmt" "github.com/coze-dev/coze-loop/backend/infra/db" "github.com/coze-dev/coze-loop/backend/infra/idgen" + "github.com/coze-dev/coze-loop/backend/infra/platestwrite" "github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/entity" "github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/repo" "github.com/coze-dev/coze-loop/backend/modules/evaluation/infra/repo/experiment/mysql" @@ -19,6 +21,7 @@ type ExptInsightAnalysisRecordRepo struct { exptInsightAnalysisFeedbackCommentDAO mysql.IExptInsightAnalysisFeedbackCommentDAO exptInsightAnalysisFeedbackVoteDAO mysql.IExptInsightAnalysisFeedbackVoteDAO idgenerator idgen.IIDGenerator + writeTracker platestwrite.ILatestWriteTracker } func NewExptInsightAnalysisRecordRepo( @@ -26,12 +29,14 @@ func NewExptInsightAnalysisRecordRepo( exptInsightAnalysisFeedbackCommentDAO mysql.IExptInsightAnalysisFeedbackCommentDAO, exptInsightAnalysisFeedbackVoteDAO mysql.IExptInsightAnalysisFeedbackVoteDAO, idgenerator idgen.IIDGenerator, + writeTracker platestwrite.ILatestWriteTracker, ) repo.IExptInsightAnalysisRecordRepo { return &ExptInsightAnalysisRecordRepo{ exptInsightAnalysisRecordDAO: exptInsightAnalysisRecordDAO, exptInsightAnalysisFeedbackCommentDAO: exptInsightAnalysisFeedbackCommentDAO, exptInsightAnalysisFeedbackVoteDAO: exptInsightAnalysisFeedbackVoteDAO, idgenerator: idgenerator, + writeTracker: writeTracker, } } @@ -47,15 +52,34 @@ func (e ExptInsightAnalysisRecordRepo) CreateAnalysisRecord(ctx context.Context, return 0, err } + if e.writeTracker != nil { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisRecord, id, + platestwrite.SetWithSearchParam(buildRecordSearchParam(record.SpaceID, record.ExptID))) + } + return id, nil } func (e ExptInsightAnalysisRecordRepo) UpdateAnalysisRecord(ctx context.Context, record *entity.ExptInsightAnalysisRecord, opts ...db.Option) error { - return e.exptInsightAnalysisRecordDAO.Update(ctx, convert.ExptInsightAnalysisRecordDOToPO(record), opts...) + if err := e.exptInsightAnalysisRecordDAO.Update(ctx, convert.ExptInsightAnalysisRecordDOToPO(record), opts...); err != nil { + return err + } + + if e.writeTracker != nil { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisRecord, record.ID, + platestwrite.SetWithSearchParam(buildRecordSearchParam(record.SpaceID, record.ExptID))) + } + + return nil } func (e ExptInsightAnalysisRecordRepo) GetAnalysisRecordByID(ctx context.Context, spaceID, exptID, recordID int64) (*entity.ExptInsightAnalysisRecord, error) { - po, err := e.exptInsightAnalysisRecordDAO.GetByID(ctx, spaceID, exptID, recordID) + opts := make([]db.Option, 0) + if e.needForceMasterByRecord(ctx, platestwrite.ResourceTypeExptInsightAnalysisRecord, recordID, buildRecordSearchParam(spaceID, exptID)) { + opts = append(opts, db.WithMaster()) + } + + po, err := e.exptInsightAnalysisRecordDAO.GetByID(ctx, spaceID, exptID, recordID, opts...) if err != nil { return nil, err } @@ -64,7 +88,11 @@ func (e ExptInsightAnalysisRecordRepo) GetAnalysisRecordByID(ctx context.Context } func (e ExptInsightAnalysisRecordRepo) ListAnalysisRecord(ctx context.Context, spaceID, exptID int64, page entity.Page) ([]*entity.ExptInsightAnalysisRecord, int64, error) { - pos, total, err := e.exptInsightAnalysisRecordDAO.List(ctx, spaceID, exptID, page) + opts := make([]db.Option, 0) + if e.needForceMasterByRecord(ctx, platestwrite.ResourceTypeExptInsightAnalysisRecord, 0, buildRecordSearchParam(spaceID, exptID)) { + opts = append(opts, db.WithMaster()) + } + pos, total, err := e.exptInsightAnalysisRecordDAO.List(ctx, spaceID, exptID, page, opts...) if err != nil { return nil, 0, err } @@ -77,7 +105,14 @@ func (e ExptInsightAnalysisRecordRepo) ListAnalysisRecord(ctx context.Context, s } func (e ExptInsightAnalysisRecordRepo) DeleteAnalysisRecord(ctx context.Context, spaceID, exptID, recordID int64) error { - return e.exptInsightAnalysisRecordDAO.Delete(ctx, spaceID, exptID, recordID) + if err := e.exptInsightAnalysisRecordDAO.Delete(ctx, spaceID, exptID, recordID); err != nil { + return err + } + if e.writeTracker != nil { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisRecord, recordID, + platestwrite.SetWithSearchParam(buildRecordSearchParam(spaceID, exptID))) + } + return nil } func (e ExptInsightAnalysisRecordRepo) CreateFeedbackComment(ctx context.Context, feedbackComment *entity.ExptInsightAnalysisFeedbackComment, opts ...db.Option) error { @@ -86,15 +121,33 @@ func (e ExptInsightAnalysisRecordRepo) CreateFeedbackComment(ctx context.Context return err } feedbackComment.ID = id - return e.exptInsightAnalysisFeedbackCommentDAO.Create(ctx, convert.ExptInsightAnalysisFeedbackCommentDOToPO(feedbackComment), opts...) + if err := e.exptInsightAnalysisFeedbackCommentDAO.Create(ctx, convert.ExptInsightAnalysisFeedbackCommentDOToPO(feedbackComment), opts...); err != nil { + return err + } + if e.writeTracker != nil { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, feedbackComment.AnalysisRecordID, + platestwrite.SetWithSearchParam(buildFeedbackSearchParam(feedbackComment.SpaceID, feedbackComment.ExptID, feedbackComment.AnalysisRecordID))) + } + return nil } func (e ExptInsightAnalysisRecordRepo) UpdateFeedbackComment(ctx context.Context, feedbackComment *entity.ExptInsightAnalysisFeedbackComment, opts ...db.Option) error { - return e.exptInsightAnalysisFeedbackCommentDAO.Update(ctx, convert.ExptInsightAnalysisFeedbackCommentDOToPO(feedbackComment), opts...) + if err := e.exptInsightAnalysisFeedbackCommentDAO.Update(ctx, convert.ExptInsightAnalysisFeedbackCommentDOToPO(feedbackComment), opts...); err != nil { + return err + } + if e.writeTracker != nil { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, feedbackComment.AnalysisRecordID, + platestwrite.SetWithSearchParam(buildFeedbackSearchParam(feedbackComment.SpaceID, feedbackComment.ExptID, feedbackComment.AnalysisRecordID))) + } + return nil } func (e ExptInsightAnalysisRecordRepo) GetFeedbackCommentByRecordID(ctx context.Context, spaceID, exptID, recordID int64, opts ...db.Option) (*entity.ExptInsightAnalysisFeedbackComment, error) { - po, err := e.exptInsightAnalysisFeedbackCommentDAO.GetByRecordID(ctx, spaceID, exptID, recordID, opts...) + innerOpts := append([]db.Option{}, opts...) + if e.needForceMasterByRecord(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, recordID, buildFeedbackSearchParam(spaceID, exptID, recordID)) && !db.ContainWithMasterOpt(innerOpts) { + innerOpts = append(innerOpts, db.WithMaster()) + } + po, err := e.exptInsightAnalysisFeedbackCommentDAO.GetByRecordID(ctx, spaceID, exptID, recordID, innerOpts...) if err != nil { return nil, err } @@ -102,7 +155,22 @@ func (e ExptInsightAnalysisRecordRepo) GetFeedbackCommentByRecordID(ctx context. } func (e ExptInsightAnalysisRecordRepo) DeleteFeedbackComment(ctx context.Context, spaceID, exptID, commentID int64) error { - return e.exptInsightAnalysisFeedbackCommentDAO.Delete(ctx, spaceID, exptID, commentID) + po, err := e.exptInsightAnalysisFeedbackCommentDAO.GetByID(ctx, spaceID, exptID, commentID, db.WithMaster()) + if err != nil { + return err + } + if err := e.exptInsightAnalysisFeedbackCommentDAO.Delete(ctx, spaceID, exptID, commentID); err != nil { + return err + } + recordID := int64(0) + if po.AnalysisRecordID != nil { + recordID = *po.AnalysisRecordID + } + if e.writeTracker != nil && recordID > 0 { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, recordID, + platestwrite.SetWithSearchParam(buildFeedbackSearchParam(po.SpaceID, po.ExptID, recordID))) + } + return nil } func (e ExptInsightAnalysisRecordRepo) CreateFeedbackVote(ctx context.Context, feedbackVote *entity.ExptInsightAnalysisFeedbackVote, opts ...db.Option) error { @@ -111,15 +179,33 @@ func (e ExptInsightAnalysisRecordRepo) CreateFeedbackVote(ctx context.Context, f return err } feedbackVote.ID = id - return e.exptInsightAnalysisFeedbackVoteDAO.Create(ctx, convert.ExptInsightAnalysisFeedbackVoteDOToPO(feedbackVote), opts...) + if err := e.exptInsightAnalysisFeedbackVoteDAO.Create(ctx, convert.ExptInsightAnalysisFeedbackVoteDOToPO(feedbackVote), opts...); err != nil { + return err + } + if e.writeTracker != nil { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, feedbackVote.AnalysisRecordID, + platestwrite.SetWithSearchParam(buildFeedbackSearchParam(feedbackVote.SpaceID, feedbackVote.ExptID, feedbackVote.AnalysisRecordID))) + } + return nil } func (e ExptInsightAnalysisRecordRepo) UpdateFeedbackVote(ctx context.Context, feedbackVote *entity.ExptInsightAnalysisFeedbackVote, opts ...db.Option) error { - return e.exptInsightAnalysisFeedbackVoteDAO.Update(ctx, convert.ExptInsightAnalysisFeedbackVoteDOToPO(feedbackVote), opts...) + if err := e.exptInsightAnalysisFeedbackVoteDAO.Update(ctx, convert.ExptInsightAnalysisFeedbackVoteDOToPO(feedbackVote), opts...); err != nil { + return err + } + if e.writeTracker != nil { + e.writeTracker.SetWriteFlag(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, feedbackVote.AnalysisRecordID, + platestwrite.SetWithSearchParam(buildFeedbackSearchParam(feedbackVote.SpaceID, feedbackVote.ExptID, feedbackVote.AnalysisRecordID))) + } + return nil } func (e ExptInsightAnalysisRecordRepo) GetFeedbackVoteByUser(ctx context.Context, spaceID, exptID, recordID int64, userID string, opts ...db.Option) (*entity.ExptInsightAnalysisFeedbackVote, error) { - po, err := e.exptInsightAnalysisFeedbackVoteDAO.GetByUser(ctx, spaceID, exptID, recordID, userID, opts...) + innerOpts := append([]db.Option{}, opts...) + if e.needForceMasterByRecord(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, recordID, buildFeedbackSearchParam(spaceID, exptID, recordID)) && !db.ContainWithMasterOpt(innerOpts) { + innerOpts = append(innerOpts, db.WithMaster()) + } + po, err := e.exptInsightAnalysisFeedbackVoteDAO.GetByUser(ctx, spaceID, exptID, recordID, userID, innerOpts...) if err != nil { return nil, err } @@ -127,11 +213,19 @@ func (e ExptInsightAnalysisRecordRepo) GetFeedbackVoteByUser(ctx context.Context } func (e ExptInsightAnalysisRecordRepo) CountFeedbackVote(ctx context.Context, spaceID, exptID, recordID int64) (int64, int64, error) { - return e.exptInsightAnalysisFeedbackVoteDAO.Count(ctx, spaceID, exptID, recordID) + opts := make([]db.Option, 0) + if e.needForceMasterByRecord(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, recordID, buildFeedbackSearchParam(spaceID, exptID, recordID)) { + opts = append(opts, db.WithMaster()) + } + return e.exptInsightAnalysisFeedbackVoteDAO.Count(ctx, spaceID, exptID, recordID, opts...) } func (e ExptInsightAnalysisRecordRepo) List(ctx context.Context, spaceID, exptID, recordID int64, page entity.Page) ([]*entity.ExptInsightAnalysisFeedbackComment, int64, error) { - pos, total, err := e.exptInsightAnalysisFeedbackCommentDAO.List(ctx, spaceID, exptID, recordID, page) + opts := make([]db.Option, 0) + if e.needForceMasterByRecord(ctx, platestwrite.ResourceTypeExptInsightAnalysisFeedback, recordID, buildFeedbackSearchParam(spaceID, exptID, recordID)) { + opts = append(opts, db.WithMaster()) + } + pos, total, err := e.exptInsightAnalysisFeedbackCommentDAO.List(ctx, spaceID, exptID, recordID, page, opts...) if err != nil { return nil, 0, err } @@ -141,3 +235,24 @@ func (e ExptInsightAnalysisRecordRepo) List(ctx context.Context, spaceID, exptID } return dos, total, nil } + +func (e ExptInsightAnalysisRecordRepo) needForceMasterByRecord(ctx context.Context, resourceType platestwrite.ResourceType, resourceID int64, searchParam string) bool { + if e.writeTracker == nil { + return false + } + if resourceID > 0 && e.writeTracker.CheckWriteFlagByID(ctx, resourceType, resourceID) { + return true + } + if searchParam != "" && e.writeTracker.CheckWriteFlagBySearchParam(ctx, resourceType, searchParam) { + return true + } + return false +} + +func buildRecordSearchParam(spaceID, exptID int64) string { + return fmt.Sprintf("%d:%d", spaceID, exptID) +} + +func buildFeedbackSearchParam(spaceID, exptID, recordID int64) string { + return fmt.Sprintf("%d:%d:%d", spaceID, exptID, recordID) +} diff --git a/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record_test.go b/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record_test.go index a8070373b..30a829500 100644 --- a/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record_test.go +++ b/backend/modules/evaluation/infra/repo/experiment/expt_insight_analysis_record_test.go @@ -11,7 +11,9 @@ import ( "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" + "github.com/coze-dev/coze-loop/backend/infra/db" mockidgen "github.com/coze-dev/coze-loop/backend/infra/idgen/mocks" + platestwritemocks "github.com/coze-dev/coze-loop/backend/infra/platestwrite/mocks" "github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/entity" "github.com/coze-dev/coze-loop/backend/modules/evaluation/infra/repo/experiment/mysql/gorm_gen/model" "github.com/coze-dev/coze-loop/backend/modules/evaluation/infra/repo/experiment/mysql/mocks" @@ -23,6 +25,7 @@ type testMocks struct { feedbackCommentDAO *mocks.MockIExptInsightAnalysisFeedbackCommentDAO feedbackVoteDAO *mocks.MockIExptInsightAnalysisFeedbackVoteDAO idGenerator *mockidgen.MockIIDGenerator + writeTracker *platestwritemocks.MockILatestWriteTracker } func newTestExptInsightAnalysisRecordRepo(ctrl *gomock.Controller) (*ExptInsightAnalysisRecordRepo, *testMocks) { @@ -31,6 +34,7 @@ func newTestExptInsightAnalysisRecordRepo(ctrl *gomock.Controller) (*ExptInsight feedbackCommentDAO: mocks.NewMockIExptInsightAnalysisFeedbackCommentDAO(ctrl), feedbackVoteDAO: mocks.NewMockIExptInsightAnalysisFeedbackVoteDAO(ctrl), idGenerator: mockidgen.NewMockIIDGenerator(ctrl), + writeTracker: platestwritemocks.NewMockILatestWriteTracker(ctrl), } repo := &ExptInsightAnalysisRecordRepo{ @@ -38,16 +42,29 @@ func newTestExptInsightAnalysisRecordRepo(ctrl *gomock.Controller) (*ExptInsight exptInsightAnalysisFeedbackCommentDAO: mocks.feedbackCommentDAO, exptInsightAnalysisFeedbackVoteDAO: mocks.feedbackVoteDAO, idgenerator: mocks.idGenerator, + writeTracker: mocks.writeTracker, } return repo, mocks } +func expectWriteFlagAny(m *testMocks) { + m.writeTracker.EXPECT().SetWriteFlag(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() +} + +func expectNoWriteFlagRead(m *testMocks) { + m.writeTracker.EXPECT().CheckWriteFlagByID(gomock.Any(), gomock.Any(), gomock.Any()).Return(false).AnyTimes() + m.writeTracker.EXPECT().CheckWriteFlagBySearchParam(gomock.Any(), gomock.Any(), gomock.Any()).Return(false).AnyTimes() +} + func TestExptInsightAnalysisRecordRepo_CreateAnalysisRecord(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) + expectWriteFlagAny(mocks) + expectWriteFlagAny(mocks) record := &entity.ExptInsightAnalysisRecord{ SpaceID: 1, @@ -72,6 +89,9 @@ func TestExptInsightAnalysisRecordRepo_UpdateAnalysisRecord(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) + expectWriteFlagAny(mocks) + expectWriteFlagAny(mocks) record := &entity.ExptInsightAnalysisRecord{ ID: 1, @@ -93,8 +113,9 @@ func TestExptInsightAnalysisRecordRepo_GetAnalysisRecordByID(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) - mocks.analysisRecordDAO.EXPECT().GetByID(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).Return(&model.ExptInsightAnalysisRecord{ + mocks.analysisRecordDAO.EXPECT().GetByID(gomock.Any(), int64(1), int64(1), int64(1)).Return(&model.ExptInsightAnalysisRecord{ ID: 1, SpaceID: 1, ExptID: 1, @@ -111,11 +132,34 @@ func TestExptInsightAnalysisRecordRepo_GetAnalysisRecordByID(t *testing.T) { assert.Equal(t, int64(1), record.ID) } +func TestExptInsightAnalysisRecordRepo_GetAnalysisRecordByID_ForceMaster(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + + mocks.writeTracker.EXPECT().CheckWriteFlagByID(gomock.Any(), gomock.Any(), int64(1)).Return(true) + mocks.writeTracker.EXPECT().CheckWriteFlagBySearchParam(gomock.Any(), gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mocks.analysisRecordDAO.EXPECT().GetByID(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).DoAndReturn( + func(_ context.Context, _ int64, _ int64, _ int64, opts ...db.Option) (*model.ExptInsightAnalysisRecord, error) { + assert.True(t, db.ContainWithMasterOpt(opts)) + return &model.ExptInsightAnalysisRecord{ID: 1, SpaceID: 1, ExptID: 1}, nil + }, + ) + + record, err := repo.GetAnalysisRecordByID(context.Background(), 1, 1, 1) + + assert.NoError(t, err) + assert.NotNil(t, record) + assert.Equal(t, int64(1), record.ID) +} + func TestExptInsightAnalysisRecordRepo_ListAnalysisRecord(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) mocks.analysisRecordDAO.EXPECT().List(gomock.Any(), int64(1), int64(1), entity.NewPage(1, 10)).Return([]*model.ExptInsightAnalysisRecord{ { @@ -140,6 +184,7 @@ func TestExptInsightAnalysisRecordRepo_DeleteAnalysisRecord(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) mocks.analysisRecordDAO.EXPECT().Delete(gomock.Any(), int64(1), int64(1), int64(1)).Return(nil) @@ -153,6 +198,7 @@ func TestExptInsightAnalysisRecordRepo_CreateFeedbackComment(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) comment := &entity.ExptInsightAnalysisFeedbackComment{ SpaceID: 1, @@ -176,6 +222,7 @@ func TestExptInsightAnalysisRecordRepo_UpdateFeedbackComment(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) comment := &entity.ExptInsightAnalysisFeedbackComment{ ID: 1, @@ -197,7 +244,14 @@ func TestExptInsightAnalysisRecordRepo_DeleteFeedbackComment(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) + mocks.feedbackCommentDAO.EXPECT().GetByID(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).Return(&model.ExptInsightAnalysisFeedbackComment{ + ID: 1, + SpaceID: 1, + ExptID: 1, + AnalysisRecordID: ptr.Of(int64(1)), + }, nil) mocks.feedbackCommentDAO.EXPECT().Delete(gomock.Any(), int64(1), int64(1), int64(1)).Return(nil) err := repo.DeleteFeedbackComment(context.Background(), 1, 1, 1) @@ -205,11 +259,26 @@ func TestExptInsightAnalysisRecordRepo_DeleteFeedbackComment(t *testing.T) { assert.NoError(t, err) } +func TestExptInsightAnalysisRecordRepo_DeleteFeedbackComment_GetByIDError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) + + mocks.feedbackCommentDAO.EXPECT().GetByID(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).Return(nil, assert.AnError) + + err := repo.DeleteFeedbackComment(context.Background(), 1, 1, 1) + + assert.Error(t, err) +} + func TestExptInsightAnalysisRecordRepo_CreateFeedbackVote(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) vote := &entity.ExptInsightAnalysisFeedbackVote{ SpaceID: 1, @@ -233,6 +302,7 @@ func TestExptInsightAnalysisRecordRepo_UpdateFeedbackVote(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectWriteFlagAny(mocks) vote := &entity.ExptInsightAnalysisFeedbackVote{ ID: 1, @@ -254,8 +324,9 @@ func TestExptInsightAnalysisRecordRepo_GetFeedbackVoteByUser(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) - mocks.feedbackVoteDAO.EXPECT().GetByUser(gomock.Any(), int64(1), int64(1), int64(1), "user123", gomock.Any()).Return(&model.ExptInsightAnalysisFeedbackVote{ + mocks.feedbackVoteDAO.EXPECT().GetByUser(gomock.Any(), int64(1), int64(1), int64(1), "user123").Return(&model.ExptInsightAnalysisFeedbackVote{ ID: 1, SpaceID: 1, ExptID: 1, @@ -278,6 +349,7 @@ func TestExptInsightAnalysisRecordRepo_CountFeedbackVote(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) mocks.feedbackVoteDAO.EXPECT().Count(gomock.Any(), int64(1), int64(1), int64(1)).Return(int64(3), int64(2), nil) @@ -288,11 +360,34 @@ func TestExptInsightAnalysisRecordRepo_CountFeedbackVote(t *testing.T) { assert.Equal(t, int64(2), downVoteCount) } +func TestExptInsightAnalysisRecordRepo_CountFeedbackVote_ForceMaster(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + + mocks.writeTracker.EXPECT().CheckWriteFlagByID(gomock.Any(), gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mocks.writeTracker.EXPECT().CheckWriteFlagBySearchParam(gomock.Any(), gomock.Any(), gomock.Any()).Return(true) + mocks.feedbackVoteDAO.EXPECT().Count(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).DoAndReturn( + func(_ context.Context, _ int64, _ int64, _ int64, opts ...db.Option) (int64, int64, error) { + assert.True(t, db.ContainWithMasterOpt(opts)) + return 3, 2, nil + }, + ) + + upVoteCount, downVoteCount, err := repo.CountFeedbackVote(context.Background(), 1, 1, 1) + + assert.NoError(t, err) + assert.Equal(t, int64(3), upVoteCount) + assert.Equal(t, int64(2), downVoteCount) +} + func TestExptInsightAnalysisRecordRepo_List(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) mocks.feedbackCommentDAO.EXPECT().List(gomock.Any(), int64(1), int64(1), int64(1), entity.NewPage(1, 10)).Return([]*model.ExptInsightAnalysisFeedbackComment{ { @@ -411,8 +506,9 @@ func TestExptInsightAnalysisRecordRepo_GetFeedbackCommentByRecordID(t *testing.T defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) - mocks.feedbackCommentDAO.EXPECT().GetByRecordID(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).Return(&model.ExptInsightAnalysisFeedbackComment{ + mocks.feedbackCommentDAO.EXPECT().GetByRecordID(gomock.Any(), int64(1), int64(1), int64(1)).Return(&model.ExptInsightAnalysisFeedbackComment{ ID: 1, SpaceID: 1, ExptID: 1, @@ -430,13 +526,36 @@ func TestExptInsightAnalysisRecordRepo_GetFeedbackCommentByRecordID(t *testing.T assert.Equal(t, int64(1), comment.ID) } +func TestExptInsightAnalysisRecordRepo_GetFeedbackCommentByRecordID_ForceMaster(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + + mocks.writeTracker.EXPECT().CheckWriteFlagByID(gomock.Any(), gomock.Any(), int64(1)).Return(true) + mocks.writeTracker.EXPECT().CheckWriteFlagBySearchParam(gomock.Any(), gomock.Any(), gomock.Any()).Return(false).AnyTimes() + mocks.feedbackCommentDAO.EXPECT().GetByRecordID(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).DoAndReturn( + func(_ context.Context, _ int64, _ int64, _ int64, opts ...db.Option) (*model.ExptInsightAnalysisFeedbackComment, error) { + assert.True(t, db.ContainWithMasterOpt(opts)) + return &model.ExptInsightAnalysisFeedbackComment{ID: 1, SpaceID: 1, ExptID: 1, AnalysisRecordID: ptr.Of(int64(1))}, nil + }, + ) + + comment, err := repo.GetFeedbackCommentByRecordID(context.Background(), 1, 1, 1) + + assert.NoError(t, err) + assert.NotNil(t, comment) + assert.Equal(t, int64(1), comment.ID) +} + func TestExptInsightAnalysisRecordRepo_GetFeedbackCommentByRecordID_Error(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) - mocks.feedbackCommentDAO.EXPECT().GetByRecordID(gomock.Any(), int64(1), int64(1), int64(1), gomock.Any()).Return(nil, assert.AnError) + mocks.feedbackCommentDAO.EXPECT().GetByRecordID(gomock.Any(), int64(1), int64(1), int64(1)).Return(nil, assert.AnError) comment, err := repo.GetFeedbackCommentByRecordID(context.Background(), 1, 1, 1) @@ -449,8 +568,9 @@ func TestExptInsightAnalysisRecordRepo_GetFeedbackVoteByUser_Error(t *testing.T) defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) - mocks.feedbackVoteDAO.EXPECT().GetByUser(gomock.Any(), int64(1), int64(1), int64(1), "user123", gomock.Any()).Return(nil, assert.AnError) + mocks.feedbackVoteDAO.EXPECT().GetByUser(gomock.Any(), int64(1), int64(1), int64(1), "user123").Return(nil, assert.AnError) vote, err := repo.GetFeedbackVoteByUser(context.Background(), 1, 1, 1, "user123") @@ -463,6 +583,7 @@ func TestExptInsightAnalysisRecordRepo_List_Error(t *testing.T) { defer ctrl.Finish() repo, mocks := newTestExptInsightAnalysisRecordRepo(ctrl) + expectNoWriteFlagRead(mocks) mocks.feedbackCommentDAO.EXPECT().List(gomock.Any(), int64(1), int64(1), int64(1), entity.NewPage(1, 10)).Return(nil, int64(0), assert.AnError) diff --git a/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_comment.go b/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_comment.go index 33944ba43..b495b1e7a 100644 --- a/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_comment.go +++ b/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_comment.go @@ -19,8 +19,9 @@ type IExptInsightAnalysisFeedbackCommentDAO interface { Create(ctx context.Context, feedbackComment *model.ExptInsightAnalysisFeedbackComment, opts ...db.Option) error Update(ctx context.Context, feedbackComment *model.ExptInsightAnalysisFeedbackComment, opts ...db.Option) error GetByRecordID(ctx context.Context, spaceID, exptID, recordID int64, opts ...db.Option) (*model.ExptInsightAnalysisFeedbackComment, error) + GetByID(ctx context.Context, spaceID, exptID, commentID int64, opts ...db.Option) (*model.ExptInsightAnalysisFeedbackComment, error) Delete(ctx context.Context, spaceID, exptID, commentID int64) error - List(ctx context.Context, spaceID, exptID, recordID int64, page entity.Page) ([]*model.ExptInsightAnalysisFeedbackComment, int64, error) + List(ctx context.Context, spaceID, exptID, recordID int64, page entity.Page, opts ...db.Option) ([]*model.ExptInsightAnalysisFeedbackComment, int64, error) } func NewExptInsightAnalysisFeedbackCommentDAO(db db.Provider) IExptInsightAnalysisFeedbackCommentDAO { @@ -50,7 +51,7 @@ func (e exptInsightAnalysisFeedbackCommentDAO) Update(ctx context.Context, feedb } func (e exptInsightAnalysisFeedbackCommentDAO) GetByRecordID(ctx context.Context, spaceID, exptID, recordID int64, opts ...db.Option) (*model.ExptInsightAnalysisFeedbackComment, error) { - db := e.db.NewSession(ctx) + db := e.db.NewSession(ctx, opts...) q := query.Use(db).ExptInsightAnalysisFeedbackComment feedbackVote, err := q.WithContext(ctx).Where( @@ -65,6 +66,22 @@ func (e exptInsightAnalysisFeedbackCommentDAO) GetByRecordID(ctx context.Context return feedbackVote, nil } +func (e exptInsightAnalysisFeedbackCommentDAO) GetByID(ctx context.Context, spaceID, exptID, commentID int64, opts ...db.Option) (*model.ExptInsightAnalysisFeedbackComment, error) { + db := e.db.NewSession(ctx, opts...) + q := query.Use(db).ExptInsightAnalysisFeedbackComment + + comment, err := q.WithContext(ctx).Where( + q.SpaceID.Eq(spaceID), + q.ExptID.Eq(exptID), + q.ID.Eq(commentID), + ).First() + if err != nil { + return nil, errorx.Wrapf(err, "exptInsightAnalysisFeedbackCommentDAO GetByID fail, commentID: %v", commentID) + } + + return comment, nil +} + func (e exptInsightAnalysisFeedbackCommentDAO) Delete(ctx context.Context, spaceID, exptID, commentID int64) error { po := &model.ExptInsightAnalysisFeedbackComment{} db := e.db.NewSession(ctx) @@ -77,12 +94,12 @@ func (e exptInsightAnalysisFeedbackCommentDAO) Delete(ctx context.Context, space return nil } -func (e exptInsightAnalysisFeedbackCommentDAO) List(ctx context.Context, spaceID, exptID, recordID int64, page entity.Page) ([]*model.ExptInsightAnalysisFeedbackComment, int64, error) { +func (e exptInsightAnalysisFeedbackCommentDAO) List(ctx context.Context, spaceID, exptID, recordID int64, page entity.Page, opts ...db.Option) ([]*model.ExptInsightAnalysisFeedbackComment, int64, error) { var ( finds []*model.ExptInsightAnalysisFeedbackComment total int64 ) - db := e.db.NewSession(ctx).Model(&model.ExptInsightAnalysisFeedbackComment{}). + db := e.db.NewSession(ctx, opts...).Model(&model.ExptInsightAnalysisFeedbackComment{}). Where("space_id =?", spaceID). Where("expt_id =?", exptID). Where("analysis_record_id =?", recordID).Order("created_at DESC") diff --git a/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_vote.go b/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_vote.go index a22fcd40e..799b3073b 100644 --- a/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_vote.go +++ b/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_feedback_vote.go @@ -23,7 +23,7 @@ type IExptInsightAnalysisFeedbackVoteDAO interface { Create(ctx context.Context, feedbackVote *model.ExptInsightAnalysisFeedbackVote, opts ...db.Option) error Update(ctx context.Context, feedbackVote *model.ExptInsightAnalysisFeedbackVote, opts ...db.Option) error GetByUser(ctx context.Context, spaceID, exptID, recordID int64, userID string, opts ...db.Option) (*model.ExptInsightAnalysisFeedbackVote, error) - Count(ctx context.Context, spaceID, exptID, recordID int64) (int64, int64, error) + Count(ctx context.Context, spaceID, exptID, recordID int64, opts ...db.Option) (int64, int64, error) } func NewExptInsightAnalysisFeedbackVoteDAO(db db.Provider) IExptInsightAnalysisFeedbackVoteDAO { @@ -59,7 +59,7 @@ func (e exptInsightAnalysisFeedbackVoteDAO) Update(ctx context.Context, feedback } func (e exptInsightAnalysisFeedbackVoteDAO) GetByUser(ctx context.Context, spaceID, exptID, recordID int64, userID string, opts ...db.Option) (*model.ExptInsightAnalysisFeedbackVote, error) { - db := e.db.NewSession(ctx) + db := e.db.NewSession(ctx, opts...) q := query.Use(db).ExptInsightAnalysisFeedbackVote feedbackVote, err := q.WithContext(ctx).Where( @@ -78,8 +78,8 @@ func (e exptInsightAnalysisFeedbackVoteDAO) GetByUser(ctx context.Context, space return feedbackVote, nil } -func (e exptInsightAnalysisFeedbackVoteDAO) Count(ctx context.Context, spaceID, exptID, recordID int64) (int64, int64, error) { - db := e.db.NewSession(ctx) +func (e exptInsightAnalysisFeedbackVoteDAO) Count(ctx context.Context, spaceID, exptID, recordID int64, opts ...db.Option) (int64, int64, error) { + db := e.db.NewSession(ctx, opts...) type VoteStatistic struct { UpvoteCount int64 `json:"upvote_count"` DownvoteCount int64 `json:"downvote_count"` diff --git a/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_record.go b/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_record.go index a19161106..7cf1e4714 100644 --- a/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_record.go +++ b/backend/modules/evaluation/infra/repo/experiment/mysql/expt_insight_analysis_record.go @@ -19,7 +19,7 @@ type IExptInsightAnalysisRecordDAO interface { Create(ctx context.Context, record *model.ExptInsightAnalysisRecord, opts ...db.Option) error Update(ctx context.Context, record *model.ExptInsightAnalysisRecord, opts ...db.Option) error GetByID(ctx context.Context, spaceID, exptID, recordID int64, opts ...db.Option) (*model.ExptInsightAnalysisRecord, error) - List(ctx context.Context, spaceID, exptID int64, page entity.Page) ([]*model.ExptInsightAnalysisRecord, int64, error) + List(ctx context.Context, spaceID, exptID int64, page entity.Page, opts ...db.Option) ([]*model.ExptInsightAnalysisRecord, int64, error) Delete(ctx context.Context, spaceID, exptID, recordID int64) error } @@ -50,7 +50,7 @@ func (e exptInsightAnalysisRecordDAO) Update(ctx context.Context, record *model. } func (e exptInsightAnalysisRecordDAO) GetByID(ctx context.Context, spaceID, exptID, recordID int64, opts ...db.Option) (*model.ExptInsightAnalysisRecord, error) { - db := e.db.NewSession(ctx) + db := e.db.NewSession(ctx, opts...) q := query.Use(db).ExptInsightAnalysisRecord record, err := q.WithContext(ctx).Where( @@ -65,13 +65,13 @@ func (e exptInsightAnalysisRecordDAO) GetByID(ctx context.Context, spaceID, expt return record, nil } -func (e exptInsightAnalysisRecordDAO) List(ctx context.Context, spaceID, exptID int64, page entity.Page) ([]*model.ExptInsightAnalysisRecord, int64, error) { +func (e exptInsightAnalysisRecordDAO) List(ctx context.Context, spaceID, exptID int64, page entity.Page, opts ...db.Option) ([]*model.ExptInsightAnalysisRecord, int64, error) { var ( finds []*model.ExptInsightAnalysisRecord total int64 ) - db := e.db.NewSession(ctx).Model(&model.ExptInsightAnalysisRecord{}).Where("space_id = ?", spaceID).Where("expt_id = ?", exptID) + db := e.db.NewSession(ctx, opts...).Model(&model.ExptInsightAnalysisRecord{}).Where("space_id = ?", spaceID).Where("expt_id = ?", exptID) db = db.Order("created_at desc") // 总记录数 diff --git a/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_comment.go b/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_comment.go index faee0a332..187b29441 100644 --- a/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_comment.go +++ b/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_comment.go @@ -90,10 +90,34 @@ func (mr *MockIExptInsightAnalysisFeedbackCommentDAOMockRecorder) GetByRecordID( return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByRecordID", reflect.TypeOf((*MockIExptInsightAnalysisFeedbackCommentDAO)(nil).GetByRecordID), varargs...) } +// GetByID mocks base method. +func (m *MockIExptInsightAnalysisFeedbackCommentDAO) GetByID(arg0 context.Context, arg1, arg2, arg3 int64, arg4 ...db.Option) (*model.ExptInsightAnalysisFeedbackComment, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1, arg2, arg3} + for _, a := range arg4 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "GetByID", varargs...) + ret0, _ := ret[0].(*model.ExptInsightAnalysisFeedbackComment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetByID indicates an expected call of GetByID. +func (mr *MockIExptInsightAnalysisFeedbackCommentDAOMockRecorder) GetByID(arg0, arg1, arg2, arg3 interface{}, arg4 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1, arg2, arg3}, arg4...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockIExptInsightAnalysisFeedbackCommentDAO)(nil).GetByID), varargs...) +} + // List mocks base method. -func (m *MockIExptInsightAnalysisFeedbackCommentDAO) List(arg0 context.Context, arg1, arg2, arg3 int64, arg4 entity.Page) ([]*model.ExptInsightAnalysisFeedbackComment, int64, error) { +func (m *MockIExptInsightAnalysisFeedbackCommentDAO) List(arg0 context.Context, arg1, arg2, arg3 int64, arg4 entity.Page, arg5 ...db.Option) ([]*model.ExptInsightAnalysisFeedbackComment, int64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", arg0, arg1, arg2, arg3, arg4) + varargs := []interface{}{arg0, arg1, arg2, arg3, arg4} + for _, a := range arg5 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "List", varargs...) ret0, _ := ret[0].([]*model.ExptInsightAnalysisFeedbackComment) ret1, _ := ret[1].(int64) ret2, _ := ret[2].(error) @@ -101,9 +125,10 @@ func (m *MockIExptInsightAnalysisFeedbackCommentDAO) List(arg0 context.Context, } // List indicates an expected call of List. -func (mr *MockIExptInsightAnalysisFeedbackCommentDAOMockRecorder) List(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockIExptInsightAnalysisFeedbackCommentDAOMockRecorder) List(arg0, arg1, arg2, arg3, arg4 interface{}, arg5 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockIExptInsightAnalysisFeedbackCommentDAO)(nil).List), arg0, arg1, arg2, arg3, arg4) + varargs := append([]interface{}{arg0, arg1, arg2, arg3, arg4}, arg5...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockIExptInsightAnalysisFeedbackCommentDAO)(nil).List), varargs...) } // Update mocks base method. diff --git a/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_vote.go b/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_vote.go index addd54589..2c12c6390 100644 --- a/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_vote.go +++ b/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_feedback_vote.go @@ -37,9 +37,13 @@ func (m *MockIExptInsightAnalysisFeedbackVoteDAO) EXPECT() *MockIExptInsightAnal } // Count mocks base method. -func (m *MockIExptInsightAnalysisFeedbackVoteDAO) Count(arg0 context.Context, arg1, arg2, arg3 int64) (int64, int64, error) { +func (m *MockIExptInsightAnalysisFeedbackVoteDAO) Count(arg0 context.Context, arg1, arg2, arg3 int64, arg4 ...db.Option) (int64, int64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Count", arg0, arg1, arg2, arg3) + varargs := []interface{}{arg0, arg1, arg2, arg3} + for _, a := range arg4 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Count", varargs...) ret0, _ := ret[0].(int64) ret1, _ := ret[1].(int64) ret2, _ := ret[2].(error) @@ -47,9 +51,10 @@ func (m *MockIExptInsightAnalysisFeedbackVoteDAO) Count(arg0 context.Context, ar } // Count indicates an expected call of Count. -func (mr *MockIExptInsightAnalysisFeedbackVoteDAOMockRecorder) Count(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockIExptInsightAnalysisFeedbackVoteDAOMockRecorder) Count(arg0, arg1, arg2, arg3 interface{}, arg4 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Count", reflect.TypeOf((*MockIExptInsightAnalysisFeedbackVoteDAO)(nil).Count), arg0, arg1, arg2, arg3) + varargs := append([]interface{}{arg0, arg1, arg2, arg3}, arg4...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Count", reflect.TypeOf((*MockIExptInsightAnalysisFeedbackVoteDAO)(nil).Count), varargs...) } // Create mocks base method. diff --git a/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_record.go b/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_record.go index ccffbe7fc..d27da1fab 100644 --- a/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_record.go +++ b/backend/modules/evaluation/infra/repo/experiment/mysql/mocks/expt_insight_analysis_record.go @@ -91,9 +91,13 @@ func (mr *MockIExptInsightAnalysisRecordDAOMockRecorder) GetByID(arg0, arg1, arg } // List mocks base method. -func (m *MockIExptInsightAnalysisRecordDAO) List(arg0 context.Context, arg1, arg2 int64, arg3 entity.Page) ([]*model.ExptInsightAnalysisRecord, int64, error) { +func (m *MockIExptInsightAnalysisRecordDAO) List(arg0 context.Context, arg1, arg2 int64, arg3 entity.Page, arg4 ...db.Option) ([]*model.ExptInsightAnalysisRecord, int64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", arg0, arg1, arg2, arg3) + varargs := []interface{}{arg0, arg1, arg2, arg3} + for _, a := range arg4 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "List", varargs...) ret0, _ := ret[0].([]*model.ExptInsightAnalysisRecord) ret1, _ := ret[1].(int64) ret2, _ := ret[2].(error) @@ -101,9 +105,10 @@ func (m *MockIExptInsightAnalysisRecordDAO) List(arg0 context.Context, arg1, arg } // List indicates an expected call of List. -func (mr *MockIExptInsightAnalysisRecordDAOMockRecorder) List(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockIExptInsightAnalysisRecordDAOMockRecorder) List(arg0, arg1, arg2, arg3 interface{}, arg4 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockIExptInsightAnalysisRecordDAO)(nil).List), arg0, arg1, arg2, arg3) + varargs := append([]interface{}{arg0, arg1, arg2, arg3}, arg4...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockIExptInsightAnalysisRecordDAO)(nil).List), varargs...) } // Update mocks base method. diff --git a/backend/modules/evaluation/infra/rpc/agent/agent.go b/backend/modules/evaluation/infra/rpc/agent/agent.go index c5b9e529f..bea8d450e 100644 --- a/backend/modules/evaluation/infra/rpc/agent/agent.go +++ b/backend/modules/evaluation/infra/rpc/agent/agent.go @@ -18,7 +18,7 @@ func NewAgentAdapter() rpc.IAgentAdapter { return &AgentAdapter{} } -func (a AgentAdapter) CallTraceAgent(ctx context.Context, spaceID int64, url string) (int64, error) { +func (a AgentAdapter) CallTraceAgent(ctx context.Context, spaceID int64, url string, startTime, endTime int64) (int64, error) { return 0, errorx.NewByCode(errno.CommonInternalErrorCode, errorx.WithExtraMsg("CallTraceAgent not implement")) } diff --git a/backend/modules/evaluation/infra/rpc/agent/agent_test.go b/backend/modules/evaluation/infra/rpc/agent/agent_test.go index 295820750..eaa88f63c 100644 --- a/backend/modules/evaluation/infra/rpc/agent/agent_test.go +++ b/backend/modules/evaluation/infra/rpc/agent/agent_test.go @@ -34,7 +34,7 @@ func TestAgentAdapter_CallTraceAgent(t *testing.T) { ctx := context.Background() adapter, ctx := tt.setup(ctx) - result, err := adapter.CallTraceAgent(ctx, 123, "http://example.com") + result, err := adapter.CallTraceAgent(ctx, 123, "http://example.com", 0, 0) if tt.wantErr { assert.Error(t, err)