@@ -19,6 +19,7 @@ import (
19
19
"github.com/cschleiden/go-workflows/backend/metrics"
20
20
"github.com/cschleiden/go-workflows/core"
21
21
"github.com/cschleiden/go-workflows/internal/metrickeys"
22
+ "github.com/cschleiden/go-workflows/internal/workflowerrors"
22
23
"github.com/cschleiden/go-workflows/workflow"
23
24
_ "github.com/go-sql-driver/mysql"
24
25
"github.com/google/uuid"
@@ -146,7 +147,7 @@ func (b *mysqlBackend) CreateWorkflowInstance(ctx context.Context, instance *wor
146
147
defer tx .Rollback ()
147
148
148
149
// 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 {
150
151
return err
151
152
}
152
153
@@ -304,7 +305,13 @@ func (b *mysqlBackend) GetWorkflowInstanceState(ctx context.Context, instance *w
304
305
return state , nil
305
306
}
306
307
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
+
308
315
var parentInstanceID , parentExecutionID * string
309
316
var parentEventID * int64
310
317
if wfi .SubWorkflow () {
@@ -318,9 +325,9 @@ func createInstance(ctx context.Context, tx *sql.Tx, wfi *workflow.Instance, met
318
325
return fmt .Errorf ("marshaling metadata: %w" , err )
319
326
}
320
327
321
- res , err : = tx .ExecContext (
328
+ _ , err = tx .ExecContext (
322
329
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 (?, ?, ?, ?, ?, ?, ?)" ,
324
331
wfi .InstanceID ,
325
332
wfi .ExecutionID ,
326
333
parentInstanceID ,
@@ -333,17 +340,6 @@ func createInstance(ctx context.Context, tx *sql.Tx, wfi *workflow.Instance, met
333
340
return fmt .Errorf ("inserting workflow instance: %w" , err )
334
341
}
335
342
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
-
347
343
return nil
348
344
}
349
345
@@ -624,23 +620,33 @@ func (b *mysqlBackend) CompleteWorkflowTask(
624
620
groupedEvents := history .EventsByWorkflowInstance (workflowEvents )
625
621
626
622
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
633
639
}
634
640
635
- break
641
+ return fmt . Errorf ( "creating sub-workflow instance: %w" , err )
636
642
}
637
643
}
638
644
645
+ // Insert pending events for target instance
639
646
historyEvents := []* history.Event {}
640
647
for _ , m := range events {
641
648
historyEvents = append (historyEvents , m .HistoryEvent )
642
649
}
643
-
644
650
if err := insertPendingEvents (ctx , tx , & targetInstance , historyEvents ); err != nil {
645
651
return fmt .Errorf ("inserting messages: %w" , err )
646
652
}
0 commit comments