first commit
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
|
||||
const maxJobChannelMessageLength = 256
|
||||
|
||||
func ValidateRunJobClaim(claim domain.RunJobClaim) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "runEndpointId", claim.RunEndpointID)
|
||||
violations = appendRequired(violations, "sessionToken", claim.SessionToken)
|
||||
violations = appendCapacityViolations(violations, claim.Capacity)
|
||||
for i, capability := range claim.Capabilities {
|
||||
if strings.TrimSpace(capability) == "" {
|
||||
violations = append(violations, fmt.Sprintf("capabilities[%d] is required", i))
|
||||
}
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateRunJobAck(ack domain.RunJobAck) error {
|
||||
var violations []string
|
||||
violations = appendLeaseFields(violations, ack.RunEndpointID, ack.SessionToken, ack.JobID, ack.LeaseToken, ack.Attempt)
|
||||
violations = appendMessageLength(violations, "message", ack.Message)
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateRunJobProgress(progress domain.RunJobProgress) error {
|
||||
var violations []string
|
||||
violations = appendLeaseFields(violations, progress.RunEndpointID, progress.SessionToken, progress.JobID, progress.LeaseToken, progress.Attempt)
|
||||
violations = appendProgressViolations(violations, progress.Progress)
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateRunJobResult(result domain.RunJobResult) error {
|
||||
var violations []string
|
||||
violations = appendLeaseFields(violations, result.RunEndpointID, result.SessionToken, result.JobID, result.LeaseToken, result.Attempt)
|
||||
if !validTerminalJobState(result.State) {
|
||||
violations = append(violations, "state must be succeeded, failed, or cancelled")
|
||||
}
|
||||
violations = appendProgressViolations(violations, result.Progress)
|
||||
violations = appendMessageLength(violations, "message", result.Message)
|
||||
violations = appendMessageLength(violations, "errorCode", result.ErrorCode)
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateRunJobCancelRequest(request domain.RunJobCancelRequest) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "jobId", request.JobID)
|
||||
violations = appendRequired(violations, "reason", request.Reason)
|
||||
violations = appendMessageLength(violations, "reason", request.Reason)
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateRunJobCancelPoll(poll domain.RunJobCancelPoll) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "runEndpointId", poll.RunEndpointID)
|
||||
violations = appendRequired(violations, "sessionToken", poll.SessionToken)
|
||||
if poll.LeaseToken != "" && strings.TrimSpace(poll.JobID) == "" {
|
||||
violations = append(violations, "jobId is required when leaseToken is provided")
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateRunJobReconcile(reconcile domain.RunJobReconcile) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "runEndpointId", reconcile.RunEndpointID)
|
||||
violations = appendRequired(violations, "sessionToken", reconcile.SessionToken)
|
||||
seen := map[string]struct{}{}
|
||||
for i, jobID := range reconcile.ActiveJobIDs {
|
||||
jobID = strings.TrimSpace(jobID)
|
||||
if jobID == "" {
|
||||
violations = append(violations, fmt.Sprintf("activeJobIds[%d] is required", i))
|
||||
continue
|
||||
}
|
||||
if _, exists := seen[jobID]; exists {
|
||||
violations = append(violations, fmt.Sprintf("activeJobIds[%d] duplicates %q", i, jobID))
|
||||
}
|
||||
seen[jobID] = struct{}{}
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func appendLeaseFields(violations []string, runEndpointID string, sessionToken string, jobID string, leaseToken string, attempt int) []string {
|
||||
violations = appendRequired(violations, "runEndpointId", runEndpointID)
|
||||
violations = appendRequired(violations, "sessionToken", sessionToken)
|
||||
violations = appendRequired(violations, "jobId", jobID)
|
||||
violations = appendRequired(violations, "leaseToken", leaseToken)
|
||||
if attempt <= 0 {
|
||||
violations = append(violations, "attempt must be positive")
|
||||
}
|
||||
return violations
|
||||
}
|
||||
|
||||
func appendProgressViolations(violations []string, progress domain.RunJobProgressReport) []string {
|
||||
if progress.Percent < 0 || progress.Percent > 100 {
|
||||
violations = append(violations, "progress.percent must be between 0 and 100")
|
||||
}
|
||||
violations = appendMessageLength(violations, "progress.message", progress.Message)
|
||||
return violations
|
||||
}
|
||||
|
||||
func appendMessageLength(violations []string, field string, message string) []string {
|
||||
if len(message) > maxJobChannelMessageLength {
|
||||
violations = append(violations, field+" is too long")
|
||||
}
|
||||
return violations
|
||||
}
|
||||
|
||||
func validTerminalJobState(state domain.JobState) bool {
|
||||
switch state {
|
||||
case domain.JobStateSucceeded, domain.JobStateFailed, domain.JobStateCancelled:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user