-2

I want close a connection early in Laravel, i found the question:

How do I close a connection early?

the answer is:

<?php
    ob_end_clean();
    header("Connection: close");
    ignore_user_abort(true); // just to be safe
    ob_start();
    echo('Text the user will see');
    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush(); // Strange behaviour, will not work
    flush(); // Unless both are called !
    // Do processing here 
    sleep(30);
    echo('Text user will never see');
?>

but echo not work in Laravel Controller, when i change is to return, the code behind is not executed.

[update]

My question is:

I have a time-consuming task that needs to call a python script. This task may take 30 to 180 seconds. If I use the scheduled task in Laravel or the system's Conrtab timed task, the worst may be that the Python script will only run after 1 minute. This will make the user wait an extra minute, and the user experience is not very good.

So I hope to end the connection early to let the user see the response first, and call the Python script for task processing at the same time.

Currently I used two ajax requests to solve this problem, one of which is used to call the python script.

My question is to know if the same goal can be achieved without an additional request, or if there is a better solution.

Ismael Padilla
  • 5,246
  • 4
  • 23
  • 35
artwl
  • 3,502
  • 6
  • 38
  • 53
  • 6
    Aghrrr.... that code is not laravel'sk, you should use Queues and Jobs to solve your problem and fetch the data later, when the async code is done. – mrhn May 17 '21 at 13:26
  • @mrhn Thank you very much, but I want to know if it can be solved with Laravel – artwl May 19 '21 at 12:15
  • One answer made a while ago. It's about php-cli, likely a bit dirty for corporate style coding, but it does work perfectly and this never causes issues. Actually the simplest straightforward way, see explaination https://stackoverflow.com/a/57697076/2494754 – NVRM May 19 '21 at 12:24
  • 4
    Queues and jobs are a laravel concept, i can draw up an example but i need more context for the problem. What do you want to do? Tbh, the code you provided is pretty bad for a laravel application and should not be implemented that way. – mrhn May 19 '21 at 12:32
  • fastcgi_finish_request() does the job. You probably shouldn't call it yourself. You can add a middleware and put your time consuming task in the terminate() function. You can also consider using queue and jobs. – Hamid Alaei May 20 '21 at 10:35

4 Answers4

1

In your case it is better to use Http

use Illuminate\Support\Facades\Http;

and in your function use this

$response = Http::timeout(30)->get('https://www.example.com');

you can add more of your code to fix problem as well

Wassim Al Ahmad
  • 1,102
  • 2
  • 7
  • 23
0

You can try using HTML5 property server-sent events, Link https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

Traditionally, a web page has to send a request to the server to receive new data; that is, the page requests data from the server. With server-sent events, it's possible for a server to send new data to a web page at any time, by pushing messages to the web page. These incoming messages can be treated as Events + data inside the web page.
You'll need a bit of code on the server to stream events to the front-end, but the client side code works almost identically to websockets in part of handling incoming events. This is one-way connection, so you can't send events from a client to a server.

Akshay Vanjare
  • 655
  • 3
  • 10
0

I have faced the same case with you. Namely running certain scripts asyncronous to keep response times fast. Some of the methods, like the ones you mentioned, did not work as expected. I have also used Spatie\Async but the php module doesn't work when running in apache2. So the solution, I use the exec function to run the command line on which it runs in the background. This may be a bit risky, but with care it may be one of the best practices.

exec('(/path/to/script > /dev/null) &');
Toto Prasetyo
  • 148
  • 1
  • 6
-1

I suggest using dispatchAfterResponse combined with broadcasting system (e.g. pusher). This way you can notify client not only about start and end, but about all intermediate steps and you won't need extra http requests. So the whole process looks more interactive. There are some considerations about dispatchAfterResponse that must be careful about which is mentioned in documentation but I believe you can pass limitations of dispatchAfterResponse with correct server config . If you don't trust dispatchAfterResponse, try queue jobs.

MHIdea
  • 806
  • 3
  • 8