Skip to content

Commit e98bd6f

Browse files
author
Frank Martinez
authored
iterate/doWhile config fix; update doc (#111)
* iterate/doWhile config fix; update doc * add iterator to test json * temporarily remove invalid tests * fix retry and loop config nil issues
1 parent 7778247 commit e98bd6f

14 files changed

+572
-429
lines changed

definition/definition.go

+66-50
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package definition
22

33
import (
4+
"encoding/json"
45
"fmt"
56

67
"github.com/project-flogo/core/activity"
@@ -181,84 +182,108 @@ func (ac *ActivityConfig) OutputMapper() mapper.Mapper {
181182
return ac.outputMapper
182183
}
183184

184-
type loopCfg struct {
185+
type loopCfgDef struct {
185186
Condition string `md:"condition"`
186-
IterateOn string `md:"iterate"`
187+
IterateOn string `md:"iterateOn"`
187188
Delay int `md:"delay"`
188189
Accumulate bool `md:"accumulate"`
190+
191+
//DEPRECATED
192+
Iterate string `md:"iterate"`
189193
}
190194

191-
type loop struct {
192-
condition expression.Expr
193-
accumulate bool
194-
delay int
195-
iterateOn interface{}
195+
type LoopConfig struct {
196+
condition expression.Expr
197+
accumulate bool
198+
delay int
199+
iterateOn interface{}
200+
accApplyOutput bool
196201
}
197202

198-
func NewLoop(cfg *loopCfg, ef expression.Factory) (*loop, error) {
199-
loop := &loop{}
203+
func newLoopCfg(loopCfgDef *loopCfgDef, accApplyOutput bool, ef expression.Factory) (*LoopConfig, error) {
204+
loopCfg := &LoopConfig{accumulate: loopCfgDef.Accumulate, delay: loopCfgDef.Delay, accApplyOutput: accApplyOutput}
200205
var err error
201-
loop.accumulate = cfg.Accumulate
202-
loop.delay = cfg.Delay
203206

204-
if cfg.Condition != "" {
205-
if cfg.Condition[0] == '=' {
206-
loop.condition, err = ef.NewExpr(cfg.Condition[1:])
207+
if loopCfgDef.Condition != "" {
208+
if loopCfgDef.Condition[0] == '=' {
209+
loopCfg.condition, err = ef.NewExpr(loopCfgDef.Condition[1:])
207210
if err != nil {
208211
return nil, err
209212
}
210213
}
211214
}
212215

213-
if cfg.IterateOn != "" {
214-
if cfg.IterateOn[0] == '=' {
215-
loop.iterateOn, err = ef.NewExpr(cfg.IterateOn[1:])
216+
if loopCfgDef.IterateOn != "" {
217+
if loopCfgDef.IterateOn[0] == '=' {
218+
loopCfg.iterateOn, err = ef.NewExpr(loopCfgDef.IterateOn[1:])
216219
if err != nil {
217220
return nil, err
218221
}
219222
} else {
220-
loop.iterateOn = cfg.IterateOn
223+
loopCfg.iterateOn = loopCfgDef.IterateOn
221224
}
222225
}
223226

224-
return loop, nil
227+
return loopCfg, nil
225228
}
226229

227-
func (l *loop) Accumulated() bool {
230+
func (l *LoopConfig) Accumulate() bool {
228231
return l.accumulate
229232
}
230233

231-
func (l *loop) DowhileCondition() expression.Expr {
234+
func (l *LoopConfig) ApplyOutputOnAccumulate() bool {
235+
return l.accApplyOutput
236+
}
237+
238+
func (l *LoopConfig) Condition() expression.Expr {
232239
return l.condition
233240
}
234241

235-
func (l *loop) GetIterate() interface{} {
242+
func (l *LoopConfig) GetIterateOn() interface{} {
236243
return l.iterateOn
237244
}
238245

239-
func (l *loop) IterateEnabled() bool {
240-
return l.iterateOn != nil
246+
func (l *LoopConfig) Delay() int {
247+
return l.delay
241248
}
242249

243-
func (l *loop) DowhileEnabled() bool {
244-
return l.condition != nil
250+
type RetryOnErrConfig struct {
251+
count int
252+
interval int
245253
}
246254

247-
func (l *loop) Delay() int {
248-
return l.delay
255+
func (r *RetryOnErrConfig) Count() int {
256+
return r.count
249257
}
250258

251-
type retryErrorCfg struct {
252-
Count int `md:"count"`
253-
Interval int `md:"interval"`
259+
func (r *RetryOnErrConfig) Interval() int {
260+
return r.interval
254261
}
255262

256-
func (r *retryErrorCfg) RetryOnErrorCount() int {
257-
return r.Count
263+
func (r *RetryOnErrConfig) MarshalJSON() ([]byte, error) {
264+
return json.Marshal(&struct {
265+
Count int `md:"count"`
266+
Interval int `md:"interval"`
267+
}{
268+
Count: r.count,
269+
Interval: r.interval,
270+
})
258271
}
259272

260-
func (r *retryErrorCfg) RetryOnErrorInterval() int {
261-
return r.Interval
273+
// UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON
274+
func (r *RetryOnErrConfig) UnmarshalJSON(data []byte) error {
275+
276+
ser := &struct {
277+
Count int `md:"count"`
278+
Interval int `md:"interval"`
279+
}{}
280+
281+
if err := json.Unmarshal(data, ser); err != nil {
282+
return err
283+
}
284+
r.count = ser.Count
285+
r.interval = ser.Interval
286+
return nil
262287
}
263288

264289
// Task is the object that describes the definition of
@@ -275,10 +300,8 @@ type Task struct {
275300

276301
settingsMapper mapper.Mapper
277302

278-
//For do-while and retry
279-
280-
loop *loop
281-
retryErrorCfg *retryErrorCfg
303+
loopCfg *LoopConfig
304+
retryOnErrConfig *RetryOnErrConfig
282305

283306
toLinks []*Link
284307
fromLinks []*Link
@@ -308,19 +331,12 @@ func (task *Task) SettingsMapper() mapper.Mapper {
308331
return task.settingsMapper
309332
}
310333

311-
func (task *Task) RetryOnErrorEnabled() bool {
312-
return task.retryErrorCfg.Count > 0
313-
}
314-
func (task *Task) RetryOnErrorCount() int {
315-
return task.retryErrorCfg.Count
316-
}
317-
318-
func (task *Task) RetryOnErrorInterval() int {
319-
return task.retryErrorCfg.Interval
334+
func (task *Task) RetryOnErrConfig() *RetryOnErrConfig {
335+
return task.retryOnErrConfig
320336
}
321337

322-
func (task *Task) LoopConfig() *loop {
323-
return task.loop
338+
func (task *Task) LoopConfig() *LoopConfig {
339+
return task.loopCfg
324340
}
325341

326342
// ToLinks returns the predecessor links of the task

definition/definition_ser.go

+54-37
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import (
55
"fmt"
66
"github.com/project-flogo/core/app/resolve"
77
"github.com/project-flogo/core/data"
8-
"strconv"
9-
108
"github.com/project-flogo/core/data/coerce"
9+
"strconv"
1110

1211
"github.com/project-flogo/core/activity"
1312
"github.com/project-flogo/core/data/expression"
@@ -23,7 +22,7 @@ import (
2322
type DefinitionRep struct {
2423
ExplicitReply bool `json:"explicitReply,omitempty"`
2524
Name string `json:"name"`
26-
ModelID string `json:"id,omitempty"`
25+
ModelID string `json:"model,omitempty"`
2726
Metadata *metadata.IOMetadata `json:"metadata,omitempty"`
2827
Tasks []*TaskRep `json:"tasks"`
2928
Links []*LinkRep `json:"links,omitempty"`
@@ -151,12 +150,12 @@ func createTask(def *Definition, rep *TaskRep, ef expression.Factory) (*Task, er
151150

152151
mf := GetMapperFactory()
153152

154-
task.loop, err = getLoopCfg(rep.Settings, ef)
153+
task.loopCfg, err = getLoopCfg(rep.Settings, task.typeID, ef)
155154
if err != nil {
156155
return nil, err
157156
}
158157

159-
task.retryErrorCfg, err = getErrorCfg(rep.Settings)
158+
task.retryOnErrConfig, err = getRetryOnErrCfg(rep.Settings)
160159
if err != nil {
161160
return nil, err
162161
}
@@ -419,14 +418,20 @@ func createLink(tasks map[string]*Task, linkRep *LinkRep, id int, ef expression.
419418
return link, nil
420419
}
421420

422-
func getErrorCfg(settings map[string]interface{}) (*retryErrorCfg, error) {
423-
retryErr := &retryErrorCfg{}
421+
func getRetryOnErrCfg(settings map[string]interface{}) (*RetryOnErrConfig, error) {
422+
423+
retrySetting, ok := settings["retryOnError"]
424+
if !ok {
425+
return nil, nil
426+
}
424427

425-
retryCfgMap, err := coerce.ToObject(settings["retryOnError"])
428+
retryErr := &RetryOnErrConfig{}
429+
430+
retryCfgMap, err := coerce.ToObject(retrySetting)
426431
if err != nil {
427432
return nil, err
428433
}
429-
count , exist := retryCfgMap["count"]
434+
count, exist := retryCfgMap["count"]
430435
if exist && count != nil {
431436
strVal, ok := count.(string)
432437
if ok && len(strVal) > 0 && strVal[0] == '=' {
@@ -439,10 +444,10 @@ func getErrorCfg(settings map[string]interface{}) (*retryErrorCfg, error) {
439444
if err != nil {
440445
return nil, fmt.Errorf("retryOnError count must be int")
441446
}
442-
retryErr.Count = cnt
447+
retryErr.count = cnt
443448
}
444449

445-
interval , exist := retryCfgMap["interval"]
450+
interval, exist := retryCfgMap["interval"]
446451
if exist && interval != nil {
447452
strVal, ok := interval.(string)
448453
if ok && len(strVal) > 0 && strVal[0] == '=' {
@@ -455,50 +460,62 @@ func getErrorCfg(settings map[string]interface{}) (*retryErrorCfg, error) {
455460
if err != nil {
456461
return nil, fmt.Errorf("retryOnError interval must be int")
457462
}
458-
retryErr.Interval = intervalInt
463+
retryErr.interval = intervalInt
459464
}
460465

461466
return retryErr, nil
462-
463467
}
464468

465-
func getLoopCfg(settings map[string]interface{}, ef expression.Factory) (*loop, error) {
466-
loopCfg := &loopCfg{}
469+
func getLoopCfg(settings map[string]interface{}, taskType string, ef expression.Factory) (*LoopConfig, error) {
470+
471+
var lcd *loopCfgDef
472+
var err error
473+
474+
//check for old configurations
475+
if setting, ok := settings["loopConfig"]; ok {
476+
lcd, err = getLoopCfgDef(setting)
477+
} else if setting, ok := settings["doWhile"]; ok {
478+
lcd, err = getLoopCfgDef(setting)
479+
if accum,ok := settings["accumulate"]; lcd != nil && ok {
480+
lcd.Accumulate, _ = coerce.ToBool(accum)
481+
}
482+
} else {
483+
lcd, err = getLoopCfgDef(settings)
484+
}
467485

468-
loopCfgMap, err := coerce.ToObject(settings["loopConfig"])
469486
if err != nil {
470487
return nil, err
471488
}
472489

473-
if loopCfgMap != nil {
474-
475-
err = metadata.MapToStruct(loopCfgMap, loopCfg, true)
476-
477-
if err != nil {
478-
return nil, err
479-
}
490+
if lcd == nil {
491+
return nil, nil
492+
}
480493

481-
} else {
494+
return newLoopCfg(lcd, taskType == "doWhile", ef)
495+
}
482496

483-
err = metadata.MapToStruct(settings, loopCfg, true)
497+
func getLoopCfgDef(setting interface{}) (*loopCfgDef, error) {
484498

485-
if err != nil {
486-
return nil, err
487-
}
488-
dowhileObj, err := coerce.ToObject(settings["doWhile"])
489-
if err != nil {
490-
return nil, err
491-
}
492-
err = metadata.MapToStruct(dowhileObj, loopCfg, true)
499+
settingMap, err := coerce.ToObject(setting)
500+
if err != nil {
501+
return nil, err
502+
}
493503

494-
if err != nil {
495-
return nil, err
496-
}
504+
lcd := &loopCfgDef{}
505+
err = metadata.MapToStruct(settingMap, lcd, true)
506+
if err != nil {
507+
return nil, err
497508
}
498509

499-
return NewLoop(loopCfg, ef)
510+
if lcd.IterateOn == "" {
511+
lcd.IterateOn = lcd.Iterate
512+
}
500513

514+
if lcd.Condition == "" && lcd.IterateOn == "" {
515+
return nil, nil
516+
}
501517

518+
return lcd, nil
502519
}
503520

504521
type initCtxImpl struct {

0 commit comments

Comments
 (0)