fix(protocol): fence gateway work recovery
This commit is contained in:
+71
-27
@@ -14,7 +14,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const SchemaSHA256 = "614fa11dd1f49b8e10bf21b8c10eadbc1468d16bfcc6ed0a26d29671a5e61300"
|
||||
const SchemaSHA256 = "8c1ed430127cf5774a919f14ff4770b2509d322c8518bf30c412e1e89eeffced"
|
||||
const ProtocolVersion = "1.0.0"
|
||||
const CurrentWireVersion = "2"
|
||||
const NMinus1WireVersion = "1"
|
||||
@@ -330,8 +330,9 @@ type GatewayQualityAck struct {
|
||||
ReconnectSequence int64 `json:"reconnect_sequence"`
|
||||
OperationID string `json:"operation_id"`
|
||||
Revision int64 `json:"revision"`
|
||||
LeaseGeneration int64 `json:"lease_generation"`
|
||||
Outcome string `json:"outcome"`
|
||||
CurrentAppliedRevision int64 `json:"current_applied_revision"`
|
||||
CurrentAppliedRevision *int64 `json:"current_applied_revision,omitempty"`
|
||||
FailureCode string `json:"failure_code,omitempty"`
|
||||
}
|
||||
|
||||
@@ -342,6 +343,7 @@ type GatewayQualityWork struct {
|
||||
ReconnectSequence int64 `json:"reconnect_sequence"`
|
||||
OperationID string `json:"operation_id"`
|
||||
Revision int64 `json:"revision"`
|
||||
LeaseGeneration int64 `json:"lease_generation"`
|
||||
LeaseExpiresAt string `json:"lease_expires_at"`
|
||||
SelectedDescriptor SelectedSessionDescriptor `json:"selected_descriptor"`
|
||||
CurrentAppliedRevision *int64 `json:"current_applied_revision,omitempty"`
|
||||
@@ -352,8 +354,10 @@ type GatewayQualityWorkRequest struct {
|
||||
SessionID string `json:"session_id"`
|
||||
GatewayID string `json:"gateway_id"`
|
||||
ReconnectSequence int64 `json:"reconnect_sequence"`
|
||||
OperationID string `json:"operation_id"`
|
||||
Revision int64 `json:"revision"`
|
||||
Acquisition string `json:"acquisition"`
|
||||
OperationID string `json:"operation_id,omitempty"`
|
||||
Revision *int64 `json:"revision,omitempty"`
|
||||
LeaseGeneration *int64 `json:"lease_generation,omitempty"`
|
||||
CurrentAppliedRevision *int64 `json:"current_applied_revision,omitempty"`
|
||||
}
|
||||
|
||||
@@ -397,7 +401,8 @@ type GatewayStopWorkRequest struct {
|
||||
SessionID string `json:"session_id"`
|
||||
GatewayID string `json:"gateway_id"`
|
||||
ReconnectSequence int64 `json:"reconnect_sequence"`
|
||||
OperationID string `json:"operation_id"`
|
||||
Acquisition string `json:"acquisition"`
|
||||
OperationID string `json:"operation_id,omitempty"`
|
||||
}
|
||||
|
||||
type GatewayTelemetry struct {
|
||||
@@ -3487,13 +3492,19 @@ func (v GatewayQualityAck) Validate() error {
|
||||
if v.Revision != 0 && v.Revision < 1 {
|
||||
violations = append(violations, FieldViolation{Field: "revision", Code: "minimum"})
|
||||
}
|
||||
if v.LeaseGeneration == 0 {
|
||||
violations = append(violations, FieldViolation{Field: "lease_generation", Code: "required"})
|
||||
}
|
||||
if v.LeaseGeneration != 0 && v.LeaseGeneration < 1 {
|
||||
violations = append(violations, FieldViolation{Field: "lease_generation", Code: "minimum"})
|
||||
}
|
||||
if v.Outcome == "" {
|
||||
violations = append(violations, FieldViolation{Field: "outcome", Code: "required"})
|
||||
}
|
||||
if v.Outcome != "" && !(v.Outcome == "applied" || v.Outcome == "not_applied" || v.Outcome == "uncertain") {
|
||||
if v.Outcome != "" && !(v.Outcome == "applied" || v.Outcome == "proven_prior" || v.Outcome == "unknown") {
|
||||
violations = append(violations, FieldViolation{Field: "outcome", Code: "invalid_value"})
|
||||
}
|
||||
if v.CurrentAppliedRevision != 0 && v.CurrentAppliedRevision < 0 {
|
||||
if v.CurrentAppliedRevision != nil && *v.CurrentAppliedRevision != 0 && *v.CurrentAppliedRevision < 0 {
|
||||
violations = append(violations, FieldViolation{Field: "current_applied_revision", Code: "minimum"})
|
||||
}
|
||||
if len(v.FailureCode) < 1 && v.FailureCode != "" {
|
||||
@@ -3502,6 +3513,15 @@ func (v GatewayQualityAck) Validate() error {
|
||||
if len(v.FailureCode) > 128 {
|
||||
violations = append(violations, FieldViolation{Field: "failure_code", Code: "max_length"})
|
||||
}
|
||||
if v.Outcome == "applied" && (v.CurrentAppliedRevision == nil || *v.CurrentAppliedRevision != v.Revision) {
|
||||
violations = append(violations, FieldViolation{Field: "current_applied_revision", Code: "invalid_tagged_value"})
|
||||
}
|
||||
if v.Outcome == "proven_prior" && (v.CurrentAppliedRevision == nil || *v.CurrentAppliedRevision >= v.Revision) {
|
||||
violations = append(violations, FieldViolation{Field: "current_applied_revision", Code: "invalid_tagged_value"})
|
||||
}
|
||||
if v.Outcome == "unknown" && v.CurrentAppliedRevision != nil {
|
||||
violations = append(violations, FieldViolation{Field: "current_applied_revision", Code: "invalid_tagged_value"})
|
||||
}
|
||||
if len(violations) > 0 {
|
||||
return ValidationError{Violations: violations}
|
||||
}
|
||||
@@ -3520,12 +3540,12 @@ func DecodeGatewayQualityAck(data []byte) (GatewayQualityAck, error) {
|
||||
if err := json.Unmarshal(data, &fields); err != nil {
|
||||
return value, err
|
||||
}
|
||||
if raw, ok := fields["current_applied_revision"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "current_applied_revision", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["gateway_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "gateway_id", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["lease_generation"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "lease_generation", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["operation_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "operation_id", Code: "required"}}}
|
||||
}
|
||||
@@ -3616,6 +3636,12 @@ func (v GatewayQualityWork) Validate() error {
|
||||
if v.Revision != 0 && v.Revision < 1 {
|
||||
violations = append(violations, FieldViolation{Field: "revision", Code: "minimum"})
|
||||
}
|
||||
if v.LeaseGeneration == 0 {
|
||||
violations = append(violations, FieldViolation{Field: "lease_generation", Code: "required"})
|
||||
}
|
||||
if v.LeaseGeneration != 0 && v.LeaseGeneration < 1 {
|
||||
violations = append(violations, FieldViolation{Field: "lease_generation", Code: "minimum"})
|
||||
}
|
||||
if v.LeaseExpiresAt == "" {
|
||||
violations = append(violations, FieldViolation{Field: "lease_expires_at", Code: "required"})
|
||||
}
|
||||
@@ -3660,6 +3686,9 @@ func DecodeGatewayQualityWork(data []byte) (GatewayQualityWork, error) {
|
||||
if raw, ok := fields["lease_expires_at"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "lease_expires_at", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["lease_generation"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "lease_generation", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["operation_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "operation_id", Code: "required"}}}
|
||||
}
|
||||
@@ -3732,8 +3761,11 @@ func (v GatewayQualityWorkRequest) Validate() error {
|
||||
if v.ReconnectSequence != 0 && v.ReconnectSequence < 0 {
|
||||
violations = append(violations, FieldViolation{Field: "reconnect_sequence", Code: "minimum"})
|
||||
}
|
||||
if v.OperationID == "" {
|
||||
violations = append(violations, FieldViolation{Field: "operation_id", Code: "required"})
|
||||
if v.Acquisition == "" {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "required"})
|
||||
}
|
||||
if v.Acquisition != "" && !(v.Acquisition == "poll" || v.Acquisition == "prompt" || v.Acquisition == "observation") {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "invalid_value"})
|
||||
}
|
||||
if len(v.OperationID) < 36 && v.OperationID != "" {
|
||||
violations = append(violations, FieldViolation{Field: "operation_id", Code: "min_length"})
|
||||
@@ -3744,15 +3776,24 @@ func (v GatewayQualityWorkRequest) Validate() error {
|
||||
if v.OperationID != "" && !validCanonicalUUID(v.OperationID) {
|
||||
violations = append(violations, FieldViolation{Field: "operation_id", Code: "invalid_uuid"})
|
||||
}
|
||||
if v.Revision == 0 {
|
||||
violations = append(violations, FieldViolation{Field: "revision", Code: "required"})
|
||||
}
|
||||
if v.Revision != 0 && v.Revision < 1 {
|
||||
if v.Revision != nil && *v.Revision != 0 && *v.Revision < 1 {
|
||||
violations = append(violations, FieldViolation{Field: "revision", Code: "minimum"})
|
||||
}
|
||||
if v.LeaseGeneration != nil && *v.LeaseGeneration != 0 && *v.LeaseGeneration < 1 {
|
||||
violations = append(violations, FieldViolation{Field: "lease_generation", Code: "minimum"})
|
||||
}
|
||||
if v.CurrentAppliedRevision != nil && *v.CurrentAppliedRevision != 0 && *v.CurrentAppliedRevision < 0 {
|
||||
violations = append(violations, FieldViolation{Field: "current_applied_revision", Code: "minimum"})
|
||||
}
|
||||
if v.Acquisition == "poll" && (v.OperationID != "" || v.Revision != nil || v.LeaseGeneration != nil || v.CurrentAppliedRevision != nil) {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "invalid_tagged_value"})
|
||||
}
|
||||
if v.Acquisition == "prompt" && (v.OperationID == "" || v.Revision == nil || v.LeaseGeneration != nil || v.CurrentAppliedRevision != nil) {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "invalid_tagged_value"})
|
||||
}
|
||||
if v.Acquisition == "observation" && (v.OperationID == "" || v.Revision == nil || v.LeaseGeneration == nil || v.CurrentAppliedRevision == nil) {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "invalid_tagged_value"})
|
||||
}
|
||||
if len(violations) > 0 {
|
||||
return ValidationError{Violations: violations}
|
||||
}
|
||||
@@ -3771,18 +3812,15 @@ func DecodeGatewayQualityWorkRequest(data []byte) (GatewayQualityWorkRequest, er
|
||||
if err := json.Unmarshal(data, &fields); err != nil {
|
||||
return value, err
|
||||
}
|
||||
if raw, ok := fields["acquisition"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "acquisition", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["gateway_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "gateway_id", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["operation_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "operation_id", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["reconnect_sequence"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "reconnect_sequence", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["revision"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "revision", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["session_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "session_id", Code: "required"}}}
|
||||
}
|
||||
@@ -4273,8 +4311,11 @@ func (v GatewayStopWorkRequest) Validate() error {
|
||||
if v.ReconnectSequence != 0 && v.ReconnectSequence < 0 {
|
||||
violations = append(violations, FieldViolation{Field: "reconnect_sequence", Code: "minimum"})
|
||||
}
|
||||
if v.OperationID == "" {
|
||||
violations = append(violations, FieldViolation{Field: "operation_id", Code: "required"})
|
||||
if v.Acquisition == "" {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "required"})
|
||||
}
|
||||
if v.Acquisition != "" && !(v.Acquisition == "poll" || v.Acquisition == "prompt") {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "invalid_value"})
|
||||
}
|
||||
if len(v.OperationID) < 36 && v.OperationID != "" {
|
||||
violations = append(violations, FieldViolation{Field: "operation_id", Code: "min_length"})
|
||||
@@ -4285,6 +4326,9 @@ func (v GatewayStopWorkRequest) Validate() error {
|
||||
if v.OperationID != "" && !validCanonicalUUID(v.OperationID) {
|
||||
violations = append(violations, FieldViolation{Field: "operation_id", Code: "invalid_uuid"})
|
||||
}
|
||||
if v.Acquisition == "poll" && v.OperationID != "" || v.Acquisition == "prompt" && v.OperationID == "" {
|
||||
violations = append(violations, FieldViolation{Field: "acquisition", Code: "invalid_tagged_value"})
|
||||
}
|
||||
if len(violations) > 0 {
|
||||
return ValidationError{Violations: violations}
|
||||
}
|
||||
@@ -4303,12 +4347,12 @@ func DecodeGatewayStopWorkRequest(data []byte) (GatewayStopWorkRequest, error) {
|
||||
if err := json.Unmarshal(data, &fields); err != nil {
|
||||
return value, err
|
||||
}
|
||||
if raw, ok := fields["acquisition"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "acquisition", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["gateway_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "gateway_id", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["operation_id"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "operation_id", Code: "required"}}}
|
||||
}
|
||||
if raw, ok := fields["reconnect_sequence"]; !ok || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
|
||||
return value, ValidationError{Violations: []FieldViolation{{Field: "reconnect_sequence", Code: "required"}}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user