0

I am creating an analytics storage process (using elastic search) where I need to add the items to be stored in elastic from my controller. But then I want to wait until after the response has been sent to the user to actually do the processing. I don't want the user to have to wait for this process to complete before getting the server response.

I am planning on running the processing part using:

App::finish(function(){
   // DO THE PROCESSING
})

I know that this will run after the response has been sent. However, I am not sure how to get the data which has been compiled in a controller (or any class) to be referenced in the App::finish() closure method.

I have tried using App::singleton() but there are many instances where I need to be able to continually 'set' the data, I can't just set it once. I guess I am essentially looking for a global variable that I can manipulate but I know that doesn't exist in Laravel.

Another option is to use Session::push() and Session::get() but right now I have my Session storage using memcached for this app and I would rather not do additional I/O on memcached when I could just be storing the data needed to be saved in temporary memory.

Seems like I just need a simple container to write to and read from which is saved only in memory but I cannot find that in the Laravel docs.

phirschybar
  • 8,357
  • 12
  • 50
  • 66
  • As far as I know you can't do something after the request has been sent to the client. I think queues are the way to go... – lukasgeiter Jan 08 '15 at 18:46
  • @lukasgeiter -- hmm seems like `App::finish()` will do the trick. fingers crossed. – phirschybar Jan 08 '15 at 19:32
  • Really? That kind of surprises me... So the only problem is using data you set in the controller in `App::finish()`? – lukasgeiter Jan 08 '15 at 19:41
  • @lukasgeiter - you are right. When App::finish() runs the rest of the App data appears to be gone. oh well.. – phirschybar Jan 08 '15 at 20:48
  • I'll try some things and post and answer if I find something... – lukasgeiter Jan 08 '15 at 20:49
  • 1
    I just did a `sleep(10)` test and the request even took 10 seconds when I put the sleep inside `App::finish`. So I still think it doesn't run after the request. Even though [the docs](http://laravel.com/docs/4.2/lifecycle#application-events) say "The finish event is called after the response from your application has been sent back to the client" – lukasgeiter Jan 08 '15 at 21:21

2 Answers2

0

You might be able to use the __destruct() magic method on whichever controllers you need to do the processing on.

You could also potentially implement it in BaseController as well if it should run for all controllers.

Another option would be to use sqlite in memory. Simply create a new connection

    'sqlite_memory' => array(
        'driver'   => 'sqlite',
        'database' => ':memory:',
        'prefix'   => '',
    ),

Then you can use DB::connection('sqlite_memory') to use that connection and store/save whatever you need using the query builder.

user1669496
  • 32,176
  • 9
  • 73
  • 65
0

You can pass data to the closure using "use".

In PHP 5.3.0, what is the function "use" identifier?

I ended up using something like this for storing data in the cache after returning the data to the user.

App::finish(function($request, $response) use ($id, $json){
    Cache::put('key_'.$id, $json, 1440);
});
Community
  • 1
  • 1