github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/docs/v2/design/framework/flow.md (about) 1 # Flow 2 3 Flow is the concept of a workflow. A way to orchestrate multiple actions in a single place. 4 5 ## Overview 6 7 Flow is a form of workflow orchestration. It acts as a state machine which manages a specific set of steps or actions while dealing with the fault tolerance aspects. 8 This can include processing a request, publishing an event, storing data and waiting for some prior action. Normally we codify all this by hand including the 9 error handling. Flows would essentially manage the majority of this for us. 10 11 ## Design 12 13 Flow service must provide Flow manager that able to maipulate flows and steps inside it. And also Executor that runs workload in flow order. Most essential part, that we must provide not only static flow definition, but also provide ability to register some endpoint in flow after all services starts. So each service does not need to know about others. 14 15 ## Implemenations 16 17 Now we have only one default flow implementation. It uses worker pool to distribute workload across workers. And some predefined operations, like: 18 19 * ClientCallOperation - calls service endpoint via micro client (rpc) 20 21 * ClientPublishOperation - call service endpoint via broker (pubsub) 22 23 * FlowExecuteOperation - call the same or another flow with specific step, 24 useful to able to rollback some failed action. FlowExecuteOperation utlize 25 previous two operations to call endpoints 26 27 ## Design 28 29 Flow interface modifies flow 30 31 ```go 32 type Flow interface { 33 // Init flow with options 34 Init(...Option) error 35 // Get flow options 36 Options() Options 37 // Create step in specific flow 38 CreateStep(flow string, step *Step) error 39 // Delete step from specific flow 40 DeleteStep(flow string, step *Step) error 41 // Replace step in specific flow 42 ReplaceStep(flow string, oldstep *Step, newstep *Step) error 43 // Lookup specific flow 44 Lookup(flow string) ([]*Step, error) 45 // Execute specific floa via Executor and returns request id and error, optionally fills rsp in case of sync execution 46 Execute(steps []*Step, req interface{}, rsp interface{}, opts ...ExecuteOption) (string, error) 47 } 48 ``` 49 50 Flow options 51 ```go 52 type Options struct { 53 // Executor used to execute steps in flow 54 Executor Executor 55 // Context is used for storing non default options 56 Context context.Context 57 } 58 ``` 59 60 Executor interface provides steps execution 61 62 ```go 63 type Executor interface { 64 // Init flow with options 65 Init(...ExecutorOption) error 66 // Get flow options 67 Options() ExecutorOptions 68 // Run execution with sync/async capability 69 Execute(steps []*Step, req interface{}, rsp interface{}, opts ...ExecuteOption) (string, error) 70 // Resume specific flow execution by id 71 Resume(flow string, id string) error 72 // Pause specific flow execution by id 73 Pause(flow string, id string) error 74 // Abort specific flow execution by id 75 Abort(flow string, id string) error 76 // Status show status specific flow execution by request id 77 Status(flow string, id string) (Status, error) 78 // Result get result of the flow step 79 Result(flow string, id string, step string) ([]byte, error) 80 // Stop executor and drain active workers 81 Stop() error 82 } 83 ``` 84 85 Executor options 86 87 ```go 88 type ExecutorOptions struct { 89 // Flow is used to be able to run another flow from current execution 90 Flow Flow 91 // ErrorHandler is used for recovery panics 92 ErrorHandler func(interface{}) 93 // Context is used for storing non default options 94 Context context.Context 95 } 96 ``` 97 98 Step definition 99 100 ```go 101 type Step struct { 102 // name of step 103 ID string 104 // Retry count for step 105 Retry int 106 // Timeout for step 107 Timeout int 108 // Step operation to execute 109 Operation Operation 110 // Which step use as input 111 Input string 112 // Where to place output 113 Output string 114 // Steps IDs that runs after this step 115 After []*Step 116 // Steps IDs that runs before this step 117 Before []*Step 118 // Step operation to execute in case of error 119 Fallback Operation 120 } 121 ``` 122 123 Operation definition 124 125 ```go 126 type Operation interface { 127 Name() string 128 String() string 129 Type() string 130 New() Operation 131 Decode(*pb.Operation) 132 Encode() *pb.Operation 133 Execute(context.Context, []byte, ...ExecuteOption) ([]byte, error) 134 Options() OperationOptions 135 } 136 ``` 137 138 Execute options 139 140 ```go 141 type ExecuteOptions struct { 142 // Passed flow name 143 Flow string 144 // Passed execution id 145 ID strinh 146 // Passed step to start from 147 Step string 148 // Step ID to store Output data 149 Output string 150 // Timeout for currenct execution 151 Timeout time.Duration 152 // Async execution run, dont wait for complete 153 Async bool 154 // Concurrency specify count of workers create for steps in flow 155 Concurrency int 156 // Retries specify count of retries for each step in execution 157 Retries int 158 // Client for communication 159 Client client.Client 160 // Context is used for storing non default options 161 Context context.Context 162 } 163 ``` 164 165 Operation options 166 167 ```go 168 type OperationOptions struct { 169 Timeout time.Duration 170 Retries int 171 AllowFail bool 172 Context context.Context 173 } 174 ``` 175 176 Step statuses 177 178 ```go 179 180 type Status int 181 182 const ( 183 StatusUnknown Status = iota 184 StatusPending 185 StatusFailure 186 StatusSuccess 187 StatusPaused 188 StatusAborted 189 StatusStopped 190 ) 191 192 ``` 193 194 ## Status 195 196 Incomplete. Lacks of timeout, retries. Don't have proper supports to pause/resume/stop/restart flow execution. 197 But its easy to add after minimal working code has been merged. 198 199