Snippets

One Off Code Working thoughts for structure based work flow

Created by Richard Bucker
// 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"
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.