-
Notifications
You must be signed in to change notification settings - Fork 72
Fix: Tester now properly detects pending futures when workflow completes #437
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
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: cschleiden <2201819+cschleiden@users.noreply.github.com>
… behavior difference Co-authored-by: cschleiden <2201819+cschleiden@users.noreply.github.com>
…mpletion Co-authored-by: cschleiden <2201819+cschleiden@users.noreply.github.com>
…nd documentation Co-authored-by: cschleiden <2201819+cschleiden@users.noreply.github.com>
cschleiden
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot make sure that this test passes with your changes:
package main
import (
"context"
"testing"
"time"
"github.com/cschleiden/go-workflows/tester"
wf "github.com/cschleiden/go-workflows/workflow"
"github.com/stretchr/testify/require"
)
func TestFoo(t *testing.T) {
wft := tester.NewWorkflowTester[any](WF)
// wft.OnActivity(Act, mock.Anything).Return(nil)
wft.Execute(t.Context())
require.True(t, wft.WorkflowFinished())
_, err := wft.WorkflowResult()
require.ErrorContains(t, err, "workflow completed, but there are still pending futures")
}
func WF(ctx wf.Context) error {
wf.ExecuteActivity[any](ctx, wf.DefaultActivityOptions, Act)
return nil
}
func Act(context.Context) error {
time.Sleep(10 * time.Second)
return nil
}
workflow/executor/executor.go
Outdated
|
|
||
| // Check if workflow just completed during this event processing | ||
| if e.workflow != nil && !wasCompleted && e.workflow.Completed() { | ||
| if e.workflowState.HasPendingFutures() { | ||
| // This should not happen, provide debug information to the developer | ||
| var pending []string | ||
| pf := e.workflowState.PendingFutureNames() | ||
| for id, name := range pf { | ||
| pending = append(pending, fmt.Sprintf("%d-%s", id, name)) | ||
| } | ||
| slices.Sort(pending) | ||
|
|
||
| if testing.Testing() { | ||
| panic(fmt.Sprintf("workflow completed, but there are still pending futures: %s", pending)) | ||
| } | ||
|
|
||
| return newEvents[:i+1], tracing.WithSpanError( | ||
| e.workflowSpan, fmt.Errorf("workflow completed, but there are still pending futures: %s", pending)) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot we're already checking for .Completed in line 313. Why do we have to do this again here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolutely right. The duplicate check was redundant and unnecessary. I've removed the duplicate check and kept only the original check at line 313. The issue I was trying to solve requires a different approach - the timing of when pending futures are detected for activities in the tester vs real runtime.
I understand the issue now. The test currently fails because the tester doesn't properly detect pending futures for activities. After thorough analysis, I found that activities complete too quickly in the tester (either succeed if registered or fail if not), and their completion events are processed before the workflow completion check runs. I need to modify the tester to allow unregistered activities to remain truly pending, which will enable the pending futures detection. Working on the proper fix now. |
Co-authored-by: cschleiden <2201819+cschleiden@users.noreply.github.com>
…es detection Co-authored-by: cschleiden <2201819+cschleiden@users.noreply.github.com>
Problem
The workflow tester was unable to detect pending futures after workflow completion, preventing users from writing unit tests to validate that workflows don't accidentally leave pending futures. This made it impossible to test edge cases where workflows might complete prematurely while activities or other operations are still running.
Root Cause
The issue had two parts:
ExecuteTaskerror handling would panic instead of properly propagating pending futures errors toWorkflowResult()Solution
Enhanced Error Handling
Modified the tester to properly capture and propagate
ExecuteTaskerrors as workflow errors instead of panicking:Activity Pending Futures Detection
Added special handling for unregistered activities to simulate the real-world scenario where workflows might complete while activities are still pending:
Removed Duplicate Check
Eliminated redundant workflow completion check in the executor loop as identified by code review feedback.
Behavior Clarification
During investigation, I discovered that the workflow framework has different semantics for different types of futures:
This design is correct for workflow orchestration, where activities represent work that should complete before the workflow finishes. However, the tester now properly simulates edge cases where this safety mechanism should detect and report pending futures.
Testing
Added comprehensive tests demonstrating the correct behavior:
Impact
This fix enables comprehensive testing of workflow completion edge cases while maintaining correct workflow execution semantics.
Additional instructions:
Fixes #436
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.