Align runtime profiles with plugin-owned records

This commit is contained in:
npc0-hue
2026-09-02 10:22:14 +08:00
parent 6018d8f0fc
commit a027ca70eb
36 changed files with 234 additions and 1590 deletions
+3 -13
View File
@@ -4,29 +4,19 @@ import "testing"
func TestCopyGameClientBridgeDeclarationsCopiesQueryTemplateSlices(t *testing.T) {
manifest := GameClientBridgeManifest{
QueryTemplates: []GameClientBridgeQueryTemplateDeclaration{{Key: "player.lookup", PollIntervalSeconds: 3, SQLRef: "sql/player-lookup.sql", Projections: []GameClientBridgeQueryProjectionDeclaration{{Collection: "users", RowPath: "rows", MatchField: "kind", MatchValue: "player", UpsertKeys: []string{"steamId"}, FieldMappings: map[string]string{"steamId": "steamId"}, FixedValues: map[string]string{"source": "sqlite"}, ObservedAtField: "sampledAt", MergeExisting: true}}}},
LogProjections: []GameClientBridgeLogProjectionDeclaration{{
Key: "player.login", StreamKeys: []string{"process.stdout"}, Steps: []GameClientBridgeLogProjectionStepDeclaration{{Pattern: `Player (?<slot>\d+)`}}, CorrelationFields: []string{"slot"}, MaxInterveningLines: 8,
Target: GameClientBridgeLogProjectionTargetDeclaration{Collection: "users", UpsertKeys: []string{"steamId"}, CaptureMappings: map[string]string{"steamId": "steamId"}, HashMappings: map[string]string{"networkCorrelation": "ip"}, FixedValues: map[string]string{"source": "stdout"}, ObservedAtField: "lastLoginAt"},
Presence: &GameClientBridgeLogProjectionPresenceDeclaration{TimestampField: "lastLoginAt", ActiveWindowSeconds: 600, ActivityTarget: &GameClientBridgeLogProjectionTargetDeclaration{Collection: "activity", UpsertKeys: []string{"steamId"}, CaptureMappings: map[string]string{"steamId": "steamId"}}},
}},
QueryTemplates: []GameClientBridgeQueryTemplateDeclaration{{Key: "player.lookup", PollIntervalSeconds: 3, SQLRef: "sql/player-lookup.sql", Projections: []GameClientBridgeQueryProjectionDeclaration{{Collection: "users", RowPath: "rows", MatchField: "kind", MatchValue: "player", UpsertKeys: []string{"steamId"}, FieldMappings: map[string]string{"steamId": "steamId"}, FixedValues: map[string]string{"source": "sqlite"}, ObservedAtField: "sampledAt", MergeExisting: true}}}},
LifecycleProjections: []GameClientBridgeLifecycleProjectionDeclaration{{Key: "server.stop", Capabilities: []string{"process.stop"}, ProcessStates: []string{"stopped"}, Target: GameClientBridgeBulkProjectionTargetDeclaration{Collection: "users", MatchField: "online", MatchValue: "true", FixedValues: map[string]string{"online": "false"}, ActivityTarget: &GameClientBridgeBulkActivityTargetDeclaration{Collection: "activity", UpsertKeys: []string{"steamId"}, RowMappings: map[string]string{"steamId": "steamId"}, FixedValues: map[string]string{"eventType": "logout"}}}}},
DataPacks: []GameClientBridgeDataPackDeclaration{{Key: "db-v1", LogParserRefs: []string{"logs.json"}, ConfigMapRefs: []string{"config.json"}, DataRefs: []string{"data.json"}}},
DataPacks: []GameClientBridgeDataPackDeclaration{{Key: "db-v1", ConfigMapRefs: []string{"config.json"}, DataRefs: []string{"data.json"}}},
Pages: []GameClientBridgePageContract{{PageKey: "players", QueryTemplateKeys: []string{"player.lookup"}}},
}
manifestCopy := CopyGameClientBridgeManifest(manifest)
manifestCopy.QueryTemplates[0].Key = "mutated"
manifestCopy.QueryTemplates[0].Projections[0].FieldMappings["steamId"] = "mutated"
manifestCopy.LogProjections[0].StreamKeys[0] = "mutated"
manifestCopy.LogProjections[0].Target.CaptureMappings["steamId"] = "mutated"
manifestCopy.LogProjections[0].Target.HashMappings["networkCorrelation"] = "mutated"
manifestCopy.LogProjections[0].Presence.ActivityTarget.CaptureMappings["steamId"] = "mutated"
manifestCopy.LifecycleProjections[0].Capabilities[0] = "mutated"
manifestCopy.LifecycleProjections[0].Target.ActivityTarget.RowMappings["steamId"] = "mutated"
manifestCopy.DataPacks[0].LogParserRefs[0] = "mutated"
manifestCopy.DataPacks[0].DataRefs[0] = "mutated"
manifestCopy.Pages[0].QueryTemplateKeys[0] = "mutated"
if manifest.QueryTemplates[0].Key != "player.lookup" || manifest.QueryTemplates[0].SQLRef != "sql/player-lookup.sql" || manifest.QueryTemplates[0].Projections[0].FieldMappings["steamId"] != "steamId" || !manifest.QueryTemplates[0].Projections[0].MergeExisting || manifest.LogProjections[0].StreamKeys[0] != "process.stdout" || manifest.LogProjections[0].Target.CaptureMappings["steamId"] != "steamId" || manifest.LogProjections[0].Target.HashMappings["networkCorrelation"] != "ip" || manifest.LogProjections[0].Presence.ActivityTarget.CaptureMappings["steamId"] != "steamId" || manifest.LifecycleProjections[0].Capabilities[0] != "process.stop" || manifest.LifecycleProjections[0].Target.ActivityTarget.RowMappings["steamId"] != "steamId" || manifest.DataPacks[0].LogParserRefs[0] != "logs.json" || manifest.DataPacks[0].DataRefs[0] != "data.json" || manifest.Pages[0].QueryTemplateKeys[0] != "player.lookup" {
if manifest.QueryTemplates[0].Key != "player.lookup" || manifest.QueryTemplates[0].SQLRef != "sql/player-lookup.sql" || manifest.QueryTemplates[0].Projections[0].FieldMappings["steamId"] != "steamId" || !manifest.QueryTemplates[0].Projections[0].MergeExisting || manifest.LifecycleProjections[0].Capabilities[0] != "process.stop" || manifest.LifecycleProjections[0].Target.ActivityTarget.RowMappings["steamId"] != "steamId" || manifest.DataPacks[0].DataRefs[0] != "data.json" || manifest.Pages[0].QueryTemplateKeys[0] != "player.lookup" {
t.Fatalf("manifest copy aliases query template declarations: source=%#v copy=%#v", manifest, manifestCopy)
}
+19 -22
View File
@@ -442,26 +442,6 @@ type RuntimeLogSource struct {
RetentionDays int
}
type RuntimeLogEventSeverity string
const (
RuntimeLogEventSeverityInfo RuntimeLogEventSeverity = "info"
RuntimeLogEventSeverityNotice RuntimeLogEventSeverity = "notice"
RuntimeLogEventSeverityWarning RuntimeLogEventSeverity = "warning"
RuntimeLogEventSeverityCritical RuntimeLogEventSeverity = "critical"
)
type RuntimeLogEvent struct {
Key string
Title string
SourceKey string
EventType string
Permission string
SchemaRef string
RetentionDays int
Severity RuntimeLogEventSeverity
}
type RuntimeTransportProfile struct {
Key string
Kind string
@@ -469,6 +449,20 @@ type RuntimeTransportProfile struct {
Capabilities []string
}
// RuntimeDataTarget declares a bounded plugin-owned local data snapshot that
// Run may materialize before a typed query. It never carries a host path.
type RuntimeDataTarget struct {
Key string
Kind string
TransportKey string
SourceRootKey string
SourcePath string
WorkspaceKey string
RefreshPolicy string
MaxBytes int64
Platforms []string
}
type RuntimeClientManagerProfile struct {
Key string
DisplayName string
@@ -597,8 +591,8 @@ type GamePluginRuntimeProfiles struct {
InstallPlans []RuntimeInstallPlan
ServerDeployments []RuntimeServerDeploymentProfile
LogSources []RuntimeLogSource
LogEvents []RuntimeLogEvent
TransportProfiles []RuntimeTransportProfile
DataTargets []RuntimeDataTarget
ClientManagers []RuntimeClientManagerProfile
DLLExtensions []RuntimeDLLExtensionProfile
}
@@ -1926,11 +1920,14 @@ func CopyGamePluginRuntimeProfiles(profiles GamePluginRuntimeProfiles) GamePlugi
profiles.ServerDeployments[i] = CopyRuntimeServerDeploymentProfile(profiles.ServerDeployments[i])
}
profiles.LogSources = append([]RuntimeLogSource(nil), profiles.LogSources...)
profiles.LogEvents = append([]RuntimeLogEvent(nil), profiles.LogEvents...)
profiles.TransportProfiles = append([]RuntimeTransportProfile(nil), profiles.TransportProfiles...)
for i := range profiles.TransportProfiles {
profiles.TransportProfiles[i].Capabilities = CopyStringSlice(profiles.TransportProfiles[i].Capabilities)
}
profiles.DataTargets = append([]RuntimeDataTarget(nil), profiles.DataTargets...)
for i := range profiles.DataTargets {
profiles.DataTargets[i].Platforms = CopyStringSlice(profiles.DataTargets[i].Platforms)
}
profiles.ClientManagers = append([]RuntimeClientManagerProfile(nil), profiles.ClientManagers...)
for i := range profiles.ClientManagers {
profiles.ClientManagers[i].SupportedTargets = append([]RuntimeTarget(nil), profiles.ClientManagers[i].SupportedTargets...)
@@ -1,19 +0,0 @@
package domain
import "testing"
func TestCopyGamePluginRuntimeProfilesCopiesLogEvents(t *testing.T) {
profiles := GamePluginRuntimeProfiles{
LogEvents: []RuntimeLogEvent{{
Key: "chat-message", Title: "Chat message", SourceKey: "chat-log", EventType: "chat.message",
Permission: "server.logs.read", SchemaRef: "schemas/log-events/chat-message.schema.json", RetentionDays: 30, Severity: "info",
}},
}
copied := CopyGamePluginRuntimeProfiles(profiles)
copied.LogEvents[0].Title = "Mutated"
if profiles.LogEvents[0].Title != "Chat message" {
t.Fatalf("expected log event declarations to be copied, got %+v", profiles.LogEvents)
}
}