@@ -73,8 +73,29 @@ func (rb *redisBackend) GetWorkflowInstanceState(ctx context.Context, instance *
73
73
return instanceState .State , nil
74
74
}
75
75
76
- func (rb * redisBackend ) CancelWorkflowInstance (ctx context.Context , instance * core.WorkflowInstance ) error {
77
- panic ("unimplemented" )
76
+ func (rb * redisBackend ) CancelWorkflowInstance (ctx context.Context , instance * core.WorkflowInstance , event * history.Event ) error {
77
+ // Recursively, find any sub-workflow instance to cancel
78
+ toCancel := make ([]* core.WorkflowInstance , 0 )
79
+ toCancel = append (toCancel , instance )
80
+ for len (toCancel ) > 0 {
81
+ instance := toCancel [0 ]
82
+ toCancel = toCancel [1 :]
83
+
84
+ // Cancel instance
85
+ if err := rb .addWorkflowInstanceEvent (ctx , instance , event ); err != nil {
86
+ return errors .Wrap (err , "could not add cancellation event to workflow instance" )
87
+ }
88
+
89
+ // Find sub-workflows
90
+ subInstances , err := subWorkflowInstances (ctx , rb .rdb , instance )
91
+ if err != nil {
92
+ return err
93
+ }
94
+
95
+ toCancel = append (toCancel , subInstances ... )
96
+ }
97
+
98
+ return nil
78
99
}
79
100
80
101
type instanceState struct {
@@ -105,6 +126,22 @@ func createInstance(ctx context.Context, rdb redis.UniversalClient, instance *co
105
126
return errors .New ("workflow instance already exists" )
106
127
}
107
128
129
+ if instance .SubWorkflow () {
130
+ instanceStr , err := json .Marshal (instance )
131
+ if err != nil {
132
+ return err
133
+ }
134
+
135
+ c , err := rdb .RPush (ctx , subInstanceKey (instance .ParentInstanceID ), instanceStr ).Result ()
136
+ if err != nil {
137
+ return errors .Wrap (err , "could not track sub-workflow" )
138
+ }
139
+
140
+ if c != 1 {
141
+ return errors .New ("could not track sub-workflow" )
142
+ }
143
+ }
144
+
108
145
return nil
109
146
}
110
147
@@ -137,5 +174,37 @@ func readInstance(ctx context.Context, rdb redis.UniversalClient, instanceID str
137
174
return nil , errors .Wrap (err , "could not unmarshal instance state" )
138
175
}
139
176
177
+ if state .Instance .SubWorkflow () && state .State == backend .WorkflowStateFinished {
178
+ instanceStr , err := json .Marshal (state .Instance )
179
+ if err != nil {
180
+ return nil , err
181
+ }
182
+
183
+ if err := rdb .LRem (ctx , subInstanceKey (state .Instance .ParentInstanceID ), 1 , instanceStr ).Err (); err != nil {
184
+ return nil , errors .Wrap (err , "could not remove sub-workflow from parent list" )
185
+ }
186
+ }
187
+
140
188
return & state , nil
141
189
}
190
+
191
+ func subWorkflowInstances (ctx context.Context , rdb redis.UniversalClient , instance * core.WorkflowInstance ) ([]* core.WorkflowInstance , error ) {
192
+ key := subInstanceKey (instance .InstanceID )
193
+ res , err := rdb .LRange (ctx , key , 0 , - 1 ).Result ()
194
+ if err != nil {
195
+ return nil , errors .Wrap (err , "could not read sub-workflow instances" )
196
+ }
197
+
198
+ var instances []* core.WorkflowInstance
199
+
200
+ for _ , instanceStr := range res {
201
+ var instance core.WorkflowInstance
202
+ if err := json .Unmarshal ([]byte (instanceStr ), & instance ); err != nil {
203
+ return nil , errors .Wrap (err , "could not unmarshal sub-workflow instance" )
204
+ }
205
+
206
+ instances = append (instances , & instance )
207
+ }
208
+
209
+ return instances , nil
210
+ }
0 commit comments