stepflow

package module
v0.0.0-...-5266dbe Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2018 License: MIT Imports: 13 Imported by: 0

README

go-stepflow

Embeddable, scaleout-friendly data flow engine written in Go.

Stepflow lets you define a data flow through a sequence of steps. A data flow starts at an initial step and contains no data. A step transforms the flow (e.g. by modifying the data) before it gets handed off to the next step(s). The transformation depends on the type of step. A data flow can be entirely defined via a JSON document (which can be deserialized into a Dataflow object).

getting started

The executor engine is instantiated with the NewExecutor function:

func NewExecutor(httpClientFactory HTTPClientFactory, logger Logger, storage Storage, flowQueue FlowQueue) Executor 

It expects a number of interfaces to be provided to it, which allows the executor to be embeddable in different environments by providing specific implementations of the interfaces.

  1. HTTPClientFactory abstracts the creation of an HTTP client to support environments where this needs to be done outside the built-in packages
  2. Logger abstracts message logging
  3. Storage abstracts the storage, retrieval and deletion of flow execution objects such as the dataflow run, the steps, split information etc.
  4. FlowQueue abstracts the enqueueing and dequeueing of flows to/from a task queue.

A simple, in-process implementation of these services is provided in the inprocess package. See the main.go application in inprocess/cmd for details on how to instantiate an executor with the in-process implementation, how to deserialize JSON into a Dataflow and how to monitor flow execution. You can run the in-process engine by passing it the path to a dataflow file:

go run inprocess/cmd/main.go -dataflow <path-to-dataflow-json>

There are several sample dataflow files in the samples directory. If you use these samples with the above command you will need to run a web server implementing the endpoints required by the samples (see the web-method step type for more information on accessing HTTP endpoints). The node application at https://github.com/jcalvarado1965/node-functions can be to provide the required endpoints.

The samples directory has flows demonstrating all the different step types. Step types are described below.

constant step

This simple flow contains one constant step:

{
   "id": "very-simple-workflow",
   "description": "This only has a constant step",
   "startAt": "array-constant",
   "steps": [
      {
        "id": "array-constant",
        "description": "sets the flow data to the value array",
        "type": "constant",
        "value": [1, 2, 3, 4, 5, 6, 7, 8, 9]
      }
   ]
}

The flow has an id and description (both are descriptive only and do not affect execution). The startAt property tells the executor which step the flow starts at. The single step in this flow (id array-constant) is of type constant. A step's id must be unique within a flow. A constant step transforms the flow by setting the flow data to the contents of the value property, an array of integers in this case. Not very useful yet.

web-method step

The web-method is the workhorse of the executor. Most business logic would be executed through a web-method step. It takes the flow data and makes an POST HTTP request to a given endpoint, and sets the flow data to the response body. Here is the previous example with an added web-method which POSTs the constant array to an endpoint:

{
   "id": "simple-workflow",
   "description": "This has a constant sent to a web method",
   "startAt": "array-constant",
   "steps": [
      {
        "id": "array-constant",
        "description": "sets the flow data to the value array",
        "type": "constant",
        "value": [1, 2, 3, 4, 5, 6, 7, 8, 9],
        "next": "adder"
      },
      {
        "id": "adder",
        "description": "should add the ints",
        "type": "web-method",
        "method": "POST",
        "url": "http://myapp.org/gcf-executor/us-central1/adder"
      }
   ]
}

Note the next property on the constant step which tells the executor which step to execute next.

distribute and broadcast steps

The executor is scaleout-friendly by providing two step types that split a flow into multiple children flows.

The distribute step expects the flow data to be JSON-deserializable into either an array or an object. If the data is an array it creates a child flow for each element of the array, setting their flows to the array element value. If the data is an object it creates a child flow for each key of the object, setting the flow data to the key value. Here is a flow that distributes a 2D array into multiple HTTP requests:

{
   "id": "distributing-workflow",
   "description": "This sends array elements to adder",
   "startAt": "array-constant",
   "steps": [
      {
        "id": "array-constant",
        "description": "sets the flow data to a 2d array",
        "type": "constant",
        "value": [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
        "next": "dist-arrays"
      },
      {
        "id": "dist-arrays",
        "description": "breakout sub arrays",
        "type": "distribute",
        "next": "adder"
      },
      {
        "id": "adder",
        "description": "should add the ints",
        "type": "web-method",
        "method": "POST",
        "url": "http://myapp.org/gcf-executor/us-central1/adder"
      }
   ]
}

In this case the adder endpoint will be invoked three times, with POST body set to [1, 2, 3], [4, 5, 6] and [7, 8, 9] respectively.

A broadcast step splits the flow into multiple children based on a list of steps to forward the flow to (i.e. send the flow to multiple steps instead of a single one). Building on the previous example, the following flow distributes a 2d array into two web-method steps:

{
   "id": "distributing-broadcasting-workflow",
   "description": "This sends array elements to adder and multiplier",
   "startAt": "array-constant",
   "steps": [
      {
        "id": "array-constant",
        "description": "sets the flow data to a 2d array",
        "type": "constant",
        "value": [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
        "next": "dist-arrays"
      },
      {
        "id": "dist-arrays",
        "description": "breakout sub arrays",
        "type": "distribute",
        "next": "broadcast-array"
      },
      {
        "id": "broadcast-array",
        "description": "broadcast to add and mult",
        "type": "broadcast",
        "forwardTo": ["adder","multiplier"]
      },
      {
        "id": "adder",
        "description": "should add the ints",
        "type": "web-method",
        "method": "POST",
        "url": "http://myapp.org/gcf-executor/us-central1/adder"
      },
      {
        "id": "multiplier",
        "description": "should multiply the ints",
        "type": "web-method",
        "method": "POST",
        "url": "http://myapp.org/gcf-executor/us-central1/multiplier"
      }
   ]
}

In this case both the adder and multiplier endpoints will be invoked three times, with POST body set to [1, 2, 3], [4, 5, 6] and [7, 8, 9] respectively.

join and race steps

Children flows from a split can proceed to completion and the executor will finish the workflow once all children are finished. However it can be useful to merge the children flows before executing subsequent steps (think map/reduce).

The join step will wait until all children flows are finished, then re-activate the parent flow, setting the flow data to the merged data from all the children. If the children were split from a distribute step acting on an array, the merged data will be an array containing each of the children flows' data. If the split was from a distribute on an object, or a broadcast step, the merged data will be an object, with keys set to the distribute object keys or the broadcast step id's, respectively, and the key values set to the children flows' data.

In the following example, a distribute step sends array elements to a web-method, then a join collects the outputs of the web-method requests:

{
   "id": "distributing-and-joining",
   "description": "This distributes to an adder, then join",
   "startAt": "array-constant",
   "steps": [
      {
        "id": "array-constant",
        "description": "sets the flow data to a 2d array",
        "type": "constant",
        "value": [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
        "next": "dist-arrays"
      },
      {
        "id": "dist-arrays",
        "description": "breakout sub arrays",
        "type": "distribute",
        "next": "adder"
      },
      {
        "id": "adder",
        "description": "should add the ints",
        "type": "web-method",
        "method": "POST",
        "url": "http://myapp.org/gcf-executor/us-central1/adder",
        "next": "joiner"
      },
      {
        "id": "joiner",
        "description": "collect adder outputs",
        "type": "join",
        "next": "echo"
      },
      {
        "id": "echo",
        "description": "should echo the joined data",
        "type": "web-method",
        "method": "POST",
        "url": "http://myapp.org/gcf-executor/us-central1/echo"
      },
   ]
}

In this case, the final web-method step will POST the array [6, 10, 24] to the echo endpoint.

The race step will activate the parent flow as soon as the first non-error child flow arrives. The parent flow's data will be set to the "winnning" childs flow data. All other child flows will be interrupted. If the previous flow is modified to use race instead of join in the 4th step, the final web-method will post either 6, 10 or 24 to the echo endpoint.

conditional and select steps

A conditional step acts like an if statement. If the flow data (which must be JSON deserializable) satisfies the given expression, the flow continues to the next step, with its data unchanged. If not, the flow is interrupted. Expressions are evaluated with github.com/Knetic/govaluate. Expression variables are represented by jsonpath selectors and evaluated using github.com/oliveagle/jsonpath. Because jsonpath variables are complex strings they generally need to be enclosed with []. If the jsonpath expression contains [] these need to be further escaped with \. The following flow demonstrates the behavior of conditional:

{
   "id": "conditional-workflow",
   "description": "Demo the conditional step",
   "startAt": "array-constant",
   "steps": [
      {
        "id": "array-constant",
        "description": "sets the flow data to an object array",
        "type": "constant",
        "value": [
          {"name": "joe", "age": 35},
          {"name": "mark", "age": 26},
          {"name": "mary", "age": 42}
          ],
        "next": "dist-arrays"
      },
      {
        "id": "dist-arrays",
        "description": "breakout sub objects",
        "type": "distribute",
        "next": "age-filter"
      },
      {
        "id": "conditional",
        "description": "filter by age",
        "type": "conditional",
        "condition": "[$.age] > 30",
        "next": "echo"
      },
      {
         "id": "echo",
         "description": "call web method echo",
         "type": "web-method",
         "method": "POST",
         "url": "http://localhost:8080/echo"
       }
   ]
}

In this example the echo endpoint will be called twice, with content {"name": "joe", "age": 35} and {"name": "mary", "age": 42} respectively.

The select step provides simple data manipulation (complex manipulation should be done as business logic via web-method). It uses the provided jsonpath expression to select a subset of the incoming data (which must be JSON deserializable). Below is the previous example, modified so that the echo endpoint receives only the name property.

{
   "id": "conditional-workflow",
   "description": "Demo the conditional step",
   "startAt": "array-constant",
   "steps": [
      {
        "id": "array-constant",
        "description": "sets the flow data to an object array",
        "type": "constant",
        "value": [
          {"name": "joe", "age": 35},
          {"name": "mark", "age": 26},
          {"name": "mary", "age": 42}
          ],
        "next": "dist-arrays"
      },
      {
        "id": "dist-arrays",
        "description": "breakout sub objects",
        "type": "distribute",
        "next": "age-filter"
      },
      {
        "id": "conditional",
        "description": "filter by age",
        "type": "conditional",
        "condition": "[$.age] > 30",
        "next": "select"
      },
      {
        "id": "select",
        "description": "select the name property",
        "type": "select",
        "selector": "$.name",
        "next": "echo"
      },
      {
         "id": "echo",
         "description": "call web method echo",
         "type": "web-method",
         "method": "POST",
         "url": "http://localhost:8080/echo"
       }
   ]
}

Documentation

Index

Constants

View Source
const (
	RunStateNew         = DataflowRunState("New")
	RunStateActive      = DataflowRunState("Active")
	RunStateInterrupted = DataflowRunState("Interrupted")
	RunStateCompleted   = DataflowRunState("Completed")
	RunStateError       = DataflowRunState("Error")
)

list of workflow run states

Variables

View Source
var (
	FlowContextKey        = FlowContextKeyType{}
	DataflowRunContextKey = DataflowRunContextKeyType{}
	StepContextKey        = StepContextKeyType{}
)

Used to store info in context

Functions

This section is empty.

Types

type BaseStep

type BaseStep struct {
	ID          string   `json:"id,omitempty"`
	Description string   `json:"description,omitempty"`
	Type        StepType `json:"type,omitempty"`
	Next        Step     `json:"-"`
	NextID      string   `json:"next,omitempty"`
}

BaseStep holds the basic step details. ID must be unique within a Dataflow. Type is used for serialization. Next points to the next step in the workflow (except for BroadcastStep which forwards to multiples). AcceptContent indicates the content type the step requires, if any. ContentType indicates the content type of the output, if any. If KeepOutput is true, the outputs are copied to the workflow run so they are available when the workflow completes. If HandleErrorAs is not nil, then errors do not stop the flow but instead the given JSON is passed to the next task(s)

func (*BaseStep) GetID

func (s *BaseStep) GetID() string

GetID for Step impl in BaseStep

func (*BaseStep) GetNextID

func (s *BaseStep) GetNextID() string

GetNextID for Step impl in BaseStep

func (*BaseStep) PrepareMarshal

func (s *BaseStep) PrepareMarshal()

PrepareMarshal for Step impl in BaseStep

func (*BaseStep) ResolveIDs

func (s *BaseStep) ResolveIDs(stepMap map[string]Step) error

ResolveIDs for Step impl in BaseStep

func (*BaseStep) String

func (s *BaseStep) String() string

func (*BaseStep) Validate

func (s *BaseStep) Validate() []error

Validate for Step impl in BaseStep

type BroadcastStep

type BroadcastStep struct {
	BaseStep
	ForwardTo    []Step   `json:"-"`
	ForwardToIDs []string `json:"forwardTo,omitempty"`
}

BroadcastStep describes a step that takes its input and forwards to multiple steps

func (*BroadcastStep) PrepareMarshal

func (s *BroadcastStep) PrepareMarshal()

PrepareMarshal sets the step type

func (*BroadcastStep) ResolveIDs

func (s *BroadcastStep) ResolveIDs(stepMap map[string]Step) error

ResolveIDs resolve the ForwardToIDs

func (*BroadcastStep) Split

func (s *BroadcastStep) Split(ctx context.Context, exec Executor, flow *Flow) (outflows []*Flow, split *FlowSplit, err error)

Split implements the splitter step interface

type ConditionalStep

type ConditionalStep struct {
	BaseStep
	Condition string `json:"condition,omitempty"`
}

ConditionalStep only forwards to the next step if condition is satisfied. Input must be JSON.

func (*ConditionalStep) Do

func (s *ConditionalStep) Do(ctx context.Context, exec Executor, flow *Flow) error

Do implements DoerStep interface

func (*ConditionalStep) PrepareMarshal

func (s *ConditionalStep) PrepareMarshal()

PrepareMarshal sets the step type

func (*ConditionalStep) Validate

func (s *ConditionalStep) Validate() []error

Validate checks the condition is set and can be compiled

type ConstantStep

type ConstantStep struct {
	BaseStep
	Value json.RawMessage `json:"value,omitempty"`
}

ConstantStep takes its value (JSON) and sends it to the Next step

func (*ConstantStep) Do

func (s *ConstantStep) Do(ctx context.Context, exec Executor, flow *Flow) error

Do implements DoerStep interface

func (*ConstantStep) PrepareMarshal

func (s *ConstantStep) PrepareMarshal()

PrepareMarshal sets the step type

func (*ConstantStep) Validate

func (s *ConstantStep) Validate() []error

Validate checks that the constant step has a value

type Dataflow

type Dataflow struct {
	ID          string          `json:"id,omitempty"`
	Description string          `json:"description,omitempty"`
	Steps       []Step          `json:"-"`
	StartAt     Step            `json:"-"`
	StepMap     map[string]Step `json:"-"`
}

Dataflow defines a workflow

func (*Dataflow) GetStep

func (w *Dataflow) GetStep(ID string) Step

GetStep returns the workflow step with the given ID

func (Dataflow) MarshalJSON

func (w Dataflow) MarshalJSON() ([]byte, error)

MarshalJSON implements Marshaller for Dataflow

func (Dataflow) String

func (w Dataflow) String() string

func (*Dataflow) UnmarshalJSON

func (w *Dataflow) UnmarshalJSON(bytes []byte) error

UnmarshalJSON implements Unmarshaller for Dataflow

type DataflowMarshaller

type DataflowMarshaller struct {
	DataflowNoFn
	StepsJSON []json.RawMessage `json:"steps"`
	StartID   string            `json:"startAt,omitempty"`
}

DataflowMarshaller is used for marshaling a workflow into JSON

type DataflowNoFn

type DataflowNoFn Dataflow

DataflowNoFn erases the marshaling functions to avoid recursion

type DataflowRun

type DataflowRun struct {
	ID       DataflowRunID
	Dataflow *Dataflow
	State    DataflowRunState
}

DataflowRun describes a running workflow

func NewDataflowRun

func NewDataflowRun(df *Dataflow) *DataflowRun

NewDataflowRun creates a run

type DataflowRunContextKeyType

type DataflowRunContextKeyType struct{}

DataflowRunContextKeyType used to store workflow run id in context

type DataflowRunID

type DataflowRunID string

DataflowRunID identifies a workflow run (generated UUID)

type DataflowRunState

type DataflowRunState string

DataflowRunState is the string type of workflow run states

type DistributeStep

type DistributeStep struct {
	BaseStep
}

DistributeStep takes its input, which must be a JSON array, and sends each element of the array to the Next step

func (*DistributeStep) PrepareMarshal

func (s *DistributeStep) PrepareMarshal()

PrepareMarshal sets the step type

func (*DistributeStep) Split

func (s *DistributeStep) Split(ctx context.Context, exec Executor, flow *Flow) (outflows []*Flow, split *FlowSplit, err error)

Split implements the splitter step interface

type DoerStep

type DoerStep interface {
	Do(ctx context.Context, exec Executor, flow *Flow) error
}

DoerStep is implemented by steps that perform an action

type Executor

type Executor interface {
	Start(ctx context.Context, workflow *Dataflow) (*DataflowRun, []error)
	Validate(ctx context.Context, workflow *Dataflow) []error
	Interrupt(ctx context.Context, run *DataflowRun)

	GetHTTPClientFactory() HTTPClientFactory
	GetLogger() Logger
	GetStorage() Storage
}

Executor is the interface implemented by the executing engine

func NewExecutor

func NewExecutor(httpClientFactory HTTPClientFactory, logger Logger, storage Storage, flowQueue FlowQueue) Executor

NewExecutor creates an instance of the execution engine

type Flow

type Flow struct {
	FlowNoData             // helps with serialization
	Data       interface{} // if State is Completed, this has the result
}

Flow represents an execution unit for a workflow Dataflow runs start with one flow, set at the starting step. When a step completes, the flow transitions to the next step. Flows can split in Distribute and Broadcast steps. Flows can merge in the Join and Race steps.

func (*Flow) String

func (f *Flow) String() string

type FlowContextKeyType

type FlowContextKeyType struct{}

FlowContextKeyType used to store flow id in context

type FlowID

type FlowID string

FlowID identifies a flow

type FlowNoData

type FlowNoData struct {
	ID             FlowID        // UUID
	DataflowRunID  DataflowRunID // identifies the run instance
	PreviousStepID string
	NextStepID     string
	State          FlowState
	Message        string        // if State is Error, this has the explanation
	ContentType    string        // content type of data
	Splits         []FlowSplitID // identifies the splits that led to this flow
	SplitKey       string        // if the current split is from dictionary, the key
	SplitIndex     int           // if the current split is from array, the index
}

type FlowQueue

type FlowQueue interface {
	SetDequeueCb(func(ctx context.Context, flow *Flow) error)
	Enqueue(ctx context.Context, flow *Flow) error
}

FlowQueue is the interface implemented by external queue service

type FlowSplit

type FlowSplit struct {
	ID            FlowSplitID        // uuid
	DataflowRunID DataflowRunID      // identifies the run instance
	SplitStepID   string             // this would be a broadcast or distribute step
	ParentFlowID  FlowID             // the flow that was split
	IndexType     FlowSplitIndexType // the type of index used in the split
	FlowIDs       []FlowID           // lists the flows generated by the split
}

FlowSplit holds information about an instance of a split flow

type FlowSplitID

type FlowSplitID string

FlowSplitID identifies a flow split instance

type FlowSplitIndexType

type FlowSplitIndexType string

FlowSplitIndexType represents the type of flow split index (key or numerical)

const (
	FlowSplitNumericalIndex FlowSplitIndexType = "Numerical"
	FlowSplitKeyIndex       FlowSplitIndexType = "Key"
)

These are the index types for a flow split

type FlowState

type FlowState string

FlowState represents the state of a flow

const (
	FlowStateActive      FlowState = "Active"
	FlowStateError       FlowState = "Error"       // flow stopped due to error
	FlowStateCompleted   FlowState = "Completed"   // flow dead-ended
	FlowStateSplit       FlowState = "Split"       // there are child flows
	FlowStateInterrupted FlowState = "Interrupted" // e.g. from a conditional
)

These are the states a flow can be in, w.r.t. to the previous step ID

type HTTPClientFactory

type HTTPClientFactory interface {
	GetHTTPClient(ctx context.Context, disableSSLValidation bool) *http.Client
}

HTTPClientFactory is used to abstract HTTP client creation

type JoinStep

type JoinStep struct {
	BaseStep
}

JoinStep waits until all the steps providing input to it complete, combines the inputs into a single result and forwards to the Next step. The combination is a JSON object whose keys are the IDs of the steps providing the input, and the values are the inputs. If the input value is not JSON then it is given as a base64-encoded string. If the input is from a step receiving a distribution, the value is an array.

func (*JoinStep) Join

func (s *JoinStep) Join(ctx context.Context, exec Executor, flow *Flow) (joinedFlow *Flow, err error)

Join implements Joiner interface for join step

func (*JoinStep) PrepareMarshal

func (s *JoinStep) PrepareMarshal()

PrepareMarshal sets the step type

type JoinerStep

type JoinerStep interface {
	Join(ctx context.Context, exec Executor, flow *Flow) (joinedFlow *Flow, err error)
}

JoinerStep is implemented by steps that join flows

type Logger

type Logger interface {
	Debugf(ctx context.Context, fmt string, params ...interface{})
	Infof(ctx context.Context, fmt string, params ...interface{})
	Warnf(ctx context.Context, fmt string, params ...interface{})
	Errorf(ctx context.Context, fmt string, params ...interface{})
}

Logger is passed to other services for pluggable logging

type RaceStep

type RaceStep struct {
	BaseStep
}

RaceStep waits until it receives its first active flow input and forwards it to the Next step. Subsequent inputs are discarded

func (*RaceStep) Join

func (s *RaceStep) Join(ctx context.Context, exec Executor, flow *Flow) (joinedFlow *Flow, err error)

Join implements Joiner interface for race step

func (*RaceStep) PrepareMarshal

func (s *RaceStep) PrepareMarshal()

PrepareMarshal sets the step type

type SelectStep

type SelectStep struct {
	BaseStep
	Selector string `json:"selector,omitempty"`
}

SelectStep expects the flow data to be parseable as JSON. It then uses the selector expression (see https://github.com/oliveagle/jsonpath) and returns the results of applying the expression to the flow data.

func (*SelectStep) Do

func (s *SelectStep) Do(ctx context.Context, exec Executor, flow *Flow) error

Do implements DoerStep interface

func (*SelectStep) PrepareMarshal

func (s *SelectStep) PrepareMarshal()

PrepareMarshal sets the step type

func (*SelectStep) Validate

func (s *SelectStep) Validate() (errList []error)

Validate checks the selector can be compiled

type SplitterStep

type SplitterStep interface {
	Split(ctx context.Context, exec Executor, flow *Flow) (outflows []*Flow, split *FlowSplit, err error)
}

SplitterStep is implemented by steps that split flows

type Step

type Step interface {
	GetID() string
	GetNextID() string
	PrepareMarshal()
	ResolveIDs(map[string]Step) error
	Validate() []error
}

Step is the interface implemented by all steps

func UnmarshalStep

func UnmarshalStep(raw json.RawMessage) (Step, error)

UnmarshalStep returns a specialized step based on the raw JSON

type StepContextKeyType

type StepContextKeyType struct{}

StepContextKeyType used to store step ID in context

type StepType

type StepType string

StepType is an enum for the known step types

const (
	TypeWebMethod   StepType = "web-method"
	TypeDistribute  StepType = "distribute"
	TypeBroadcast   StepType = "broadcast"
	TypeSelect      StepType = "select"
	TypeConditional StepType = "conditional"
	TypeJoin        StepType = "join"
	TypeRace        StepType = "race"
	TypeConstant    StepType = "constant"
)

These are the known step types

type Storage

type Storage interface {
	StoreDataflowRun(ctx context.Context, run *DataflowRun) error
	RetrieveDataflowRuns(ctx context.Context, keys []DataflowRunID) map[DataflowRunID]*DataflowRun
	DeleteDataflowRun(ctx context.Context, key DataflowRunID) error

	StoreFlow(ctx context.Context, flow *Flow) error
	RetrieveFlows(ctx context.Context, keys []FlowID) map[FlowID]*Flow
	DeleteFlow(ctx context.Context, key FlowID) error

	StoreFlowSplit(ctx context.Context, flowSplit *FlowSplit) error
	RetrieveFlowSplits(ctx context.Context, keys []FlowSplitID) map[FlowSplitID]*FlowSplit
	DeleteFlowSplit(ctx context.Context, key FlowSplitID) error

	Increment(ctx context.Context, key string, initialValue int64, increment int64) int64
	IncrementWithError(ctx context.Context, key string, increment int64, errIncrement int64) (count int64, errCount int64)
}

Storage is the interface implemented by external storage service

type WebMethodStep

type WebMethodStep struct {
	BaseStep
	Method string `json:"method,omitempty"`
	URL    string `json:"url,omitempty"`
}

WebMethodStep describes a step that makes an HTTP request, and sends the response to the Next step

func (*WebMethodStep) Do

func (s *WebMethodStep) Do(ctx context.Context, exec Executor, flow *Flow) error

Do implements DoerStep interface

func (*WebMethodStep) PrepareMarshal

func (s *WebMethodStep) PrepareMarshal()

PrepareMarshal sets the step type

func (*WebMethodStep) Validate

func (s *WebMethodStep) Validate() []error

Validate checks the method and URL are OK

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL