skip to Main Content

I’am using Laravel 11.x as Framework and currently trying to figure out "the best" way to handle a big process from the amazon sp-api. I want to handle the API Requests within Jobs and want to chain them for a bigger process. E.g. the process of getting a shipping label for an Fullfilment package need like ~16 steps. (a horrible thing..)

I create Jobs for each request and want to chain them as needed. e.g. each POST Request must follow a request to the operationStatus Ressource which should anwser finally with SUCCESS or FAILED.

So the question is, can I capsulate smaller processes in functions and chain them finally for the big process?
E.g. this are three functions which should be processed one after another:

public function createInboundPlan(Request $request){
    $uuid = Str::orderedUuid()->toString();
    Bus::chain([
        new CreateInboundPlan($uuid, $request),
        new GetInboundOperationStatus($uuid, Cache::pull($uuid.':'.'CreateInboundPlan'.':'.'operationId'), $request),
    ])->catch(function (Throwable $e) {
        // A job within the chain has failed...
    })->dispatch();
}

public function generatePackingOptions(string $inboundPlanId, Request $request){
    $uuid = Str::orderedUuid()->toString();
    Bus::chain([
        new GeneratePackingOptions($uuid, $inboundPlanId, $request),
        new GetInboundOperationStatus($uuid, Cache::pull($uuid.':'.'GeneratePackingOptions'.':'.'operationId'), $request),
    ])->catch(function (Throwable $e) {
        // A job within the chain has failed...
    })->dispatch();
}

public function listPackingOptions(string $inboundPlanId, Request $request){
    $uuid = Str::orderedUuid()->toString();
    Bus::chain([
        new ListPackingOptions($uuid, $inboundPlanId, $request),
        new SelectInboundPackingOption($uuid, Cache::pull($uuid.':'.'ListPackingOptions'.':'.'packingOptions'), $request),
    ])->catch(function (Throwable $e) {
        // A job within the chain has failed...
    })->dispatch();
}

Is there a way to archive something like this?

Bus::chain([
$this->createInboundPlan($request),
$this->generatePackingOptions($inboundPlanId, $request),
$this->generatelistPackingOptions($inboundPlanId, $request)
])->dispatch();

Currently the only Idea I have is to not work with functions and instead create "parent" jobs, which get chained. I mean I could just create a big chain for that big process and don’t capsulate everything, but I may need single parts of this later again and I like the idea of that structure^^

Greetings

2

Answers


  1. Chosen as BEST ANSWER

    Okay.. may I made this a bit too complicated.. After some further thinking about that structure I think it would be way more handy to dispatch directly depending tasks inside the initial Job.

    E.g. the POST Requests which need to call the operationStatus Ressource should do that inside their jobs after finishing succesfull their Request. Furthermore that way should be better for requests which are followed by a decision making job (listPlacements => decide which placement should be used), because no cache handling are needed that way.

    So I will build the jobs in a way that directly depending jobs(tasks) get dispatched inside. That way I capsulate already enough imo.

    The big processes still will get builded as chains as otherwise I would duplicate to much code.

    May that thinking process helps someone :D At least it helped me.


  2. I suggest you use Pipeline to merge the processes.

    use IlluminateDatabaseEloquentBuilder;
    use IlluminateSupportFacadesPipeline;
    
    class InboundPlanProcess
    {
        protected array $steps = [];
    
        public function __construct(array $steps)
        {
            // each step implement your interface 
            $this->steps = $steps;
        }
    
        public function apply(mixed $passedDataHere): mixed
        {
            return app(Pipeline::class)
                ->send($passedDataHere)
                ->through($this->steps)
                ->thenReturn();
        }
    }
        class CreateInboundPlan implements StepInterface {
          public function __invoke() {
            // 
          }
        } 
        class GeneratePackingOptions implements StepInterface {...}
    
    

    then you create all the steps

    class PlanController extends Controller
    {
        
        public function process(Request $request): JsonResponse
        {
            $pipeline = new InboundPlanProcess([
                CreateInboundPlan::class,
                GeneratePackingOptions::class,
                generatelistPackingOptions::class,
                .......... more
            ]);
    
            $result = $pipeline->apply(Product::query());
    
            // do something
        }
    

    If even one step goes wrong, the process will be aborted. For example, this is how middleware works in Laravel

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search