Fix local run freshness and plugin asset handling

This commit is contained in:
npc0-hue
2026-08-22 19:45:00 +08:00
parent bb5e48b29c
commit ebd616c549
23 changed files with 312 additions and 58 deletions
+4 -4
View File
@@ -461,7 +461,7 @@ func (svc *CoreService) authorizeClientManagerLifecycle(sessionID, serverInstanc
if err != nil || profile.Deployment.Mode != "run-supervised" || !containsString(profile.Deployment.RequiredRunCapabilities, capability) {
return domain.User{}, domain.ServerInstance{}, domain.GamePlugin{}, domain.RuntimeClientManagerProfile{}, domain.RunEndpoint{}, ErrForbidden
}
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return domain.User{}, domain.ServerInstance{}, domain.GamePlugin{}, domain.RuntimeClientManagerProfile{}, domain.RunEndpoint{}, err
}
@@ -1027,11 +1027,11 @@ func (svc *CoreService) clientManagerLifecycleView(installation domain.ClientMan
}
profile, _ := findRuntimeClientManagerProfile(plugin, installation.ProfileKey)
endpoint, endpointErr := svc.store.RunEndpoints().Get(instance.RunEndpointID)
view.Actions = clientManagerLifecycleActions(installation, view.Distribution, profile, endpoint, endpointErr)
view.Actions = svc.clientManagerLifecycleActions(installation, view.Distribution, profile, endpoint, endpointErr)
return domain.CopyClientManagerLifecycleView(view), nil
}
func clientManagerLifecycleActions(installation domain.ClientManagerInstallation, distribution domain.ClientManagerDistribution, profile domain.RuntimeClientManagerProfile, endpoint domain.RunEndpoint, endpointErr error) []domain.ClientManagerLifecycleActionAvailability {
func (svc *CoreService) clientManagerLifecycleActions(installation domain.ClientManagerInstallation, distribution domain.ClientManagerDistribution, profile domain.RuntimeClientManagerProfile, endpoint domain.RunEndpoint, endpointErr error) []domain.ClientManagerLifecycleActionAvailability {
operations := []domain.ClientManagerLifecycleOperation{domain.ClientManagerOperationDeploy, domain.ClientManagerOperationStart, domain.ClientManagerOperationStop, domain.ClientManagerOperationRestart, domain.ClientManagerOperationStatus, domain.ClientManagerOperationUpdate, domain.ClientManagerOperationRollback, domain.ClientManagerOperationUninstall}
items := make([]domain.ClientManagerLifecycleActionAvailability, 0, len(operations))
for _, operation := range operations {
@@ -1046,7 +1046,7 @@ func clientManagerLifecycleActions(installation domain.ClientManagerInstallation
case domain.ClientManagerOperationUninstall:
capability = domain.JobCapabilityClientManagerUninstall
}
available := endpointErr == nil && endpoint.Status == domain.RunEndpointStatusOnline && containsString(endpoint.Capabilities, capability) && containsString(profile.Deployment.RequiredRunCapabilities, capability)
available := endpointErr == nil && endpoint.Status == domain.RunEndpointStatusOnline && svc.runEndpointHeartbeatCurrent(endpoint) && containsString(endpoint.Capabilities, capability) && containsString(profile.Deployment.RequiredRunCapabilities, capability)
reason := ""
if !available {
reason = "assigned Run endpoint is offline or lacks the declared capability"
+3 -3
View File
@@ -270,7 +270,7 @@ func (svc *CoreService) resolveDependencyContext(serverInstanceID string) (depen
if binding.Status != domain.RuntimeBindingStatusComplete || binding.PluginVersion != plugin.Version {
return dependencyResolution{}, validationError("runtime binding is incomplete or stale")
}
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return dependencyResolution{}, err
}
@@ -410,7 +410,7 @@ func (svc *CoreService) resolveRunUpdate(job domain.Job) (domain.RunUpdateJob, d
if distribution.ID == "" || distribution.RunEndpointID != job.RunEndpointID || distribution.TargetOS != update.TargetOS || distribution.TargetArch != update.TargetArch || distribution.Checksum != update.Checksum {
return domain.RunUpdateJob{}, domain.RunDistribution{}, domain.Artifact{}, validationError("Run distribution no longer matches update")
}
endpoint, err := svc.store.RunEndpoints().Get(job.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(job.RunEndpointID)
if err != nil {
return domain.RunUpdateJob{}, domain.RunDistribution{}, domain.Artifact{}, err
}
@@ -551,7 +551,7 @@ func (svc *CoreService) ReportRunUpdateHealth(report domain.RunUpdateHealthRepor
if update.ID == "" || job.ExecutionResult.Checksum != update.Checksum {
return domain.RunUpdateHealthResult{}, validationError("Run update health report does not match staged update")
}
endpoint, err := svc.store.RunEndpoints().Get(report.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(report.RunEndpointID)
if err != nil {
return domain.RunUpdateHealthResult{}, err
}
@@ -376,13 +376,14 @@ func encodePluginWorkspaceSeed(files []domain.PluginAssetFile) (string, error) {
return "", nil
}
type seedFile struct {
Path string `json:"path"`
Content string `json:"content"`
Mode int `json:"mode,omitempty"`
Path string `json:"path"`
Content string `json:"content"`
Encoding string `json:"encoding,omitempty"`
Mode int `json:"mode,omitempty"`
}
seed := make([]seedFile, len(files))
for i, file := range files {
seed[i] = seedFile{Path: file.Path, Content: file.Content, Mode: file.Mode}
seed[i] = seedFile{Path: file.Path, Content: file.Content, Encoding: file.Encoding, Mode: file.Mode}
}
body, err := json.Marshal(seed)
if err != nil {
@@ -95,6 +95,7 @@ func TestCoreServiceKeepsPlatformBuildKeyOffMachineJobChannel(t *testing.T) {
plugin.LifecycleAssets = []domain.PluginAssetFile{
{Path: "actions/install.json", Content: `{"version":1,"action":"install","mode":"oneshot"}`, Mode: 0o600},
{Path: "bin/install-server", Content: "#!/usr/bin/env sh\n", Mode: 0o700},
{Path: "assets/map.bin", Content: base64.StdEncoding.EncodeToString([]byte{0xff, 0x00, 0x7f}), Encoding: "base64", Mode: 0o600},
}
plugin.RuntimeProfiles.LogSources = append(plugin.RuntimeProfiles.LogSources,
domain.RuntimeLogSource{Key: "console", Kind: "process.stdout", TargetKey: "server/process", StreamKey: "console", CursorKind: "sequence", RetentionDays: 14},
@@ -135,10 +136,10 @@ func TestCoreServiceKeepsPlatformBuildKeyOffMachineJobChannel(t *testing.T) {
if err := json.Unmarshal(decodedSeed, &seedFiles); err != nil {
t.Fatalf("unmarshal workspace seed: %v", err)
}
if platformInput.ProfileKey != "local" || len(seedFiles) != 3 || seedFiles[1].Path != "bin/install-server" || seedFiles[1].Content == "" {
if platformInput.ProfileKey != "local" || len(seedFiles) != 4 || seedFiles[1].Path != "bin/install-server" || seedFiles[1].Content == "" || seedFiles[2].Encoding != "base64" {
t.Fatalf("platform builder received incomplete plugin workspace seed: profile=%q seed=%+v", platformInput.ProfileKey, seedFiles)
}
if seedFiles[2].Path != ".platform/autonomous-lifecycle-plan.json" || seedFiles[2].Content == "" || seedFiles[2].Mode != 0o600 {
if seedFiles[3].Path != ".platform/autonomous-lifecycle-plan.json" || seedFiles[3].Content == "" || seedFiles[3].Mode != 0o600 {
t.Fatalf("workspace seed did not include autonomous lifecycle plan file: %+v", seedFiles)
}
plan := platformInput.AutonomousLifecycle
@@ -152,7 +153,7 @@ func TestCoreServiceKeepsPlatformBuildKeyOffMachineJobChannel(t *testing.T) {
t.Fatalf("autonomous lifecycle plan must not carry file-tail sources into process.start: %+v", plan.LogSources)
}
var seededPlan domain.RunAutonomousLifecyclePlan
if err := json.Unmarshal([]byte(seedFiles[2].Content), &seededPlan); err != nil {
if err := json.Unmarshal([]byte(seedFiles[3].Content), &seededPlan); err != nil {
t.Fatalf("unmarshal seeded autonomous lifecycle plan: %v", err)
}
if seededPlan.ServerInstanceID != plan.ServerInstanceID || seededPlan.Bootstrap == nil || seededPlan.Bootstrap.TargetKey != plan.Bootstrap.TargetKey {
+2 -2
View File
@@ -413,7 +413,7 @@ func (svc *CoreService) GetServerRuntimeActionsForSession(sessionID string, serv
if err != nil {
return domain.ServerRuntimeActions{}, err
}
endpoint, endpointErr := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, endpointErr := svc.GetRunEndpoint(instance.RunEndpointID)
runRegistered := endpointErr == nil
if endpointErr != nil && !errors.Is(endpointErr, repo.ErrNotFound) {
return domain.ServerRuntimeActions{}, endpointErr
@@ -514,7 +514,7 @@ func (svc *CoreService) PushRunUpdateForSession(sessionID string, request domain
if request.Checksum != artifact.Checksum {
return domain.RunUpdateJob{}, validationError("checksum must match artifact")
}
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return domain.RunUpdateJob{}, err
}
+15
View File
@@ -199,10 +199,25 @@ func TestCoreServiceDistributionBuildIgnoresStaleRunEndpoint(t *testing.T) {
if err != nil {
t.Fatalf("get runtime actions: %v", err)
}
if actions.RunStatus != domain.RunEndpointStatusOffline {
t.Fatalf("stale Run endpoint must project offline runtime status, got %+v", actions)
}
staleRunGated := map[string]bool{"dependencies-check": false, "dependencies-install": false, "live-logs": false}
for _, action := range actions.Actions {
if action.Key == "generate-run" && !action.Available {
t.Fatalf("stale Run endpoint must not gate platform build availability: %+v", action)
}
if _, gated := staleRunGated[action.Key]; gated {
staleRunGated[action.Key] = true
if action.Available || action.Reason != "Run heartbeat has not been observed" {
t.Fatalf("stale Run endpoint must gate runtime action %s, got %+v", action.Key, action)
}
}
}
for key, seen := range staleRunGated {
if !seen {
t.Fatalf("expected stale Run gating action %s in %+v", key, actions.Actions)
}
}
}
+1 -1
View File
@@ -55,7 +55,7 @@ func (svc *CoreService) RunPluginLifecycleForSession(sessionID string, request d
if !containsString(plugin.ProductionLifecycle.Operations, string(request.Operation)) {
return domain.PluginLifecycleResult{}, validationError("plugin lifecycle operation is not declared by the manifest")
}
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return domain.PluginLifecycleResult{}, err
}
+2 -2
View File
@@ -17,7 +17,7 @@ func (svc *CoreService) ListRemoteAdapterDeclarationsForSession(sessionID string
if err != nil {
return nil, err
}
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return nil, err
}
@@ -61,7 +61,7 @@ func (svc *CoreService) RequestRemoteAdapterForSession(sessionID string, request
}
if selected.Key == "" {
plugin, pluginErr := svc.store.GamePlugins().Get(instance.PluginID)
endpoint, endpointErr := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, endpointErr := svc.GetRunEndpoint(instance.RunEndpointID)
if pluginErr == nil && endpointErr == nil && plugin.Permissions.RemoteAccess && containsString(plugin.RemoteAccess.RunCapabilities, request.Capability) && containsString(endpoint.Capabilities, request.Capability) {
selected = domain.RemoteAdapterDeclaration{Key: "legacy-" + string(remoteAdapterKindForCapability(request.Capability)), Kind: remoteAdapterKindForCapability(request.Capability), TargetKeys: []string{request.TargetKey}, Capabilities: []string{request.Capability}, TimeoutSeconds: 30, MaxAttempts: 3}
}
+57 -7
View File
@@ -739,17 +739,67 @@ func (svc *CoreService) RegisterGamePluginManifest(registration domain.GamePlugi
if err := validator.ValidateGamePlugin(plugin); err != nil {
return domain.GamePlugin{}, err
}
if err := svc.store.GamePlugins().Create(plugin); err != nil {
if !errors.Is(err, repo.ErrDuplicate) {
return domain.GamePlugin{}, err
}
if existing, err := svc.store.GamePlugins().Get(plugin.ID); err == nil {
if err := svc.store.GamePlugins().Update(plugin); err != nil {
return domain.GamePlugin{}, err
}
if err := svc.refreshServerPluginReferences(existing.ID, plugin.Version); err != nil {
return domain.GamePlugin{}, err
}
} else if errors.Is(err, repo.ErrNotFound) {
if err := svc.store.GamePlugins().Create(plugin); err != nil {
return domain.GamePlugin{}, err
}
} else {
return domain.GamePlugin{}, err
}
return domain.CopyGamePlugin(plugin), nil
}
// refreshServerPluginReferences keeps existing server projections usable when a
// manifest is refreshed in place. The server and its logical runtime binding
// carry the manifest version used for lifecycle validation; leaving either at a
// stale version would make a healthy existing server impossible to start after
// the registry refresh.
func (svc *CoreService) refreshServerPluginReferences(pluginID, pluginVersion string) error {
if strings.TrimSpace(pluginID) == "" || strings.TrimSpace(pluginVersion) == "" {
return nil
}
stamp := svc.now()
instances, err := svc.store.ServerInstances().List(domain.ServerInstanceFilter{PluginID: pluginID})
if err != nil {
return err
}
for _, instance := range instances {
if instance.PluginVersion != pluginVersion {
instance.PluginVersion = pluginVersion
instance.UpdatedAt = stamp
if err := validator.ValidateStoredServerInstance(instance); err != nil {
return err
}
if err := svc.store.ServerInstances().Update(instance); err != nil {
return err
}
}
bindings, err := svc.store.RuntimeBindings().List(domain.RuntimeBindingFilter{ServerInstanceID: instance.ID})
if err != nil {
return err
}
for _, binding := range bindings {
if binding.PluginID != pluginID || binding.PluginVersion == pluginVersion {
continue
}
binding.PluginVersion = pluginVersion
binding.UpdatedAt = stamp
if err := svc.store.RuntimeBindings().Update(binding); err != nil {
return err
}
}
}
return nil
}
func gamePluginFromManifestRegistration(registration domain.GamePluginManifestRegistration) domain.GamePlugin {
registration = domain.CopyGamePluginManifestRegistration(registration)
manifest := registration.Manifest
@@ -1633,7 +1683,7 @@ func (svc *CoreService) CreateServerInstance(instance domain.ServerInstance) (do
}
var endpoint domain.RunEndpoint
if strings.TrimSpace(instance.RunEndpointID) != "" {
endpoint, err = svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err = svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return domain.ServerInstance{}, fmt.Errorf("get run endpoint dependency: %w", err)
}
@@ -1779,7 +1829,7 @@ func (svc *CoreService) GetPlatformResourceUsage() (domain.PlatformResourceUsage
if err != nil {
return domain.PlatformResourceUsage{}, err
}
endpoints, err := svc.store.RunEndpoints().List(domain.RunEndpointFilter{})
endpoints, err := svc.ListRunEndpoints(domain.RunEndpointFilter{})
if err != nil {
return domain.PlatformResourceUsage{}, err
}
@@ -2212,7 +2262,7 @@ func (svc *CoreService) latestMetricsForServer(instance domain.ServerInstance) d
}
return domain.ServerMetrics{
ServerInstanceID: instance.ID,
Online: instance.State == domain.ServerInstanceStateRunning,
Online: false,
Source: "run-metrics-pending",
CollectedAt: svc.now(),
}
+30 -4
View File
@@ -1,6 +1,7 @@
package service
import (
"encoding/base64"
"errors"
"strings"
"testing"
@@ -165,6 +166,17 @@ func TestCoreServiceCreateListGetWorkflows(t *testing.T) {
}
func TestCoreServiceRejectsServerCreationOnStaleRunEndpoint(t *testing.T) {
svc := newTestCoreService()
plugin, endpoint := createPluginAndRunEndpoint(t, svc)
svc.now = func() time.Time { return fixedTime.Add(runHeartbeatStaleAfter + time.Second) }
_, err := svc.CreateServerInstance(domain.ServerInstance{ID: "server-stale-run", PluginID: plugin.ID, RunEndpointID: endpoint.ID, Name: "Stale Run Server"})
if err == nil || !strings.Contains(err.Error(), "get run endpoint dependency") || !errors.Is(err, repo.ErrNotFound) {
t.Fatalf("expected stale Run endpoint to be rejected before binding, got %v", err)
}
}
func TestCoreServiceCreateRemoteProgramJobCreatesManagementLogStreams(t *testing.T) {
svc := newTestCoreService()
plugin, endpoint := createPluginAndRunEndpoint(t, svc)
@@ -685,7 +697,7 @@ func TestCoreServiceMetricsAndConfigReadAreRoleScoped(t *testing.T) {
if err != nil {
t.Fatalf("list owner metrics: %v", err)
}
if len(ownerMetrics) != 1 || ownerMetrics[0].ServerInstanceID != instance.ID || !ownerMetrics[0].Online || ownerMetrics[0].CPUPercent != nil || ownerMetrics[0].Source != "run-metrics-pending" {
if len(ownerMetrics) != 1 || ownerMetrics[0].ServerInstanceID != instance.ID || ownerMetrics[0].Online || ownerMetrics[0].CPUPercent != nil || ownerMetrics[0].Source != "run-metrics-pending" {
t.Fatalf("expected pending metrics without fabricated resource values, got %+v", ownerMetrics)
}
@@ -1223,8 +1235,8 @@ func TestCoreServiceRegistersGamePluginManifest(t *testing.T) {
svc := newTestCoreService()
registration := validPluginManifestRegistration()
registration.Manifest.AssetFiles = []domain.PluginAssetFile{{Path: "actions/install.json", Mode: 0o600}, {Path: "bin/install-server", Mode: 0o700}}
registration.AssetFiles = []domain.PluginAssetFile{{Path: "actions/install.json", Content: "{}", Mode: 0o600}, {Path: "bin/install-server", Content: "#!/usr/bin/env sh\n"}}
registration.Manifest.AssetFiles = []domain.PluginAssetFile{{Path: "actions/install.json", Mode: 0o600}, {Path: "bin/install-server", Mode: 0o700}, {Path: "assets/map.bin", Mode: 0o600}}
registration.AssetFiles = []domain.PluginAssetFile{{Path: "actions/install.json", Content: "{}", Mode: 0o600}, {Path: "bin/install-server", Content: "#!/usr/bin/env sh\n"}, {Path: "assets/map.bin", Content: base64.StdEncoding.EncodeToString([]byte{0xff, 0x00, 0x7f}), Encoding: "base64"}}
plugin, err := svc.RegisterGamePluginManifest(registration)
if err != nil {
t.Fatalf("register manifest: %v", err)
@@ -1247,7 +1259,7 @@ func TestCoreServiceRegistersGamePluginManifest(t *testing.T) {
if len(plugin.BridgeActions) != 4 || plugin.BridgeActions[0] != string(domain.PluginBridgeActionServerInstancesRead) {
t.Fatalf("expected bridge actions, got %+v", plugin.BridgeActions)
}
if len(plugin.LifecycleAssets) != 2 || plugin.LifecycleAssets[1].Path != "bin/install-server" || plugin.LifecycleAssets[1].Mode != 0o700 {
if len(plugin.LifecycleAssets) != 3 || plugin.LifecycleAssets[1].Path != "bin/install-server" || plugin.LifecycleAssets[1].Mode != 0o700 || plugin.LifecycleAssets[2].Encoding != "base64" {
t.Fatalf("expected declared lifecycle assets with manifest mode defaults, got %+v", plugin.LifecycleAssets)
}
@@ -1624,6 +1636,12 @@ func TestCoreServiceUpsertsDuplicateGamePluginManifest(t *testing.T) {
if _, err := svc.RegisterGamePluginManifest(registration); err != nil {
t.Fatalf("register first manifest: %v", err)
}
if _, err := svc.CreateServerInstance(domain.ServerInstance{ID: "manifest-refresh-server", PluginID: registration.Manifest.ID, PluginVersion: registration.Manifest.Version, Name: "Manifest refresh server"}); err != nil {
t.Fatalf("create server for manifest refresh: %v", err)
}
if err := svc.store.RuntimeBindings().Create(domain.RuntimeBinding{ID: "runtime-binding-manifest-refresh-server", ServerInstanceID: "manifest-refresh-server", PluginID: registration.Manifest.ID, PluginVersion: registration.Manifest.Version, ProfileKey: "local", Mode: "local-process", Status: domain.RuntimeBindingStatusComplete, CreatedAt: fixedTime, UpdatedAt: fixedTime}); err != nil {
t.Fatalf("create runtime binding for manifest refresh: %v", err)
}
registration.Manifest.Version = "0.1.1"
registration.Manifest.Description = "Development plugin refreshed"
@@ -1639,6 +1657,14 @@ func TestCoreServiceUpsertsDuplicateGamePluginManifest(t *testing.T) {
if err != nil || len(listed) != 1 || listed[0].ID != "game.example" || listed[0].Version != "0.1.1" {
t.Fatalf("expected one refreshed plugin after upsert, listed=%+v err=%v", listed, err)
}
server, err := svc.GetServerInstance("manifest-refresh-server")
if err != nil || server.PluginVersion != "0.1.1" {
t.Fatalf("expected existing server to follow refreshed plugin version, server=%+v err=%v", server, err)
}
binding, err := svc.store.RuntimeBindings().Get("runtime-binding-manifest-refresh-server")
if err != nil || binding.PluginVersion != "0.1.1" {
t.Fatalf("expected runtime binding to follow refreshed plugin version, binding=%+v err=%v", binding, err)
}
}
func TestCoreServiceRejectsUnsafeGamePluginManifest(t *testing.T) {
+1 -1
View File
@@ -104,7 +104,7 @@ func (svc *CoreService) deployServerInstance(command domain.ServerLifecycleComma
if strings.TrimSpace(instance.RunEndpointID) == "" {
return domain.ServerLifecycleResult{}, validationError("an active Run heartbeat is required for legacy manual deployment dispatch")
}
if _, err := svc.store.RunEndpoints().Get(instance.RunEndpointID); err != nil {
if _, err := svc.GetRunEndpoint(instance.RunEndpointID); err != nil {
return domain.ServerLifecycleResult{}, err
}
plugin, endpoint, err := svc.lifecycleDependencies(instance.PluginID, instance.RunEndpointID)
+4 -4
View File
@@ -66,7 +66,7 @@ func (svc *CoreService) CreateServerInstanceWorkflow(create domain.ServerLifecyc
instance.ConfigChecksum = validator.BytesChecksum([]byte(instance.ConfigContent))
instance.ConfigUpdatedAt = stamp
if strings.TrimSpace(create.DeploymentTargetID) != "" {
target, targetErr := svc.store.RunEndpoints().Get(create.DeploymentTargetID)
target, targetErr := svc.GetRunEndpoint(create.DeploymentTargetID)
if targetErr != nil {
return domain.ServerLifecycleResult{}, fmt.Errorf("get deployment target dependency: %w", targetErr)
}
@@ -106,7 +106,7 @@ func (svc *CoreService) CreateServerInstanceWorkflow(create domain.ServerLifecyc
}
return domain.CopyServerLifecycleResult(domain.ServerLifecycleResult{Accepted: true, Action: domain.ServerLifecycleActionCreate, Instance: instance}), nil
}
endpoint, err := svc.store.RunEndpoints().Get(create.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(create.RunEndpointID)
if err != nil {
return domain.ServerLifecycleResult{}, fmt.Errorf("get run endpoint dependency: %w", err)
}
@@ -296,7 +296,7 @@ func (svc *CoreService) lifecycleDependencies(pluginID string, runEndpointID str
if err != nil {
return domain.GamePlugin{}, domain.RunEndpoint{}, fmt.Errorf("get plugin dependency: %w", err)
}
endpoint, err := svc.store.RunEndpoints().Get(runEndpointID)
endpoint, err := svc.GetRunEndpoint(runEndpointID)
if err != nil {
return domain.GamePlugin{}, domain.RunEndpoint{}, fmt.Errorf("get run endpoint dependency: %w", err)
}
@@ -335,7 +335,7 @@ func (svc *CoreService) dispatchLifecycleJob(instance domain.ServerInstance, act
var dllExtensions []domain.RuntimeDLLExtensionPlan
var logSources []domain.RuntimeLogSource
if action == domain.ServerLifecycleActionStart && hasProfile {
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return domain.Job{}, err
}
+1 -1
View File
@@ -167,7 +167,7 @@ func (svc *CoreService) resolveSourceRCONDispatch(instance domain.ServerInstance
if plugin.Status != domain.GamePluginStatusInstalled || plugin.Version != instance.PluginVersion || !plugin.Permissions.RemoteAccess || !plugin.RemoteAccess.RCON || !containsString(plugin.RequiredRunCapabilities, domain.JobCapabilityRemoteRunRCONCommand) || !containsString(plugin.RemoteAccess.RunCapabilities, domain.JobCapabilityRemoteRunRCONCommand) {
return sourceRCONDispatchResolution{}, forbiddenError("plugin does not declare SCUM RCON command access")
}
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
endpoint, err := svc.GetRunEndpoint(instance.RunEndpointID)
if err != nil {
return sourceRCONDispatchResolution{}, err
}