Files
tasks/chasm/lib/workflow/workflow.go
zeekay 5a601d081b rebrand: go.temporal.io/server -> github.com/hanzoai/tasks
Full module path rebrand from Temporal to Hanzo Tasks:
- go.mod module: github.com/hanzoai/tasks
- All internal Go imports updated (1906 files)
- cmd/server renamed to cmd/tasksd
- Binary name: tasksd (was temporal-server)
- Docker images: hanzoai/tasks (was temporalio/server)
- README rewritten with Hanzo Tasks branding
- LLM.md created with integration notes
- Makefile, goreleaser, CI workflows updated
- go.temporal.io/sdk and go.temporal.io/api imports preserved (separate repos)

Fork of Temporal.io (MIT license).
2026-03-19 10:36:40 -07:00

124 lines
3.9 KiB
Go

package workflow
import (
"fmt"
commonpb "go.temporal.io/api/common/v1"
"go.temporal.io/api/serviceerror"
"github.com/hanzoai/tasks/chasm"
"github.com/hanzoai/tasks/chasm/lib/callback"
callbackspb "github.com/hanzoai/tasks/chasm/lib/callback/gen/callbackpb/v1"
"github.com/hanzoai/tasks/common/nexus/nexusrpc"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
)
type Workflow struct {
chasm.UnimplementedComponent
// For now, workflow state is managed by mutable_state_impl, not CHASM engine, leaving it empty as CHASM expects a
// state object.
*emptypb.Empty
// MSPointer is a special in-memory field for accessing the underlying mutable state.
chasm.MSPointer
// Callbacks map is used to store the callbacks for the workflow.
Callbacks chasm.Map[string, *callback.Callback]
}
func NewWorkflow(
_ chasm.MutableContext,
msPointer chasm.MSPointer,
) *Workflow {
return &Workflow{
MSPointer: msPointer,
}
}
func (w *Workflow) LifecycleState(
_ chasm.Context,
) chasm.LifecycleState {
// NOTE: closeTransactionHandleRootLifecycleChange() is bypassed in tree.go
//
// NOTE: detached mode is not implemented yet, so always return Running here.
// Otherwise, tasks for callback component can't be executed after workflow is closed.
return chasm.LifecycleStateRunning
}
// ProcessCloseCallbacks triggers "WorkflowClosed" callbacks using the CHASM implementation.
// It iterates through all callbacks and schedules WorkflowClosed ones that are in STANDBY state.
func (w *Workflow) ProcessCloseCallbacks(ctx chasm.MutableContext) error {
// Iterate through all callbacks and schedule WorkflowClosed ones
for _, field := range w.Callbacks {
cb := field.Get(ctx)
// Only process callbacks in STANDBY state (not already triggered)
if cb.Status != callbackspb.CALLBACK_STATUS_STANDBY {
continue
}
// Trigger the callback by transitioning to SCHEDULED state
if err := callback.TransitionScheduled.Apply(cb, ctx, callback.EventScheduled{}); err != nil {
return err
}
}
return nil
}
// AddCompletionCallbacks creates completion callbacks using the CHASM implementation.
// maxCallbacksPerWorkflow is the configured maximum number of callbacks allowed per workflow.
func (w *Workflow) AddCompletionCallbacks(
ctx chasm.MutableContext,
eventTime *timestamppb.Timestamp,
requestID string,
completionCallbacks []*commonpb.Callback,
maxCallbacksPerWorkflow int,
) error {
// Check CHASM max callbacks limit
currentCallbackCount := len(w.Callbacks)
if len(completionCallbacks)+currentCallbackCount > maxCallbacksPerWorkflow {
return serviceerror.NewFailedPreconditionf(
"cannot attach more than %d callbacks to a workflow (%d callbacks already attached)",
maxCallbacksPerWorkflow,
currentCallbackCount,
)
}
// Initialize map if needed
if w.Callbacks == nil {
w.Callbacks = make(chasm.Map[string, *callback.Callback], len(completionCallbacks))
}
// Add each callback
for idx, cb := range completionCallbacks {
chasmCB := &callbackspb.Callback{
Links: cb.GetLinks(),
}
switch variant := cb.Variant.(type) {
case *commonpb.Callback_Nexus_:
chasmCB.Variant = &callbackspb.Callback_Nexus_{
Nexus: &callbackspb.Callback_Nexus{
Url: variant.Nexus.GetUrl(),
Header: variant.Nexus.GetHeader(),
},
}
default:
return fmt.Errorf("unsupported callback variant: %T", variant)
}
id := fmt.Sprintf("%s-%d", requestID, idx)
// Create and add callback
callbackObj := callback.NewCallback(requestID, eventTime, &callbackspb.CallbackState{}, chasmCB)
w.Callbacks[id] = chasm.NewComponentField(ctx, callbackObj)
}
return nil
}
func (w *Workflow) GetNexusCompletion(
ctx chasm.Context,
requestID string,
) (nexusrpc.CompleteOperationOptions, error) {
// Retrieve the completion data from the underlying mutable state via MSPointer
return w.MSPointer.GetNexusCompletion(ctx, requestID)
}