Stream live server logs over SSE

This commit is contained in:
npc0-hue
2026-08-03 22:28:54 +08:00
parent 5d4fca14f9
commit 7eac1926dd
48 changed files with 1526 additions and 263 deletions
+66 -1
View File
@@ -1392,9 +1392,35 @@ func ValidateJob(job domain.Job) error {
for i, plan := range job.ExecutionInput.DLLExtensions {
violations = append(violations, validateRuntimeDLLExtensionPlan(fmt.Sprintf("executionInput.dllExtensions[%d]", i), plan)...)
}
if job.ExecutionInput.LogSource != nil {
violations = append(violations, validateRuntimeLogSourcePlanForJob("executionInput.logSource", job.ExecutionInput.LogSource)...)
if job.Capability != domain.JobCapabilityLogsBackfill || job.ServerInstanceID == "" {
violations = append(violations, "executionInput.logSource is allowed only for logs.backfill jobs")
}
}
if len(job.ExecutionInput.LogSources) > 0 {
if job.Capability != domain.LifecycleCapabilityStart || job.ExecutionInput.LifecycleOperation != "start" || job.ServerInstanceID == "" {
violations = append(violations, "executionInput.logSources are allowed only for scoped process.start jobs")
}
seenKinds := map[string]struct{}{}
for i, source := range job.ExecutionInput.LogSources {
prefix := fmt.Sprintf("executionInput.logSources[%d]", i)
violations = append(violations, validateRuntimeProcessLogSourcePlanForJob(prefix, source)...)
if _, exists := seenKinds[source.Kind]; exists {
violations = append(violations, "executionInput.logSources kind is duplicated")
}
seenKinds[source.Kind] = struct{}{}
}
}
if job.ExecutionInput.SourceRCON != nil {
violations = append(violations, validateRuntimeSourceRCONPlan("executionInput.sourceRcon", job.ExecutionInput.SourceRCON)...)
if job.Capability != domain.JobCapabilityRemoteRunRCONCommand || job.ExecutionInput.RemoteAdapterKind != "rcon" {
isSourceCommand := job.Capability == domain.JobCapabilityRemoteRunRCONCommand
isProtectedRCON := job.Capability == domain.JobCapabilityRemoteRunProtectedRCON
wantAdapterKind := "rcon"
if isProtectedRCON {
wantAdapterKind = "protected-rcon"
}
if (!isSourceCommand && !isProtectedRCON) || job.ExecutionInput.RemoteAdapterKind != wantAdapterKind {
violations = append(violations, "executionInput.sourceRcon is allowed only for rcon jobs")
}
if job.RetryPolicy.MaxAttempts != 1 {
@@ -1441,6 +1467,45 @@ func ValidateJob(job domain.Job) error {
return finish(violations)
}
func validateRuntimeLogSourcePlanForJob(prefix string, source *domain.RuntimeLogSource) []string {
if source == nil {
return nil
}
var violations []string
violations = append(violations, validateProfileKey(prefix+".key", source.Key)...)
violations = append(violations, validateProfileKey(prefix+".targetKey", source.TargetKey)...)
violations = append(violations, validateProfileKey(prefix+".streamKey", source.StreamKey)...)
if source.Kind != "file.tail" {
violations = append(violations, prefix+".kind must be file.tail")
}
if source.CursorKind != "" && !oneOf(source.CursorKind, "offset", "fingerprint") {
violations = append(violations, prefix+".cursorKind is invalid")
}
if source.RetentionDays < 0 || source.RetentionDays > 365 {
violations = append(violations, prefix+".retentionDays is invalid")
}
return violations
}
func validateRuntimeProcessLogSourcePlanForJob(prefix string, source domain.RuntimeLogSource) []string {
var violations []string
violations = append(violations, validateProfileKey(prefix+".key", source.Key)...)
if source.TargetKey != "" {
violations = append(violations, validateProfileKey(prefix+".targetKey", source.TargetKey)...)
}
violations = append(violations, validateProfileKey(prefix+".streamKey", source.StreamKey)...)
if source.Kind != "process.stdout" && source.Kind != "process.stderr" {
violations = append(violations, prefix+".kind must be process.stdout or process.stderr")
}
if source.CursorKind != "" && source.CursorKind != "sequence" {
violations = append(violations, prefix+".cursorKind is invalid")
}
if source.RetentionDays < 0 || source.RetentionDays > 365 {
violations = append(violations, prefix+".retentionDays is invalid")
}
return violations
}
func ValidateArtifact(artifact domain.Artifact) error {
var violations []string
violations = appendRequired(violations, "id", artifact.ID)