@@ -19,6 +19,7 @@ import (
1919 "github.com/cschleiden/go-workflows/backend/metrics"
2020 "github.com/cschleiden/go-workflows/core"
2121 "github.com/cschleiden/go-workflows/internal/metrickeys"
22+ "github.com/cschleiden/go-workflows/internal/workflowerrors"
2223 "github.com/cschleiden/go-workflows/workflow"
2324 _ "github.com/go-sql-driver/mysql"
2425 "github.com/google/uuid"
@@ -146,7 +147,7 @@ func (b *mysqlBackend) CreateWorkflowInstance(ctx context.Context, instance *wor
146147 defer tx .Rollback ()
147148
148149 // Create workflow instance
149- if err := createInstance (ctx , tx , instance , event .Attributes .(* history.ExecutionStartedAttributes ).Metadata , false ); err != nil {
150+ if err := createInstance (ctx , tx , instance , event .Attributes .(* history.ExecutionStartedAttributes ).Metadata ); err != nil {
150151 return err
151152 }
152153
@@ -304,7 +305,13 @@ func (b *mysqlBackend) GetWorkflowInstanceState(ctx context.Context, instance *w
304305 return state , nil
305306}
306307
307- func createInstance (ctx context.Context , tx * sql.Tx , wfi * workflow.Instance , metadata * workflow.Metadata , ignoreDuplicate bool ) error {
308+ func createInstance (ctx context.Context , tx * sql.Tx , wfi * workflow.Instance , metadata * workflow.Metadata ) error {
309+ // Check for existing instance
310+ if err := tx .QueryRowContext (ctx , "SELECT 1 FROM `instances` WHERE instance_id = ? AND state = ? LIMIT 1" , wfi .InstanceID , core .WorkflowInstanceStateActive ).
311+ Scan (new (int )); err != sql .ErrNoRows {
312+ return backend .ErrInstanceAlreadyExists
313+ }
314+
308315 var parentInstanceID , parentExecutionID * string
309316 var parentEventID * int64
310317 if wfi .SubWorkflow () {
@@ -318,9 +325,9 @@ func createInstance(ctx context.Context, tx *sql.Tx, wfi *workflow.Instance, met
318325 return fmt .Errorf ("marshaling metadata: %w" , err )
319326 }
320327
321- res , err : = tx .ExecContext (
328+ _ , err = tx .ExecContext (
322329 ctx ,
323- "INSERT IGNORE INTO `instances` (instance_id, execution_id, parent_instance_id, parent_execution_id, parent_schedule_event_id, metadata, state) VALUES (?, ?, ?, ?, ?, ?, ?)" ,
330+ "INSERT INTO `instances` (instance_id, execution_id, parent_instance_id, parent_execution_id, parent_schedule_event_id, metadata, state) VALUES (?, ?, ?, ?, ?, ?, ?)" ,
324331 wfi .InstanceID ,
325332 wfi .ExecutionID ,
326333 parentInstanceID ,
@@ -333,17 +340,6 @@ func createInstance(ctx context.Context, tx *sql.Tx, wfi *workflow.Instance, met
333340 return fmt .Errorf ("inserting workflow instance: %w" , err )
334341 }
335342
336- if ! ignoreDuplicate {
337- rows , err := res .RowsAffected ()
338- if err != nil {
339- return err
340- }
341-
342- if rows != 1 {
343- return backend .ErrInstanceAlreadyExists
344- }
345- }
346-
347343 return nil
348344}
349345
@@ -624,23 +620,33 @@ func (b *mysqlBackend) CompleteWorkflowTask(
624620 groupedEvents := history .EventsByWorkflowInstance (workflowEvents )
625621
626622 for targetInstance , events := range groupedEvents {
627- for _ , m := range events {
628- if m .HistoryEvent .Type == history .EventType_WorkflowExecutionStarted {
629- a := m .HistoryEvent .Attributes .(* history.ExecutionStartedAttributes )
630- // Create new instance
631- if err := createInstance (ctx , tx , m .WorkflowInstance , a .Metadata , true ); err != nil {
632- return err
623+ // Are we creating a new sub-workflow instance?
624+ m := events [0 ]
625+ if m .HistoryEvent .Type == history .EventType_WorkflowExecutionStarted {
626+ a := m .HistoryEvent .Attributes .(* history.ExecutionStartedAttributes )
627+ // Create new instance
628+ if err := createInstance (ctx , tx , m .WorkflowInstance , a .Metadata ); err != nil {
629+ if err == backend .ErrInstanceAlreadyExists {
630+ if err := insertPendingEvents (ctx , tx , instance , []* history.Event {
631+ history .NewPendingEvent (time .Now (), history .EventType_SubWorkflowFailed , & history.SubWorkflowFailedAttributes {
632+ Error : workflowerrors .FromError (backend .ErrInstanceAlreadyExists ),
633+ }, history .ScheduleEventID (m .WorkflowInstance .ParentEventID )),
634+ }); err != nil {
635+ return fmt .Errorf ("inserting sub-workflow failed event: %w" , err )
636+ }
637+
638+ continue
633639 }
634640
635- break
641+ return fmt . Errorf ( "creating sub-workflow instance: %w" , err )
636642 }
637643 }
638644
645+ // Insert pending events for target instance
639646 historyEvents := []* history.Event {}
640647 for _ , m := range events {
641648 historyEvents = append (historyEvents , m .HistoryEvent )
642649 }
643-
644650 if err := insertPendingEvents (ctx , tx , & targetInstance , historyEvents ); err != nil {
645651 return fmt .Errorf ("inserting messages: %w" , err )
646652 }
0 commit comments