Hi everyone,
I’m trying to standardize input and output across all my workflows using a common struct, something like this:
type (
RawJSON = json.RawMessage
NodeID string
WorkflowInput = struct {
Data RawJSON `json:"data,omitempty"` // Input to any workflow execution
Metadata RawJSON `json:"metadata,omitempty"` // Additional metadata for the workflow execution
// previous workflow execution output
Previous map[NodeID]RawJSON `json:"previous,omitempty"` // Previous workflow execution output, keyed by node ID
}
WorkflowOutput struct {
Data RawJSON `json:"data,omitempty"` // Output of the workflow execution
Error string `json:"error,omitempty"` // Error message if the workflow failed
Metadata RawJSON `json:"metadata,omitempty"` // Additional metadata about the workflow execution
}
)
type CommandSetWorkflowInput struct {
Commands []oapi.Command
}
func CommandSetWorkflow(
ctx workflow.Context,
wfInput vw.WorkflowInput,
) (vw.WorkflowOutput, error) {
var out vw.WorkflowOutput
var input CommandSetWorkflowInput
if err := json.Unmarshal(wfInput.Data, &input); err != nil {
return out, temporal.NewNonRetryableApplicationError(
"failed to unmarshal workflow input", "InvalidInput", err,
)
}
return out, nil
}
The issue is: workflowcheck
complains that json.Unmarshal
is a non-deterministic function.
So my questions are:
- Is there a deterministic way to decode arbitrary JSON into a specific struct like this within a workflow?
- If not, what’s the recommended pattern for handling generic workflow input/output while still keeping workflow code deterministic?
Appreciate any guidance or best practices from people who’ve tackled something similar.