This is an automated email from the ASF dual-hosted git repository.
jason810496 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 665e91fc7d0 Go SDK: Reject a task priority weight outside the int32
range (#76284)
665e91fc7d0 is described below
commit 665e91fc7d01c9064c42a56835006306769a28ae
Author: Y-C <[email protected]>
AuthorDate: Sun Nov 8 21:31:17 2026 +0800
Go SDK: Reject a task priority weight outside the int32 range (#76284)
---
go-sdk/airflow/dag.go | 1 +
go-sdk/airflow/enums.go | 5 ++++-
go-sdk/airflow/serialize.go | 15 +++++++++++++++
go-sdk/airflow/serialize_test.go | 30 ++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/go-sdk/airflow/dag.go b/go-sdk/airflow/dag.go
index 63c606ed45e..c639c160004 100644
--- a/go-sdk/airflow/dag.go
+++ b/go-sdk/airflow/dag.go
@@ -215,6 +215,7 @@ type TaskRef struct {
// - the TaskSpec sets TriggerRule to a value that is not a TriggerRule
constant
// - the TaskSpec sets WeightRule to a value that is not a WeightRule
constant
// - the year of the StartDate or the EndDate of the TaskSpec in UTC is not
from 1 to 9999
+// - the TaskSpec sets PriorityWeight outside the 32-bit range, from
-2147483648 to 2147483647
// - the inputs passed to Inputs do not match the parameters of fn after the
Context
// - the task_id, with the group_ids that prefix it, is longer than 250
characters, or holds a
// character other than a letter, a digit, an underscore, a dash or a dot,
as Python's
diff --git a/go-sdk/airflow/enums.go b/go-sdk/airflow/enums.go
index 709b581a36d..81c89460810 100644
--- a/go-sdk/airflow/enums.go
+++ b/go-sdk/airflow/enums.go
@@ -154,7 +154,7 @@ var (
// checkTaskSpec rejects a TaskSpec whose TriggerRule is not a TriggerRule
constant or whose
// WeightRule is not a WeightRule constant. An empty TriggerRule or WeightRule
is valid and leaves
// that rule unset. checkTaskSpec also rejects a StartDate or an EndDate that
a Python datetime
-// cannot hold.
+// cannot hold, and a PriorityWeight that the priority_weight column of
task_instance cannot hold.
func checkTaskSpec(spec TaskSpec) error {
if err := checkRule("TriggerRule", "trigger rule", spec.TriggerRule,
triggerRules); err != nil {
return err
@@ -162,6 +162,9 @@ func checkTaskSpec(spec TaskSpec) error {
if err := checkRule("WeightRule", "weight rule", spec.WeightRule,
weightRules); err != nil {
return err
}
+ if err := checkPriorityWeight(spec.PriorityWeight); err != nil {
+ return err
+ }
if err := checkTime("airflow.TaskSpec.StartDate", spec.StartDate); err
!= nil {
return err
}
diff --git a/go-sdk/airflow/serialize.go b/go-sdk/airflow/serialize.go
index 0eec1a44a3b..ec9a850ef66 100644
--- a/go-sdk/airflow/serialize.go
+++ b/go-sdk/airflow/serialize.go
@@ -20,6 +20,7 @@ package airflow
import (
"cmp"
"fmt"
+ "math"
"reflect"
"regexp"
"slices"
@@ -355,6 +356,20 @@ func checkTime(field string, t time.Time) error {
return nil
}
+// checkPriorityWeight returns an error for a weight that the 32-bit
priority_weight column of
+// task_instance cannot hold. Python's BaseOperator caps such a weight
instead. A nil weight passes,
+// because it means that the field is unset.
+func checkPriorityWeight(weight *int) error {
+ if weight != nil && (*weight < math.MinInt32 || *weight >
math.MaxInt32) {
+ return fmt.Errorf(
+ "airflow.TaskSpec.PriorityWeight is %d; Airflow takes a
priority weight only "+
+ "from %d to %d",
+ *weight, math.MinInt32, math.MaxInt32,
+ )
+ }
+ return nil
+}
+
// encodeDuration returns d as Python's serializer writes a timedelta: a
number of seconds, to the
// microsecond. A Python timedelta holds nothing finer than a microsecond.
func encodeDuration(d time.Duration) float64 { return
float64(d.Microseconds()) / 1e6 }
diff --git a/go-sdk/airflow/serialize_test.go b/go-sdk/airflow/serialize_test.go
index 4a7bcf96dd8..1e8a6544659 100644
--- a/go-sdk/airflow/serialize_test.go
+++ b/go-sdk/airflow/serialize_test.go
@@ -22,8 +22,10 @@ import (
"encoding/json"
"fmt"
"maps"
+ "math"
"reflect"
"slices"
+ "strconv"
"strings"
"testing"
"time"
@@ -339,6 +341,34 @@ func
TestSerializeWritesAPointerFieldThatHoldsTheZeroValue(t *testing.T) {
)
}
+func TestTaskRejectsAPriorityWeightOutsideTheInt32Range(t *testing.T) {
+ if strconv.IntSize < 64 {
+ t.Skip("requires 64-bit int to hold a weight outside the int32
range")
+ }
+ // int64, not int, so the file still compiles where int is 32 bits.
+ for name, weight := range map[string]int64{
+ "above": math.MaxInt32 + 1,
+ "below": math.MinInt32 - 1,
+ } {
+ t.Run(name, func(t *testing.T) {
+ assert.PanicsWithValue(t,
+ fmt.Sprintf(`airflow.DagRef.Task: task "ping"
of Dag "etl": `+
+ "airflow.TaskSpec.PriorityWeight is %d;
Airflow takes a priority weight "+
+ "only from -2147483648 to 2147483647",
weight),
+ func() { Dag("etl").Task(ping,
TaskSpec{PriorityWeight: ptr(int(weight))}) },
+ )
+ })
+ }
+}
+
+func TestTaskAcceptsAPriorityWeightAtTheInt32Bounds(t *testing.T) {
+ dag := Dag("etl")
+ assert.NotPanics(t, func() {
+ dag.Task(ping, TaskSpec{TaskID: "max", PriorityWeight:
ptr(math.MaxInt32)})
+ dag.Task(ping, TaskSpec{TaskID: "min", PriorityWeight:
ptr(math.MinInt32)})
+ })
+}
+
func TestSerializeWritesTimesAndDurationsToTheMicrosecond(t *testing.T) {
dag := Dag("etl")
dag.Task(ping, TaskSpec{