Flush ActionController Action's output and continue

Hi

After beeing able to render my nodes to an variable (Render node to variable - #2 by sebobo - works great in general) my controller actions are becoming slower and slower (because the document is getting bigger and bigger). Until now I didn’t find a way on howto render a view using a Command Controller. This would be the most elegant way because I could use queuing services, but I tried a lot without sucess.

However, I now decided to run those background tasks after the (visible) controller results have been flushed to the user and to wait for the PDFs to become ready with a Java Script that triggers a RestController. All of this works, but I’m not able to flush the output to the user.

Calling:

session_write_close();
fastcgi_finish_request();

Ends up in a white page being flushed to the user.

Calling

echo $this->view->render();
session_write_close();
fastcgi_finish_request();

Flushes only the view’s template - but not the whole page. Is there a way to inform the controller that all content should be rendered and flushed?

Thank you for your help.

Jan

You might want to go full async processing for something like that and use e.g. the jobqueue package to send work to a background worker process. Less working against the technology, more robust/scalable handling and truly async.

but I tried a lot without sucess.

What did you struggle with exactly?

I’m currently using “OutOfBandRendering” (https://github.com/ttreeagency/OutOfBandRendering) to render round about 400 nodes into a HTML file. I don’t know how to initialize a view in a CommandController (to be able to call $this->view). The only way I know would be to use a CommandController to call a ActionController via curl/wget. Or is there another way?

You can use the StandaloneView to be able to render templates from outside the Web MVC stack. You maybe need to provide it with a useful ActionRequest (referencing a useful faked HttpRequest) to properly resolve absolute URLs in the template. But for a first step and testing, you can just create a new StandaloneView() and then set the template and render.

1 Like

Thank you. But how is it possible to not only paste some variables to this StandardView, but render complete nodes?

Ah, yes, sorry. In that case the https://github.com/neos/neos-development-collection/blob/master/Neos.Fusion/Classes/View/FusionView.php is probably what you need. The only issue is, you need to manually inject a ControllerContext with setControllerContext. You can take a look at https://github.com/neos/neos-development-collection/blob/master/Neos.Fusion/Classes/Core/RuntimeFactory.php#L56 on how you to create one. Afterwards you should have a fully working FusionView that you can use to render your nodes, by setting $view->assign('node', $myNodeToRender).

I also just created https://github.com/neos/neos-development-collection/pull/2721 that will allow to use the FusionView without manually creating the ControllerContext, similar to the StandaloneView of Fluid.

1 Like

Great. This worked. I used it in combination with https://github.com/Flowpack/jobqueue-doctrine and it’s a big improvement.

However, it seems as if it’s some slower than calling the same functions via ActionController by about 25%. Is this possible or might there be a problem with my implementation? I’ve disabled caches completly to be sure that’s not a caching issue.

25% sounds a bit much. How and what exactly did you measure? There’s a bit overhead creating a new php process and bootstrapping Flow to render a node async, but if you work multiple jobs with one call that can be alleviated. Glad you got things working, that’s the first step. Optimization comes on top