// Copyright (c) 2015, One Off Code LLC., All Rights Reserved
// some helper type declarations because I read somewhere that this is preferred.
type SelectKey string
type SelectValue string
type TaskParam string
// ExeConFunc is a function prototype signature
type ExeConFunc func(context.Context, ...interface{}) (context.Context, SelectValue)
// ExeConTask is a single node/task signature
// each field has a default value and behavior
type ExeConTask struct (
Func ExeConFunc // default: use the fieldname prefixed with "Fn"
Params []TaskParam // default: empty
Select map[SelectKey]SelectValue // default: {"ERROR":"_ERROR_", "DONE":"_EXIT_", "NEXT":"_NEXT_"}
)
// ExeCon is the interface entrance to the workflow manager
type ExeCon interface {
Execute(context.Context) context.Context
}
// MyFlow is a userspace structure which defines the workflow
type MyFlow struct {
Init ExeConTask
Random ExeConTask `params:"RANDVAL"`
OddEven ExeConTask `params:"RANDVAL" select:"ODD:Odd,EVEN:Even,ELSE:Error"`
Odd ExeConTask
Even ExeConTask
Finish ExeConTask
Error ExeConTask
err error
}
// instance example instead of working from the structure
var myflow = MyFlow {
Init: {Func: FnInit,},
Random: {Func: FnRandom, Params: []interface{}{"RANDVAL"},}
OddEven: {Func: FnOddEven, Params: []interface{}{"RANDVAL"}, Select:{"ODD":"Odd", "EVEN":"Even","ELSE","Error"},}
Odd: {Func: FnOdd, Select:{"NEXT":"Finish",},},
Even: {Func: FnEven,Select:{"NEXT":"Finish",},},
Finish: {Func: FnFinish,},
Error: {Func: FnError,},
}
func (p *MyFlow)Execute(ctx context.Context) context.Context {
return execon.Execute(context.WithValue(ctx, "SELF", p))
}
// not sure which is better... execon.New() would convert the tags to instance values like a generator
retctx := MyFlow{}.Execute(context.Context{})
retctx := execon.New(MyFlow{}).Execute(context.Context{})
// Execute the flow
retctx := myflow.Execute(context.Context{})
func FnInit(ctx context.Context, args ...interface{}) (context.Context, SelectValue) {
log.Printf("Init: ...")
return ctx, "NEXT"
}
func FnFinish(ctx context.Context, args ...interface{}) (context.Context, SelectValue) {
log.Printf("Finish: ...")
return ctx, "DONE"
}
func FnError(ctx context.Context, args ...interface{}) (context.Context, SelectValue) {
log.Printf("Error: ...")
return ctx, "ERROR"
}
func FnRandom(ctx context.Context, args ...interface{}) (context.Context, SelectValue) {
log.Printf("Random: ...")
return context.WithValue(ctx, args[0].(string), rand.Int()), "NEXT"
}
func FnOddEven(ctx context.Context, args ...interface{}) (context.Context, SelectValue) {
log.Printf("OddEven: ...")
n := ctx.Value(args[0].(string)).(int)
if n % 2 == 0 {
return ctx, "EVEN"
}
return ctx, "ODD"
}
func FnEven(ctx context.Context, args ...interface{}) (context.Context, SelectValue) {
log.Printf("Even: ...")
return ctx, "NEXT"
}
func FnOdd(ctx context.Context, args ...interface{}) (context.Context, SelectValue) {
log.Printf("Odd: ...")
return ctx, "NEXT"
}