2

I'm been a long time reading how to solve my problem, but I can't find the solution.

I'm working with symfony, and I have a long time process to execute when an user calls an action. Can I process the data when the request has finished? The purpose is launch a polling process from client with jQuery and wait until the process finish to redirect to another action.

Now, I'm doing that with a ContainerAwareCommand, but it waits until the background process finish.

Please, could you help me?

Thanks in advance.

XMP
  • 29
  • 3
  • Well. User do a POST request to server, including a big file. I need to process that file, but I don't want to block the request until processing has finished. My purpose is process that big file in background, and poll from browser to know when process is complete. Have you enough details? – XMP Sep 07 '17 at 22:44

2 Answers2

1

Yes, it's possible to do some background process in Symfony after Response was sent to the user.

You need to write a listener for kernel.terminate event. And define your long-running process inside of callback.

Just be aware of few things:

  • This techniek does not work if Response is send in encoded gzip format. So, you should force apache/nginx not to use gzip for this particular response.
  • It's pretty complex to set any session data during this request, because session will be set only after your long-running process is finished. It means, that you need to find an alternative to flashbag messages.
Maksym Moskvychev
  • 1,471
  • 8
  • 11
  • Hi @Maksym Moskvychev! As you suggested me, I have implemented a listener for kernel.terminate event, but even I modified my AppKernel to implements TerminableInterface as I read in documentation, request from browser does not end until the method that I execute in this listener ends. public function onTerminate(PostResponseEvent $event) { sleep(60); } public static function getSubscribedEvents() { return array( KernelEvents::TERMINATE => 'onTerminate', ); } Do you know where is the problem? Thanks in advance. – XMP Sep 09 '17 at 10:10
  • Are you using app_dev.php ? Usually this works only in prod env. Also check in network tab in browser, are there content-encoding: gzip header? If yes - then it's a problem. – Maksym Moskvychev Sep 09 '17 at 11:05
  • Yes, It seems that gzip is enabled. I'm searching how disable it only for this action but I can't find the solution. I'm not very acquainted with .htaccess and I don't know if it is possible to disable compression directly from code in Symfony. – XMP Sep 09 '17 at 11:15
  • You can disable it from Symfony. What server are you using? – Maksym Moskvychev Sep 09 '17 at 11:18
  • In dev environment, I'm using Apache. – XMP Sep 09 '17 at 11:19
  • apache_setenv('no-gzip', '1'); http://php.net/manual/en/function.apache-setenv.php#60530 – Maksym Moskvychev Sep 09 '17 at 11:24
  • https://stackoverflow.com/questions/10267061/for-php-flush-how-to-disable-gzip-for-specific-file – Maksym Moskvychev Sep 09 '17 at 11:25
  • Yes, I've already see that info, but where I have to call it? I think that it's necessary before ob_start, and that is called before the controller. – XMP Sep 09 '17 at 11:27
  • You can call it any place inside your controller. – Maksym Moskvychev Sep 09 '17 at 11:32
  • It does not work :( I have tried including that line in a kernel.request listener, but the result is the same – XMP Sep 09 '17 at 11:38
  • Usually you write that line inside of your Action. Try post another question here. Describe what server you using, how it's configured, php-fpm/module/cgi, etc and ask how to disable gzip from php. – Maksym Moskvychev Sep 09 '17 at 13:24
1

This is a good case for a queue such as RabbitMQ or Redis. Put a message into a queue as each file is uploaded. One or more PHP daemons read out of the queue, process each file, and update status for the user (e.g. update a row in a database).

This lets you run your processing on servers separate from your web requests and scales easily. With a queue you can also break your processing up into multiple concurrent tasks, if what you need to do allows it.

Matt S
  • 14,976
  • 6
  • 57
  • 76
  • Thanks for your response. Do you think this is the optimal solution for my problem? If I have understand you, daemon will be running forever, doing fetchs to database maybe each 15 seconds and it could be too much. Remember that the user is waiting and polling until the process end. Really thanks for your help. – XMP Sep 07 '17 at 23:31
  • I think this is the most scalable solution. Daemon(s) process from a queue and update status in a DB. The front-end of your app can make an AJAX request every 15 seconds to check the status in the DB. That's not much load. Or the user can leave the page and still find the status when they come back. – Matt S Sep 08 '17 at 12:57