mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
## What changed?
<!-- Describe what has changed in this PR -->
Remove license header from every file. Because it is really hard to
follow in this PR here is the summary:
1. License header is removed from all `.go` and `.proto` files
:fireworks::fireworks:🎆.
2. `LICENSE` file in the root directory has only Temporal and Uber
copyrights.
3. 5 other `LICENSE` files added to the packages which have copyrights
different from Temporal and Uber: Datadog, Xargin, "Mat Ryer, Tyler
Bunnell and contributors".
4. `license_file` flag is removed from all code generation tools.
5. `copyright_file` flag is removed from `go:generate mockgen`
directive.
6. All copyright related targets are removed from `Makefile`.
7. Updated Temporal copyright year to 2025 everywhere.
## Why?
<!-- Tell your future self why have you made these changes -->
I double checked with legal department that it is not needed to have
license header in every file. One file per repo is enough. I put all
copyrights to the root `LICENSE` file and removed header from all other
files. Also updated tools and `Makefile`.
195 lines
5.9 KiB
Go
195 lines
5.9 KiB
Go
package callbacks_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
enumsspb "go.temporal.io/server/api/enums/v1"
|
|
persistencespb "go.temporal.io/server/api/persistence/v1"
|
|
"go.temporal.io/server/common"
|
|
"go.temporal.io/server/common/backoff"
|
|
"go.temporal.io/server/components/callbacks"
|
|
"go.temporal.io/server/service/history/hsm"
|
|
)
|
|
|
|
func TestValidTransitions(t *testing.T) {
|
|
// Setup
|
|
currentTime := time.Now().UTC()
|
|
callback := callbacks.Callback{
|
|
&persistencespb.CallbackInfo{
|
|
Callback: &persistencespb.Callback{
|
|
Variant: &persistencespb.Callback_Nexus_{
|
|
Nexus: &persistencespb.Callback_Nexus{
|
|
Url: "http://address:666/path/to/callback?query=string",
|
|
},
|
|
},
|
|
},
|
|
State: enumsspb.CALLBACK_STATE_SCHEDULED,
|
|
},
|
|
}
|
|
// AttemptFailed
|
|
out, err := callbacks.TransitionAttemptFailed.Apply(callback, callbacks.EventAttemptFailed{
|
|
Time: currentTime,
|
|
Err: fmt.Errorf("test"),
|
|
RetryPolicy: backoff.NewExponentialRetryPolicy(time.Second),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Assert info object is updated
|
|
require.Equal(t, enumsspb.CALLBACK_STATE_BACKING_OFF, callback.State())
|
|
require.Equal(t, int32(1), callback.Attempt)
|
|
require.Equal(t, "test", callback.LastAttemptFailure.Message)
|
|
require.False(t, callback.LastAttemptFailure.GetApplicationFailureInfo().NonRetryable)
|
|
require.Equal(t, currentTime, callback.LastAttemptCompleteTime.AsTime())
|
|
dt := currentTime.Add(time.Second).Sub(callback.NextAttemptScheduleTime.AsTime())
|
|
require.True(t, dt < time.Millisecond*200)
|
|
|
|
// Assert backoff task is generated
|
|
require.Equal(t, 1, len(out.Tasks))
|
|
boTask := out.Tasks[0].(callbacks.BackoffTask)
|
|
require.Equal(t, callback.NextAttemptScheduleTime.AsTime(), boTask.Deadline())
|
|
|
|
// Rescheduled
|
|
out, err = callbacks.TransitionRescheduled.Apply(callback, callbacks.EventRescheduled{})
|
|
require.NoError(t, err)
|
|
|
|
// Assert info object is updated only where needed
|
|
require.Equal(t, enumsspb.CALLBACK_STATE_SCHEDULED, callback.State())
|
|
require.Equal(t, int32(1), callback.Attempt)
|
|
require.Equal(t, "test", callback.LastAttemptFailure.Message)
|
|
// Remains unmodified
|
|
require.Equal(t, currentTime, callback.LastAttemptCompleteTime.AsTime())
|
|
require.Nil(t, callback.NextAttemptScheduleTime)
|
|
|
|
// Assert callback task is generated
|
|
require.Equal(t, 1, len(out.Tasks))
|
|
cbTask := out.Tasks[0].(callbacks.InvocationTask)
|
|
require.Equal(t, "http://address:666", cbTask.Destination())
|
|
|
|
// Store the pre-succeeded state to test Failed later
|
|
dup := callbacks.Callback{common.CloneProto(callback.CallbackInfo)}
|
|
|
|
// Succeeded
|
|
currentTime = currentTime.Add(time.Second)
|
|
out, err = callbacks.TransitionSucceeded.Apply(callback, callbacks.EventSucceeded{Time: currentTime})
|
|
require.NoError(t, err)
|
|
|
|
// Assert info object is updated only where needed
|
|
require.Equal(t, enumsspb.CALLBACK_STATE_SUCCEEDED, callback.State())
|
|
require.Equal(t, int32(2), callback.Attempt)
|
|
require.Nil(t, callback.LastAttemptFailure)
|
|
require.Equal(t, currentTime, callback.LastAttemptCompleteTime.AsTime())
|
|
require.Nil(t, callback.NextAttemptScheduleTime)
|
|
|
|
// Assert no additional tasks are generated
|
|
require.Equal(t, 0, len(out.Tasks))
|
|
|
|
// Reset back to scheduled
|
|
callback = dup
|
|
// Increment the time to ensure it's updated in the transition
|
|
currentTime = currentTime.Add(time.Second)
|
|
|
|
// failed
|
|
out, err = callbacks.TransitionFailed.Apply(callback, callbacks.EventFailed{Time: currentTime, Err: fmt.Errorf("failed")})
|
|
require.NoError(t, err)
|
|
|
|
// Assert info object is updated only where needed
|
|
require.Equal(t, enumsspb.CALLBACK_STATE_FAILED, callback.State())
|
|
require.Equal(t, int32(2), callback.Attempt)
|
|
require.Equal(t, "failed", callback.LastAttemptFailure.Message)
|
|
require.True(t, callback.LastAttemptFailure.GetApplicationFailureInfo().NonRetryable)
|
|
require.Equal(t, currentTime, callback.LastAttemptCompleteTime.AsTime())
|
|
require.Nil(t, callback.NextAttemptScheduleTime)
|
|
|
|
// Assert no additional tasks are generated
|
|
require.Equal(t, 0, len(out.Tasks))
|
|
}
|
|
|
|
func TestCompareState(t *testing.T) {
|
|
reg := hsm.NewRegistry()
|
|
require.NoError(t, callbacks.RegisterStateMachine(reg))
|
|
def, ok := reg.Machine(callbacks.StateMachineType)
|
|
require.True(t, ok)
|
|
|
|
cases := []struct {
|
|
name string
|
|
s1, s2 enumsspb.CallbackState
|
|
attempts1, attempts2 int32
|
|
sign int
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "standby < scheduled",
|
|
s1: enumsspb.CALLBACK_STATE_STANDBY,
|
|
s2: enumsspb.CALLBACK_STATE_SCHEDULED,
|
|
sign: -1,
|
|
},
|
|
{
|
|
name: "scheduled = scheduled",
|
|
s1: enumsspb.CALLBACK_STATE_SCHEDULED,
|
|
s2: enumsspb.CALLBACK_STATE_SCHEDULED,
|
|
attempts1: 2,
|
|
attempts2: 2,
|
|
sign: 0,
|
|
},
|
|
{
|
|
name: "succeeded not comparable to failed",
|
|
s1: enumsspb.CALLBACK_STATE_SUCCEEDED,
|
|
s2: enumsspb.CALLBACK_STATE_FAILED,
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "backing off < failed",
|
|
s1: enumsspb.CALLBACK_STATE_BACKING_OFF,
|
|
s2: enumsspb.CALLBACK_STATE_FAILED,
|
|
sign: -1,
|
|
},
|
|
{
|
|
name: "scheduled > backing off",
|
|
s1: enumsspb.CALLBACK_STATE_SCHEDULED,
|
|
s2: enumsspb.CALLBACK_STATE_BACKING_OFF,
|
|
sign: 1,
|
|
},
|
|
{
|
|
name: "backing off < scheduled with greater attempt",
|
|
s1: enumsspb.CALLBACK_STATE_BACKING_OFF,
|
|
s2: enumsspb.CALLBACK_STATE_SCHEDULED,
|
|
attempts2: 1,
|
|
sign: -1,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
tc := tc
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
s1 := callbacks.Callback{
|
|
CallbackInfo: &persistencespb.CallbackInfo{
|
|
State: tc.s1,
|
|
Attempt: tc.attempts1,
|
|
},
|
|
}
|
|
s2 := callbacks.Callback{
|
|
CallbackInfo: &persistencespb.CallbackInfo{
|
|
State: tc.s2,
|
|
Attempt: tc.attempts2,
|
|
},
|
|
}
|
|
res, err := def.CompareState(s1, s2)
|
|
if tc.expectError {
|
|
require.Error(t, err)
|
|
return
|
|
}
|
|
require.NoError(t, err)
|
|
if tc.sign == 0 {
|
|
require.Equal(t, 0, res)
|
|
} else if tc.sign > 0 {
|
|
require.Greater(t, res, 0)
|
|
} else {
|
|
require.Greater(t, 0, res)
|
|
}
|
|
})
|
|
}
|
|
}
|