My task is to develop a eCommerce shop with Laravel 8. I have implemented the product retrieving part as a job and in the controller I have dispatch. Idea is to improve efficiency and support concurrent users and handle parallel requests.
Below code resides in AppJobs
namespace AppJobs;
use IlluminateBusQueueable;
use IlluminateContractsQueueShouldQueue;
use IlluminateFoundationBusDispatchable;
use IlluminateQueueInteractsWithQueue;
use IlluminateQueueSerializesModels;
use IlluminateHttpRequest;
use IlluminateSupportFacadesDB;
use AppModelsProduct;
class GetProductList implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
$products = DB::table('tbl_mst_products')->get();
return response()->json(['products' => $products]);
}
}
Below is my controller code
namespace AppHttpControllers;
use IlluminateHttpRequest;
use AppJobsGetProductList;
class ProductController extends Controller
{
//
public function getProducts(){
GetProductList::dispatch();
}
}
I want to implement this in a API. Is this a good practice ? Also can anyone help me to show how to use this in API ?
I want to implement this in a REST API. Is this a good practice ? Also can anyone help me to show how to use this in REST API ?
2
Answers
As matiaslauriti explained previously I changed my controller as below.
Also I implemented api route under routes/api and below is my api.php
Now I am going to display data from that api and show it in my below blade view
Hope my approach is correct and it is align with the standards. But I don't know how to link that api call to blade view. I am seeking some help.
So, this could have a very long, but also opinionated answer, in my case I will not make it opinonated but just "basic" (or what the normal standard is, of course I could be not writting everything, or miss something).
To begin with, I think you wanted to create a job to handle "requests" because you want to have workers (maybe a lot of machines with queue workers) to handle this actions, so you can have a lot of requests and not saturate a server or similar, right?
If that is the case, this is not how you solve this issue (at least with Laravel), because a Job, by default, is asynchronous, if it is not, it does not exactly make a lot of sense to have it as a job (but you can run synchronous jobs). You may be thiking, okay then, I just run synchronous jobs, but those are run on the machine executing that code, it is not executed by another machine with queue workers.
One thing you can do is have some machines running this Laravel code, for example 5 (arbitrary number), and then you have a load balancer that will receive the request and send it to the less used machine (that is one way a load balancer can work, there are multiples, you will have to google that).
Let’s say you do create multiple machines and put a load balancer to handle the load, another thing to have in mind is the database (I will assume you will definitely use a database to store everything, you are not going to use anything special like a blockchain or anything "weird" or non-common like that), in that case you also have to have in mind that you could saturate the database due to reading data a lot of times and a lot of data per request. Same for writing to the database if multiple (A LOT of) buys are done in a second.
To solve that issue, you should have a cluster and usually a single writter and multiple readers, so you read data from another machine that has the data in sync (for example, for listing products, pre-procesed filters, etc), this way you user readers to get data from (and saturate them) instead of saturating the writer that is the most important one.
To continue solving performance issues, you could also use Redis (for example) and cache information, like some products that are visited multiple times per second(s), cache some sections (for example, phones section is visited multiple times per second, cache the entirety or the first pages of it if possible). Doing this also means that you have to refresh the cache when anything happens to the context of it, if there is one new phone on that section, you have to refresh that cache, else you will never show it, and a long etc related to caching.
You then have one more possible performance hit, the background, this means when someone buys a product, or triggers something that then requires multiple steps, for example, if a product is bought (payment accepted), you then need to trigger some events or similar and notify logistics, send emails to the buyer and seller, and more. That could 100% be solved by jobs and workers executing them, so you don’t hit the main machines showing data to the user (main web page app).
In a super TL;DR; layer your application acordingly, this is a very broad, opinionated, and custom solution topic.
Some tips related to the code you showed:
DB::table('tbl_mst_products')->get()
, use a model so you can use scopes, custom attributes and more.->get()
without filters, in your case, if you have 10.000 items to show, you are literally going to get 10.000 rows, store that in the server RAM, Laravel will process it (and maybe crash), and it depends if you will paginate it on the UI with Javascript (hence losing the remaining items, for example 9.990 if you display 10 per page). So use->paginate()
to already get the items per page and don’t waste resources, or add filters.json response
on a Job, so the job should not throw an exception, because you could in theory get what the job is returning, but jobs are not used to return stuff, if they need to "communicate" something, they use events or something else, but not a literalreturn
with data. And because you are not writingreturn
in your controller, even if you got a synchronous response back from the job in the controller, you are not returning it.