Fix server file root loading and refresh
This commit is contained in:
@@ -151,7 +151,6 @@ func TestMetricsAndConfigReadAPIAreSafeAndRoleScoped(t *testing.T) {
|
||||
|
||||
postJSON[dto.GamePluginResponse](t, router, "/api/v1/game-plugins", validGamePluginRequest())
|
||||
endpointRequest := validRunEndpointRequest()
|
||||
endpointRequest.Capabilities = append(endpointRequest.Capabilities, domain.JobCapabilityFilesList)
|
||||
postJSON[dto.RunEndpointResponse](t, router, "/api/v1/run/endpoints", endpointRequest)
|
||||
instance := postJSONWithAuth[dto.ServerInstanceResponse](t, router, "/api/v1/server-instances", dto.ServerInstanceCreateRequest{
|
||||
ID: "server-metrics-api",
|
||||
@@ -267,6 +266,12 @@ func TestCoreAPIServerFileWorkspaceRoutesAreScoped(t *testing.T) {
|
||||
if list.State != "declared" || list.DirectoryKey != "server-root" || list.Entries == nil || !strings.Contains(list.Reason, "服务器文件缓存") {
|
||||
t.Fatalf("expected generic root file list, got %+v", list)
|
||||
}
|
||||
refreshRecorder := requestJSONWithAuth(t, router, http.MethodPost, "/api/v1/server-instances/"+instance.ID+"/files/refresh", dto.ServerFileListRequest{DirectoryKey: "server-root", IdempotencyKey: "api-file-list-refresh"}, adminSession)
|
||||
assertStatus(t, refreshRecorder, http.StatusAccepted)
|
||||
refresh := decodeBody[dto.ServerFileListResponse](t, refreshRecorder)
|
||||
if refresh.State != "pending" || refresh.Job == nil || refresh.Job.Capability != domain.JobCapabilityFilesList {
|
||||
t.Fatalf("expected file list refresh without endpoint declaration gate, got %+v", refresh)
|
||||
}
|
||||
readRecorder := requestJSONWithAuth(t, router, http.MethodPost, "/api/v1/server-instances/"+instance.ID+"/files/read", dto.ServerFileReadRequest{PluginID: "server.scum", Key: "scum-server-settings", IdempotencyKey: "api-file-read"}, adminSession)
|
||||
assertStatus(t, readRecorder, http.StatusAccepted)
|
||||
read := decodeBody[dto.FileOperationDispatchResponse](t, readRecorder)
|
||||
|
||||
@@ -43,9 +43,6 @@ func (svc *CoreService) ClaimRunJob(claim domain.RunJobClaim) (domain.RunJobClai
|
||||
if claim.Capacity.MaxJobs > 0 && claim.Capacity.RunningJobs >= claim.Capacity.MaxJobs {
|
||||
return emptyJobClaim(claim.RunEndpointID, stamp), nil
|
||||
}
|
||||
if session.RequireSignedRequests && len(claim.Capabilities) == 0 {
|
||||
return emptyJobClaim(claim.RunEndpointID, stamp), nil
|
||||
}
|
||||
jobs, err := svc.store.Jobs().List(domain.JobFilter{RunEndpointID: claim.RunEndpointID})
|
||||
if err != nil {
|
||||
return domain.RunJobClaimResult{}, err
|
||||
@@ -614,7 +611,7 @@ func firstEligibleSupportedJob(jobs []domain.Job, capabilities []string, stamp t
|
||||
if !eligible || !job.CancelRequestedAt.IsZero() {
|
||||
continue
|
||||
}
|
||||
if len(capabilitySet) > 0 {
|
||||
if len(capabilitySet) > 0 && !isServerFileCapability(job.Capability) {
|
||||
if _, supported := capabilitySet[job.Capability]; !supported {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -2754,6 +2754,9 @@ func (svc *CoreService) validateRunnableEndpoint(endpoint domain.RunEndpoint, ca
|
||||
if !svc.runEndpointHeartbeatCurrent(endpoint) {
|
||||
return validationError("run endpoint heartbeat is stale")
|
||||
}
|
||||
if isServerFileCapability(capability) {
|
||||
return nil
|
||||
}
|
||||
if len(validator.MissingCapabilities(endpoint.Capabilities, []string{capability})) > 0 {
|
||||
return validationError("run endpoint missing required capability: " + capability)
|
||||
}
|
||||
@@ -2782,7 +2785,7 @@ func validateJobServerTarget(job domain.Job, instance domain.ServerInstance, plu
|
||||
if plugin.ID != instance.PluginID {
|
||||
return validationError("job plugin must match server instance")
|
||||
}
|
||||
if job.Capability != domain.JobCapabilityDistributionBuild && !containsString(plugin.RequiredRunCapabilities, job.Capability) {
|
||||
if job.Capability != domain.JobCapabilityDistributionBuild && !isServerFileCapability(job.Capability) && !containsString(plugin.RequiredRunCapabilities, job.Capability) {
|
||||
return validationError("plugin missing required capability: " + job.Capability)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -101,14 +101,14 @@ func (svc *CoreService) ListServerFilesForSession(sessionID string, request doma
|
||||
}
|
||||
}
|
||||
state := "declared"
|
||||
reason := "展示服务器文件缓存;点击刷新目录读取 Run 实时目录。"
|
||||
reason := "展示服务器文件缓存;打开文件标签时会自动读取 Run 实时目录。"
|
||||
if hasLatest && !isTerminalJobState(latest.State) {
|
||||
state = "pending"
|
||||
reason = "Run 正在刷新目录。"
|
||||
}
|
||||
entries := filterServerFileEntries(serverFileEntriesFromDeclaredWorkspace(ctx.Workspace, request.DirectoryKey), request.Query)
|
||||
if state == "declared" {
|
||||
reason = "展示服务器文件缓存;点击刷新目录读取 Run 实时目录。"
|
||||
reason = "展示服务器文件缓存;打开文件标签时会自动读取 Run 实时目录。"
|
||||
}
|
||||
return domain.CopyServerFileListResult(domain.ServerFileListResult{ServerInstanceID: ctx.Instance.ID, PluginID: ctx.Plugin.ID, DirectoryKey: request.DirectoryKey, Path: request.Path, State: state, Entries: entries, Job: latest, RefreshedAt: latest.TerminalAt, Reason: reason}), nil
|
||||
}
|
||||
@@ -425,7 +425,34 @@ func filterServerFileEntries(entries []domain.ServerFileEntry, query string) []d
|
||||
}
|
||||
|
||||
func (svc *CoreService) latestFileListJob(serverInstanceID string, directoryKey string, relativePath string) (domain.Job, bool, error) {
|
||||
return svc.latestServerFileJob(serverInstanceID, domain.JobCapabilityFilesList, directoryKey)
|
||||
jobs, err := svc.store.Jobs().List(domain.JobFilter{ServerInstanceID: serverInstanceID})
|
||||
if err != nil {
|
||||
return domain.Job{}, false, err
|
||||
}
|
||||
var latest domain.Job
|
||||
found := false
|
||||
for _, job := range jobs {
|
||||
if job.Capability != domain.JobCapabilityFilesList || job.TargetKey != directoryKey {
|
||||
continue
|
||||
}
|
||||
if job.ExecutionInput.Inputs["path"] != relativePath {
|
||||
continue
|
||||
}
|
||||
if !found || job.UpdatedAt.After(latest.UpdatedAt) || job.CreatedAt.After(latest.CreatedAt) {
|
||||
latest = job
|
||||
found = true
|
||||
}
|
||||
}
|
||||
return domain.CopyJob(latest), found, nil
|
||||
}
|
||||
|
||||
func isServerFileCapability(capability string) bool {
|
||||
switch capability {
|
||||
case domain.JobCapabilityFilesList, domain.JobCapabilityFilesRead, domain.JobCapabilityFilesWrite:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *CoreService) latestFileReadJob(serverInstanceID string, key string) (domain.Job, bool, error) {
|
||||
|
||||
@@ -1270,6 +1270,13 @@ func ValidateServerInstanceDependenciesForCapabilities(instance domain.ServerIns
|
||||
violations = append(violations, "run endpoint must be online or degraded")
|
||||
}
|
||||
missing := MissingCapabilities(endpoint.Capabilities, requiredRunCapabilities)
|
||||
fileCapabilityMissing := missing[:0]
|
||||
for _, capability := range missing {
|
||||
if capability != "files.list" && capability != "files.read" && capability != "files.write" {
|
||||
fileCapabilityMissing = append(fileCapabilityMissing, capability)
|
||||
}
|
||||
}
|
||||
missing = fileCapabilityMissing
|
||||
if len(missing) > 0 {
|
||||
violations = append(violations, "run endpoint missing required capabilities: "+strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user