Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for non-durable updates shiped on WFT with events #480

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions features/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package features

import (
activity_basic_no_workflow_timeout "github.com/temporalio/features/features/activity/basic_no_workflow_timeout"

activity_cancel_try_cancel "github.com/temporalio/features/features/activity/cancel_try_cancel"
activity_retry_on_error "github.com/temporalio/features/features/activity/retry_on_error"
bugs_go_activity_start_race "github.com/temporalio/features/features/bugs/go/activity_start_race"
Expand Down Expand Up @@ -45,6 +46,7 @@ import (
update_client_interceptor "github.com/temporalio/features/features/update/client_interceptor"
update_deduplication "github.com/temporalio/features/features/update/deduplication"
update_non_durable_reject "github.com/temporalio/features/features/update/non_durable_reject"
update_non_durable_reject_with_events "github.com/temporalio/features/features/update/non_durable_reject_with_events"
update_self "github.com/temporalio/features/features/update/self"
update_task_failure "github.com/temporalio/features/features/update/task_failure"
update_validation_replay "github.com/temporalio/features/features/update/validation_replay"
Expand Down Expand Up @@ -99,6 +101,7 @@ func init() {
update_deduplication.Feature,
update_client_interceptor.Feature,
update_non_durable_reject.Feature,
update_non_durable_reject_with_events.Feature,
update_self.Feature,
update_task_failure.Feature,
update_validation_replay.Feature,
Expand Down
12 changes: 12 additions & 0 deletions features/update/non_durable_reject_with_events/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Update Rejections Do Not Take Up Space In History

When updates are registered with a validation handler and that validation
handler rejects an update, neither the invocation of the update nor the
rejection appear as part of the workflow's history.

# Detailed spec

Update requests don't hit history until they've passed validation on a worker.
Update rejections never hit history. If a workflow task carries _only_ update
requests and all of those requests are rejected, the events related to that
workflow task (i.e. Scheduled/Started/Completed) do not land in history.
92 changes: 92 additions & 0 deletions features/update/non_durable_reject_with_events/feature.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package non_durable_reject

import (
"context"
"fmt"
"time"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/workflow"

"github.com/temporalio/features/features/update/updateutil"
"github.com/temporalio/features/harness/go/harness"
)

const (
step = 2
count = 5
updateAdd = "updateActivity"
)

var Feature = harness.Feature{
Workflows: NonDurableReject,
ExpectRunResult: step * count,
Execute: func(ctx context.Context, runner *harness.Runner) (client.WorkflowRun, error) {
if reason := updateutil.CheckServerSupportsUpdate(ctx, runner.Client); reason != "" {
return nil, runner.Skip(reason)
}
run, err := runner.ExecuteDefault(ctx)
if err != nil {
return nil, err
}

handle, err := runner.Client.UpdateWorkflow(
ctx,
run.GetID(),
run.GetRunID(),
updateAdd,
-1,
)
runner.Require.NoError(err)
var result int
runner.Require.Error(handle.Get(ctx, &result), "expected negative value to be rejected")

for i := 0; i < count; i++ {
handle, err := runner.Client.UpdateWorkflow(
ctx,
run.GetID(),
run.GetRunID(),
updateAdd,
step,
)
runner.Require.NoError(err)
runner.Require.NoError(handle.Get(ctx, &result), "expected non-negative value to be accepted")

handle, err = runner.Client.UpdateWorkflow(
ctx,
run.GetID(),
run.GetRunID(),
updateAdd,
-1,
)
runner.Require.NoError(err)
runner.Require.Error(handle.Get(ctx, &result), "expected negative value to be rejected")
}

updateutil.RequireNoUpdateRejectedEvents(ctx, runner)
return run, nil
},
}

func nonNegative(i int) error {
if i < 0 {
return fmt.Errorf("expected non-negative value (%v)", i)
}
return nil
}

func NonDurableReject(ctx workflow.Context) (int, error) {
counter := 0
if err := workflow.SetUpdateHandlerWithOptions(ctx, updateAdd,
func(ctx workflow.Context, i int) (int, error) {
counter += i
return counter, nil
},
workflow.UpdateHandlerOptions{Validator: nonNegative},
); err != nil {
return 0, err
}

_ = workflow.Sleep(ctx, 4*time.Second)
return counter, nil
}
Loading