action/action.go
func (p *Pipeline) Execute(params ...interface{}) (err error) {
	var r Result
	if len(p.actions) == 0 {
		return ErrPipelineNoActions
	}
	fwCtx := FWContext{Params: params}
	var i int
	var a *Action
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("[pipeline] PANIC running the Forward for the %s action - %v", a.Name, r)
			err = fmt.Errorf("panic running the Forward for the %s action: %v", a.Name, r)
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
		}
	}()
	for i, a = range p.actions {
		log.Debugf("[pipeline] running the Forward for the %s action", a.Name)
		if a.Forward == nil {
			err = ErrPipelineForwardMissing
		} else if len(fwCtx.Params) < a.MinParams {
			err = ErrPipelineFewParameters
		} else {
			r, err = a.Forward(fwCtx)
			a.rMutex.Lock()
			a.result = r
			a.rMutex.Unlock()
			fwCtx.Previous = r
		}
		if err != nil {
			log.Errorf("[pipeline] error running the Forward for the %s action - %s", a.Name, err)
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
			return err
		}
	}
	return nil
}
func (p *Pipeline) Execute(params ...interface{}) (err error) {
	var r Result
	if len(p.actions) == 0 {
		return ErrPipelineNoActions
	}
	fwCtx := FWContext{Params: params}
	var i int
	var a *Action
	defer func() {
		if r := recover(); r != nil {
			log.Errorf("[pipeline] PANIC running the Forward for the %s action - %v", a.Name, r)
			err = fmt.Errorf("panic running the Forward for the %s action: %v", a.Name, r)
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
		}
	}()
	for i, a = range p.actions {
		log.Debugf("[pipeline] running the Forward for the %s action", a.Name)
		if a.Forward == nil {
			err = ErrPipelineForwardMissing
		} else if len(fwCtx.Params) < a.MinParams {
			err = ErrPipelineFewParameters
		} else {
			r, err = a.Forward(fwCtx)
			a.rMutex.Lock()
			a.result = r
			a.rMutex.Unlock()
			fwCtx.Previous = r
		}
		if err != nil {
			log.Errorf("[pipeline] error running the Forward for the %s action - %s", a.Name, err)
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
			return err
		}
	}
	return nil
}
// Execute executes the pipeline.
//
// The execution starts in the forward phase, calling the Forward function of
// all actions. If none of the Forward calls return error, the pipeline
// execution ends in the forward phase and is "committed".
//
// If any of the Forward calls fails, the executor switches to the backward phase
// (roll back) and call the Backward function for each action completed. It
// does not call the Backward function of the action that has failed.
//
// After rolling back all completed actions, it returns the original error
// returned by the action that failed.