Skip to content

Commit e51b36c

Browse files
committed
Merge branch 'master' into verkle-support
2 parents f3bd778 + b284c7e commit e51b36c

File tree

11 files changed

+108
-46
lines changed

11 files changed

+108
-46
lines changed

pkg/coordinator/tasks/check_clients_are_healthy/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ These are the default settings for the `check_clients_are_healthy` task:
3636
skipExecutionCheck: false
3737
expectUnhealthy: false
3838
minClientCount: 0
39-
```
39+
```

pkg/coordinator/tasks/check_consensus_proposer_duty/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ The `check_consensus_proposer_duty` task is designed to check for a specific pro
1111
- **`validatorIndex`**:\
1212
The index of a specific validator to be checked. If this is set, the task focuses on the validator with this index. If it is `null`, the task does not filter by a specific validator index.
1313

14+
- **`minSlotDistance`**:\
15+
The minimum slot distance from the current slot at which to start checking for the validator's proposer duty. A value of 0 indicates the current slot.
16+
1417
- **`maxSlotDistance`**:\
1518
The maximum number of slots (individual time periods in the blockchain) within which the validator is expected to propose a block. The task succeeds if a matching validator is scheduled for block proposal within this slot distance.
1619

pkg/coordinator/tasks/check_consensus_proposer_duty/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package checkconsensusproposerduty
33
type Config struct {
44
ValidatorNamePattern string `yaml:"validatorNamePattern" json:"validatorNamePattern"`
55
ValidatorIndex *uint64 `yaml:"validatorIndex" json:"validatorIndex"`
6+
MinSlotDistance uint64 `yaml:"minSlotDistance" json:"minSlotDistance"`
67
MaxSlotDistance uint64 `yaml:"maxSlotDistance" json:"maxSlotDistance"`
78
FailOnCheckMiss bool `yaml:"failOnCheckMiss" json:"failOnCheckMiss"`
89
}

pkg/coordinator/tasks/check_consensus_proposer_duty/task.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ func (t *Task) runProposerDutyCheck(slot uint64) bool {
182182
}
183183
}
184184

185+
if t.config.MinSlotDistance > 0 && slot-1-currentSlot < t.config.MinSlotDistance {
186+
t.logger.Errorf("slot %v check failed: matching duty too early: in %v slots, min distance: %v", slot, slot-1-currentSlot, t.config.MinSlotDistance)
187+
return false
188+
}
189+
185190
return true
186191
}
187192
}

pkg/coordinator/tasks/run_task_matrix/task.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,25 +127,34 @@ func (t *Task) Execute(ctx context.Context) error {
127127

128128
t.taskCtx = taskCtx
129129

130-
var taskWaitChan chan bool
131-
if !t.config.RunConcurrent {
132-
taskWaitChan = make(chan bool, 1)
133-
}
130+
var currentTaskWaitChan, previousTaskWaitChan chan bool
134131

135132
// start child tasks
136133
for i := range t.tasks {
137134
taskWaitGroup.Add(1)
138135

136+
if !t.config.RunConcurrent {
137+
previousTaskWaitChan = currentTaskWaitChan
138+
currentTaskWaitChan = make(chan bool)
139+
}
140+
139141
t.taskIdxMap[t.tasks[i]] = i
140142

141-
go func(i int) {
143+
go func(i int, taskWaitChan, prevTaskWaitChan chan bool) {
142144
defer taskWaitGroup.Done()
143145

144-
if taskWaitChan != nil {
145-
taskWaitChan <- true
146-
defer func() {
147-
<-taskWaitChan
148-
}()
146+
if !t.config.RunConcurrent {
147+
if prevTaskWaitChan != nil {
148+
// wait for previous task to be executed
149+
select {
150+
case <-prevTaskWaitChan:
151+
case <-ctx.Done():
152+
return
153+
}
154+
}
155+
156+
// allow next task to run once this finishes
157+
defer close(taskWaitChan)
149158
}
150159

151160
task := t.tasks[i]
@@ -158,7 +167,7 @@ func (t *Task) Execute(ctx context.Context) error {
158167

159168
//nolint:errcheck // ignore
160169
t.ctx.Scheduler.ExecuteTask(taskCtx, task, t.watchChildTask)
161-
}(i)
170+
}(i, currentTaskWaitChan, previousTaskWaitChan)
162171
}
163172

164173
// watch result updates

pkg/coordinator/tasks/run_task_options/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ The `run_task_options` task is designed to execute a single task with configurab
88
- **`task`**:\
99
The task to be executed. This is defined following the standard task definition format.
1010

11+
- **`propagateResult`**:\
12+
This setting controls how the result of the child task influences the result of the `run_task_options` task. If set to `true`, any change in the result of the child task (success or failure) is immediately reflected in the result of the parent `run_task_options` task. If `false`, the child task's result is only propagated to the parent task after the child task has completed its execution.
13+
1114
- **`exitOnResult`**:\
1215
If set to `true`, the task will cancel the child task as soon as it sets a result, whether it is "success" or "failure." This option is useful for scenarios where immediate response to the child task's result is necessary.
1316

@@ -20,6 +23,12 @@ The `run_task_options` task is designed to execute a single task with configurab
2023
- **`ignoreFailure`**:\
2124
When `true`, any failure result from the child task is ignored, and the `run_task_options` task will return a success result instead. This is useful for cases where the child task's failure is an acceptable outcome.
2225

26+
- **`retryOnFailure`**:\
27+
If set to `true`, the task will retry the execution of the child task if it fails, up to the maximum number of retries specified by `maxRetryCount`.
28+
29+
- **`maxRetryCount`**:\
30+
The maximum number of times the child task will be retried if it fails and `retryOnFailure` is true. A value of 0 means no retries.
31+
2332
- **`newVariableScope`**:\
2433
Determines whether to create a new variable scope for the child task. If `false`, the current scope is passed through, allowing the child task to share the same variable context as the `run_task_options` task.
2534

@@ -31,9 +40,12 @@ Default settings for the `run_task_options` task:
3140
- name: run_task_options
3241
config:
3342
task: null
43+
propagateResult: false
3444
exitOnResult: false
3545
invertResult: false
3646
expectFailure: false
3747
ignoreFailure: false
48+
retryOnFailure: false
49+
maxRetryCount: 0
3850
newVariableScope: false
3951
```

pkg/coordinator/tasks/run_task_options/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import (
88

99
type Config struct {
1010
Task *helper.RawMessage `yaml:"task" json:"tasks"`
11+
PropagateResult bool `yaml:"propagateResult" json:"propagateResult"`
1112
ExitOnResult bool `yaml:"exitOnResult" json:"exitOnResult"`
1213
InvertResult bool `yaml:"invertResult" json:"invertResult"`
1314
ExpectFailure bool `yaml:"expectFailure" json:"expectFailure"`
1415
IgnoreFailure bool `yaml:"ignoreFailure" json:"ignoreFailure"`
16+
RetryOnFailure bool `yaml:"retryOnFailure" json:"retryOnFailure"`
17+
MaxRetryCount uint `yaml:"maxRetryCount" json:"maxRetryCount"`
1518
NewVariableScope bool `yaml:"newVariableScope" json:"newVariableScope"`
1619
}
1720

pkg/coordinator/tasks/run_task_options/task.go

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,48 +80,65 @@ func (t *Task) LoadConfig() error {
8080
return err2
8181
}
8282

83-
// init child task
84-
taskOpts, err := t.ctx.Scheduler.ParseTaskOptions(config.Task)
85-
if err != nil {
86-
return fmt.Errorf("failed parsing child task config: %w", err)
87-
}
88-
89-
taskVars := t.ctx.Vars
90-
if config.NewVariableScope {
91-
taskVars = taskVars.NewScope()
92-
}
93-
94-
t.task, err = t.ctx.NewTask(taskOpts, taskVars)
95-
if err != nil {
96-
return fmt.Errorf("failed initializing child task: %w", err)
97-
}
98-
9983
t.config = config
10084

10185
return nil
10286
}
10387

10488
func (t *Task) Execute(ctx context.Context) error {
105-
err := t.ctx.Scheduler.ExecuteTask(ctx, t.task, func(ctx context.Context, cancelFn context.CancelFunc, _ types.Task) {
106-
t.watchTaskResult(ctx, cancelFn)
107-
})
108-
109-
switch {
110-
case t.config.ExpectFailure:
111-
if err == nil {
112-
return fmt.Errorf("child task succeeded, but should have failed")
113-
}
114-
case t.config.IgnoreFailure:
89+
var taskErr error
90+
91+
retryCount := uint(0)
92+
93+
for {
94+
// init child task
95+
taskOpts, err := t.ctx.Scheduler.ParseTaskOptions(t.config.Task)
11596
if err != nil {
116-
t.logger.Warnf("child task failed: %w", err)
97+
return fmt.Errorf("failed parsing child task config: %w", err)
98+
}
99+
100+
taskVars := t.ctx.Vars
101+
if t.config.NewVariableScope {
102+
taskVars = taskVars.NewScope()
117103
}
118-
default:
104+
105+
t.task, err = t.ctx.NewTask(taskOpts, taskVars)
119106
if err != nil {
120-
return fmt.Errorf("child task failed: %w", err)
107+
return fmt.Errorf("failed initializing child task: %w", err)
121108
}
109+
110+
// execute task
111+
taskErr = t.ctx.Scheduler.ExecuteTask(ctx, t.task, func(ctx context.Context, cancelFn context.CancelFunc, _ types.Task) {
112+
t.watchTaskResult(ctx, cancelFn)
113+
})
114+
115+
switch {
116+
case t.config.RetryOnFailure && retryCount < t.config.MaxRetryCount:
117+
if taskErr != nil {
118+
retryCount++
119+
120+
t.logger.Warnf("child task failed: %w (retrying)", taskErr)
121+
122+
continue
123+
}
124+
case t.config.ExpectFailure:
125+
if taskErr == nil {
126+
return fmt.Errorf("child task succeeded, but should have failed")
127+
}
128+
case t.config.IgnoreFailure:
129+
if taskErr != nil {
130+
t.logger.Warnf("child task failed: %w", taskErr)
131+
}
132+
default:
133+
if taskErr != nil {
134+
return fmt.Errorf("child task failed: %w", taskErr)
135+
}
136+
}
137+
138+
break
122139
}
123140

124-
return nil
141+
return taskErr
125142
}
126143

127144
func (t *Task) watchTaskResult(ctx context.Context, cancelFn context.CancelFunc) {
@@ -158,7 +175,9 @@ func (t *Task) watchTaskResult(ctx context.Context, cancelFn context.CancelFunc)
158175
}
159176
}
160177

161-
t.ctx.SetResult(taskResult)
178+
if t.config.PropagateResult {
179+
t.ctx.SetResult(taskResult)
180+
}
162181

163182
if t.config.ExitOnResult {
164183
cancelFn()

pkg/coordinator/tasks/run_tasks/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## `run_tasks` Task
22

33
### Description
4-
The `run_tasks` task is designed for executing a series of tasks sequentially, ensuring each task is completed before starting the next. This setup is essential for tests requiring a specific order of task execution.
4+
The `run_tasks` task executes a series of specified tasks sequentially. This is particularly useful for scenarios where tasks need to be performed in a specific order, with the outcome of one potentially affecting the subsequent ones.
55

66
#### Task Behavior
77
- The task starts the child tasks one after the other in the order they are listed.
@@ -15,6 +15,9 @@ An important aspect of this task is that it cancels tasks once they return a res
1515
- **`tasks`**:\
1616
An array of tasks to be executed one after the other. Each task is defined according to the standard task structure.
1717

18+
- **`stopChildOnResult`**:\
19+
If set to `true`, each child task in the sequence is stopped as soon as it sets a result (either "success" or "failure"). This ensures that once a task has reached a outcome, it does not continue to run unnecessarily, allowing the next task in the sequence to commence.
20+
1821
- **`expectFailure`**:\
1922
If set to `true`, this option expects each task in the sequence to fail. The task sequence stops with a "failure" result if any task does not fail as expected.
2023

@@ -29,6 +32,7 @@ Default settings for the `run_tasks` task:
2932
- name: run_tasks
3033
config:
3134
tasks: []
35+
stopChildOnResult: true
3236
expectFailure: false
3337
continueOnFailure: false
3438
```

pkg/coordinator/tasks/run_tasks/config.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import (
88

99
type Config struct {
1010
Tasks []helper.RawMessage `yaml:"tasks" json:"tasks"`
11+
StopChildOnResult bool `yaml:"stopChildOnResult" json:"stopChildOnResult"`
1112
ExpectFailure bool `yaml:"expectFailure" json:"expectFailure"`
1213
ContinueOnFailure bool `yaml:"continueOnFailure" json:"continueOnFailure"`
1314
}
1415

1516
func DefaultConfig() Config {
1617
return Config{
17-
Tasks: []helper.RawMessage{},
18+
Tasks: []helper.RawMessage{},
19+
StopChildOnResult: true,
1820
}
1921
}
2022

0 commit comments

Comments
 (0)