func (s *Sat) handleFnResult(msg grav.Message, result interface{}, fnErr error) {
	// first unmarshal the request and sequence information
	req, err := request.FromJSON(msg.Data())
	if err != nil {
		s.l.Error(errors.Wrap(err, "failed to request.FromJSON"))
		return
	}

	ctx := vk.NewCtx(s.l, nil, nil)
	ctx.UseRequestID(req.ID)
	ctx.UseScope(loggerScope{req.ID})

	seq, err := sequence.FromJSON(req.SequenceJSON, req, s.e, ctx)
	if err != nil {
		s.l.Error(errors.Wrap(err, "failed to sequence.FromJSON"))
		return
	}

	// figure out where we are in the sequence
	step := seq.NextStep()
	if step == nil {
		ctx.Log.Error(errors.New("got nil NextStep"))
		return
	}

	step.Completed = true

	// start evaluating the result of the function call
	resp := &request.CoordinatedResponse{}
	var runErr rt.RunErr
	var execErr error

	if fnErr != nil {
		if fnRunErr, isRunErr := fnErr.(rt.RunErr); isRunErr {
			// great, it's a runErr
			runErr = fnRunErr
		} else {
			execErr = fnErr
		}
	} else {
		resp = result.(*request.CoordinatedResponse)
	}

	// package everything up and shuttle it back to the parent (atmo-proxy)
	fnr := &sequence.FnResult{
		FQFN:     msg.Type(),
		Key:      step.Exec.CallableFn.Key(), // to support groups, we'll need to find the correct CallableFn in the list
		Response: resp,
		RunErr:   runErr,
		ExecErr: func() string {
			if execErr != nil {
				return execErr.Error()
			}

			return ""
		}(),
	}

	if err := s.sendFnResult(fnr, ctx); err != nil {
		ctx.Log.Error(errors.Wrap(err, "failed to sendFnResult"))
		return
	}

	// determine if we ourselves should continue or halt the sequence
	if execErr != nil {
		ctx.Log.ErrorString("stopping execution after error failed execution of", msg.Type(), ":", execErr.Error())
		return
	}

	if err := seq.HandleStepErrs([]sequence.FnResult{*fnr}, step.Exec); err != nil {
		ctx.Log.Error(err)
		return
	}

	// load the results into the request state
	seq.HandleStepResults([]sequence.FnResult{*fnr})

	// prepare for the next step in the chain to be executed
	stepJSON, err := seq.StepsJSON()
	if err != nil {
		ctx.Log.Error(errors.Wrap(err, "failed to StepsJSON"))
		return
	}

	req.SequenceJSON = stepJSON

	s.sendNextStep(msg, seq, req, ctx)
}
// handleFnResult is mounted onto exec.ListenAndRun...
// when a meshed peer sends us a job, it is executed by Reactr and then
// the result is passed into this function for handling
handleFnResult is mounted onto exec.ListenAndRun
when a meshed peer sends us a job, it is executed by Reactr and then
the result is passed into this function for handling
// handleFnResult is mounted onto exec . ListenAndRun ... // when a meshed peer sends us a job it is executed by Reactr and then // the result is passed into this function for handling
func (s *Sat) handleFnResult(msg grav.Message, result interface{}, fnErr error) {
	req, err := request.FromJSON(msg.Data())
	if err != nil {
		s.l.Error(errors.Wrap(err, "failed to request.FromJSON"))
		return
	}
	ctx := vk.NewCtx(s.l, nil, nil)
	ctx.UseRequestID(req.ID)
	ctx.UseScope(loggerScope{req.ID})
	seq, err := sequence.FromJSON(req.SequenceJSON, req, s.e, ctx)
	if err != nil {
		s.l.Error(errors.Wrap(err, "failed to sequence.FromJSON"))
		return
	}
	step := seq.NextStep()
	if step == nil {
		ctx.Log.Error(errors.New("got nil NextStep"))
		return
	}
	step.Completed = true
	resp := &request.CoordinatedResponse{}
	var runErr rt.RunErr
	var execErr error
	if fnErr != nil {
		if fnRunErr, isRunErr := fnErr.(rt.RunErr); isRunErr {
			runErr = fnRunErr
		} else {
			execErr = fnErr
		}
	} else {
		resp = result.(*request.CoordinatedResponse)
	}
	fnr := &sequence.FnResult{
		FQFN:     msg.Type(),
		Key:      step.Exec.CallableFn.Key(), 
		Response: resp,
		RunErr:   runErr,
		ExecErr: func() string {
			if execErr != nil {
				return execErr.Error()
			}
			return ""
		}(),
	}
	if err := s.sendFnResult(fnr, ctx); err != nil {
		ctx.Log.Error(errors.Wrap(err, "failed to sendFnResult"))
		return
	}
	if execErr != nil {
		ctx.Log.ErrorString("stopping execution after error failed execution of", msg.Type(), ":", execErr.Error())
		return
	}
	if err := seq.HandleStepErrs([]sequence.FnResult{*fnr}, step.Exec); err != nil {
		ctx.Log.Error(err)
		return
	}
	seq.HandleStepResults([]sequence.FnResult{*fnr})
	stepJSON, err := seq.StepsJSON()
	if err != nil {
		ctx.Log.Error(errors.Wrap(err, "failed to StepsJSON"))
		return
	}
	req.SequenceJSON = stepJSON
	s.sendNextStep(msg, seq, req, ctx)
}
func ( s * Sat ) handleFnResult ( msg grav . Message , result interface { } , fnErr error ) { req , err := request . FromJSON ( msg . Data ( ) ) if err != nil { s . l . Error ( errors . Wrap ( err , " " ) ) return } ctx := vk . NewCtx ( s . l , nil , nil ) ctx . UseRequestID ( req . ID ) ctx . UseScope ( loggerScope { req . ID } ) seq , err := sequence . FromJSON ( req . SequenceJSON , req , s . e , ctx ) if err != nil { s . l . Error ( errors . Wrap ( err , " " ) ) return } step := seq . NextStep ( ) if step == nil { ctx . Log . Error ( errors . New ( " " ) ) return } step . Completed = true resp := & request . CoordinatedResponse { } var runErr rt . RunErr var execErr error if fnErr != nil { if fnRunErr , isRunErr := fnErr . ( rt . RunErr ) ; isRunErr { runErr = fnRunErr } else { execErr = fnErr } } else { resp = result . ( * request . CoordinatedResponse ) } fnr := & sequence . FnResult { FQFN : msg . Type ( ) , Key : step . Exec . CallableFn . Key ( ) , Response : resp , RunErr : runErr , ExecErr : func ( ) string { if execErr != nil { return execErr . Error ( ) } return " " } ( ) , } if err := s . sendFnResult ( fnr , ctx ) ; err != nil { ctx . Log . Error ( errors . Wrap ( err , " " ) ) return } if execErr != nil { ctx . Log . ErrorString ( " " , msg . Type ( ) , " " , execErr . Error ( ) ) return } if err := seq . HandleStepErrs ( [ ] sequence . FnResult { * fnr } , step . Exec ) ; err != nil { ctx . Log . Error ( err ) return } seq . HandleStepResults ( [ ] sequence . FnResult { * fnr } ) stepJSON , err := seq . StepsJSON ( ) if err != nil { ctx . Log . Error ( errors . Wrap ( err , " " ) ) return } req . SequenceJSON = stepJSON s . sendNextStep ( msg , seq , req , ctx ) }
handleFnResult is mounted onto exec.ListenAndRun
when a meshed peer sends us a job, it is executed by Reactr and then
the result is passed into this function for handling
handleFnResult is mounted onto exec . ListenAndRun when a meshed peer sends us a job it is executed by Reactr and then the result is passed into this function for handling
// first unmarshal the request and sequence information // figure out where we are in the sequence // start evaluating the result of the function call // great, it's a runErr // package everything up and shuttle it back to the parent (atmo-proxy) // to support groups, we'll need to find the correct CallableFn in the list // determine if we ourselves should continue or halt the sequence // load the results into the request state // prepare for the next step in the chain to be executed