Fix declared server config file reads

This commit is contained in:
npc0-hue
2026-09-21 10:05:50 +08:00
parent b481b1b798
commit 20008b4043
16 changed files with 166 additions and 33 deletions
+54 -9
View File
@@ -2114,6 +2114,7 @@ func (svc *CoreService) GetDeclaredFileReadSnapshotForSession(sessionID string,
}
var completed *domain.Job
var pending *domain.Job
var terminalFailure *domain.Job
for i := range jobs {
job := jobs[i]
if job.Capability != domain.JobCapabilityFilesRead || job.TargetKey != fileKey {
@@ -2129,6 +2130,11 @@ func (svc *CoreService) GetDeclaredFileReadSnapshotForSession(sessionID string,
if declaredFileReadPendingState(job.State) && (pending == nil || newerJob(job, *pending)) {
copy := job
pending = &copy
continue
}
if (job.State == domain.JobStateFailed || job.State == domain.JobStateCancelled) && (terminalFailure == nil || newerJob(job, *terminalFailure)) {
copy := job
terminalFailure = &copy
}
}
base := domain.DeclaredFileReadSnapshot{ServerInstanceID: instance.ID, PluginID: plugin.ID, Key: fileKey}
@@ -2152,6 +2158,16 @@ func (svc *CoreService) GetDeclaredFileReadSnapshotForSession(sessionID string,
base.Reason = "等待运行端完成文件读取。"
return base, nil
}
if terminalFailure != nil {
base.State = "failed"
if terminalFailure.State == domain.JobStateCancelled {
base.State = "cancelled"
}
base.JobID = terminalFailure.ID
base.ReadAt = jobCompletedAt(*terminalFailure)
base.Reason = declaredFileReadFailureReason(*terminalFailure)
return base, nil
}
base.State = "not-read"
base.Reason = "尚未读取此文件。"
return base, nil
@@ -2166,6 +2182,24 @@ func declaredFileReadPendingState(state domain.JobState) bool {
}
}
func declaredFileReadFailureReason(job domain.Job) string {
prefix := "Run 文件读取失败"
if job.State == domain.JobStateCancelled {
prefix = "Run 文件读取已取消"
}
detail := strings.TrimSpace(job.CancelReason)
if detail == "" {
detail = strings.TrimSpace(job.Progress.Message)
}
if detail == "" {
detail = strings.TrimSpace(job.ExecutionResult.Summary)
}
if detail == "" {
return prefix + "。"
}
return prefix + "" + detail
}
func newerJob(left domain.Job, right domain.Job) bool {
leftTime, rightTime := jobCompletedAt(left), jobCompletedAt(right)
if !leftTime.Equal(rightTime) {
@@ -2293,14 +2327,18 @@ func (svc *CoreService) DispatchFileOperationForSession(sessionID string, reques
return domain.FileOperationDispatchResult{}, ErrForbidden
}
}
pluginID := strings.TrimSpace(request.PluginID)
if pluginID == "" {
pluginID = instance.PluginID
}
plugin, err := svc.store.GamePlugins().Get(pluginID)
if err != nil {
return domain.FileOperationDispatchResult{}, err
}
if plugin.ID != instance.PluginID {
return domain.FileOperationDispatchResult{}, validationError("pluginId must match server instance")
}
if request.PluginID != "" {
plugin, err := svc.store.GamePlugins().Get(request.PluginID)
if err != nil {
return domain.FileOperationDispatchResult{}, err
}
if plugin.ID != instance.PluginID {
return domain.FileOperationDispatchResult{}, validationError("pluginId must match server instance")
}
if plugin.Status != domain.GamePluginStatusInstalled {
return domain.FileOperationDispatchResult{}, validationError("plugin must be installed")
}
@@ -2311,6 +2349,13 @@ func (svc *CoreService) DispatchFileOperationForSession(sessionID string, reques
return domain.FileOperationDispatchResult{}, ErrForbidden
}
}
fileTargetKey := ""
if request.Operation != domain.FileOperationList {
file, declared, allowed := declaredPluginFileRequest(plugin.FileWorkspace, request)
if declared && allowed {
fileTargetKey = file.TargetKey
}
}
capability := domain.JobCapabilityFilesRead
message := "file read queued"
if request.Operation == domain.FileOperationList {
@@ -2328,7 +2373,7 @@ func (svc *CoreService) DispatchFileOperationForSession(sessionID string, reques
Capability: capability,
TargetKey: request.Key,
InputRef: request.InputRef,
ExecutionInput: domain.JobExecutionInput{WorkspaceScope: svc.runtimeProfileScope(instance.ID), Content: content, ExpectedVersion: request.ExpectedConfigVersion, ExpectedChecksum: request.ExpectedChecksum, MaxReadBytes: 64 * 1024, Deployment: deploymentPlanForDispatch(instance.Deployment)},
ExecutionInput: domain.JobExecutionInput{WorkspaceScope: svc.runtimeProfileScope(instance.ID), Content: content, FileTargetKey: fileTargetKey, ExpectedVersion: request.ExpectedConfigVersion, ExpectedChecksum: request.ExpectedChecksum, MaxReadBytes: 64 * 1024, PluginID: plugin.ID, Deployment: deploymentPlanForDispatch(instance.Deployment)},
IdempotencyKey: request.IdempotencyKey,
Progress: domain.JobProgress{Percent: 0, Message: message},
})
@@ -2337,7 +2382,7 @@ func (svc *CoreService) DispatchFileOperationForSession(sessionID string, reques
}
return domain.CopyFileOperationDispatchResult(domain.FileOperationDispatchResult{
ServerInstanceID: request.ServerInstanceID,
PluginID: request.PluginID,
PluginID: plugin.ID,
Operation: request.Operation,
Key: request.Key,
InputRef: request.InputRef,