I am facing a problem while implementing micro application in which i want a middle ware that is executed after response is send to browser. As mentioned in documentation of phalcon finish middle ware suppose to that work but its not working, browser still waiting to complete whole process then it return response.
my code is like:
$app->before(function() use ($app, $di) { $di->get('log')->log("This is a message before"); $di->get('log')->close(); });
$testCtrl = new testCtrl();
$app->get('/ctrltest', array($testCtrl, "indexAction"));
$app->after(function() use ($app, $di) {
echo "after";
$di->get('log')->log("This is a message after");
$di->get('log')->close();
});
$app->finish(function() use ($app, $di) {
$count = 100000;
while ($count) {`enter code here`
$di->get('log')->log("count " . $count);
$count--;
}
});
the response is coming after the whole loop is executed. Any sample code or some suggestion will be helpful
Related
So I'm trying to use guzzle for a couple of concurrent requests. I've seen several examples online and this is what I came up with, but can't seem to get it to work. No errors, no warnings, nothing. I've tried logging inside each promise but nothing happens.
And I know for sure that nothing is happening because nothing is getting inserted in the DB. Any ideas what I'm missing? (I'm yielding each request with its respective then because at the end of each promise, the DB operations are specific to that user)
use GuzzleHttp\Promise\EachPromise;
use Psr\Http\Message\ResponseInterface;
$promises = (function () use($userUrls){
$userUrls->each(function($user) {
yield $this->client->requestAsync('GET', $user->pivot->url)
->then(function (ResponseInterface $response) use ($user) {
$this->dom->load((string)$response->getBody());
// ... some db stuff that inserts row in table for this
// $user with stuff from this request
});
});
});
$all = new EachPromise($promises, [
'concurrency' => 4,
'fulfilled' => function () {
},
]);
$all->promise()->wait();
Not sure wht you don't get an error, but your generator is definitely wrong.
use Psr\Http\Message\ResponseInterface;
use function GuzzleHttp\Promise\each_limit_all;
$promises = function () use ($userUrls) {
foreach ($userUrls as $user) {
yield $this->client->getAsync($user->pivot->url)
->then(function (ResponseInterface $response) use ($user) {
$this->dom->load((string)$response->getBody());
// ... some db stuff that inserts row in table for this
// $user with stuff from this request
});
};
};
$all = each_limit_all($promises(), 4);
$all->promise()->wait();
Note foreach instead of $userUrls->each(), it's important because in your version generator function is the function that is passes to ->each() call, not the one you assign to $promise.
Also note that you must activate the generator (call $promises() as pass the result, not pass the function itself to Guzzle).
Otherwise all looks good, try the code with my changes.
I have a long task for a slim controller, I would like to early end the output to client and then continue the backend elaboration.
$app->get("/test",function() use($app){
$app->render("page.html"); //this is the client output
$app->easlyStop(); //a slim hypothetical command to call
$task=new MyTask();
$task->longAsyncTask(); //this take a few, client don't have to wait.
});
Is there a solution with Slim?
The easiest option here is to call a method with a system call and return before it finishes:
exec('/bin/php /path/to/a/script.php > /dev/null &');
Note that this is a simplification as PHP is request oriented, which means that a new process is started for every request, and the webserver sends the response to the user once the request is finished. You could use flush and other techniques, but these are prone to errors and depends on the configurations of the webserver too.
This is a method for Slim controller with Json view:
$app->get( '/test/', function () use($app) {
$app->view = new Json();
try{
//here the output of Json view
$model=["myjsondata"=>[]];
$app->render(200,$model);
}catch (\Slim\Exception\Stop $e) {}
//following code is copied from Slim->run() to early output
$app->response()->headers->replace(["Content-Length"=>$app->response()->length()]);
$app->response()->headers->replace(["Connection"=>"close"]);
list($status, $headers, $body) = $app->response->finalize();
\Slim\Http\Util::serializeCookies($headers, $app->response->cookies, $app->settings);
if (headers_sent() === false) {
if (strpos(PHP_SAPI, 'cgi') === 0) {
header(sprintf('Status: %s', \Slim\Http\Response::getMessageForCode($status)));
} else {
header(sprintf('HTTP/%s %s', $app->config('http.version'), \Slim\Http\Response::getMessageForCode($status)));
}
foreach ($headers as $name => $value) {
$hValues = explode("\n", $value);
foreach ($hValues as $hVal) {
header("$name: $hVal", false);
}
}
}
if (!$app->request->isHead()) {
echo $body;
}
//early output to client
ob_end_flush();
ob_flush();
flush();
if (session_id()) session_write_close();
//my async job
sleep(5);
});
I think this can be easily insert in a Slim plugin. This works only with Json view becase this is my need but it can be used with Twig or other Slim views getting output with ob* php functions instead of catching the Stop() exception.
I have created a soft phone for use with Twilio, using Twilio.js (1.4) and the Twilio REST API.
On the connection callback, I have a need to fetch the childSid for a call. To accommodate this I created a route in my Laravel app to use the Calls list resource and get it into the browser using jQuery.get() on the connection callback.
For some reason the API does not respond at all if I don't first wait about 12 seconds after the initial connection. After using sleep(12) in my PHP function I can successfully read the calls and filter for the ParentSid with no issues.
Is there a reason the API will not respond if invoked too soon after a connection is made via Twilio.js? It seems to only do this when I'm using $client->calls>read(). I have no problem retrieving a parentCallSid from a call immediately using $client->calls($callSid)->fetch().
Here is the original code:
public function showChildCallSid(Request $request, Client $client) {
$callSid = $request->input('CallSid');
sleep(12); // only works after waiting about 12 seconds
$call = $client->calls->read(['ParentCallSid' => $callSid])[0];
return $call->sid;
}
I believe the issue was ultimately a problem with syntax. I revised to the code as shown below and it works very well now (only needing a 1-second pause usually):
public function showChildCallSid(Request $request, Client $client) {
$callSid = $request->input('CallSid');
$attempt = 1;
$maxAttempts = 15;
do {
$calls = $client->calls->read(['ParentCallSid' => $callSid]);
if (sizeof($calls) > 0) {
break;
}
sleep(1);
$attempt++;
} while ($attempt < $maxAttempts);
$childSid = $calls[0]->sid;
return $childSid;
}
I am starting a long running task that returns incremental output about the tasks progress with the Symfony Process component.
One of the examples shows how to get real time output and another example shows how to run an asynchronous task.
What I am trying to achieve is sto pass the result of getIncrementalOutput back to the ajax polling function so I can update the front end in real time.
It seems in either case the process->start() is blocking because my ajax call takes a minute to return and by that time the task has finished.
I guess I'm trying to avoid writing the progress to a db or a file and get the output directly from the running PHP task.
Not sure it's possible.
Although I don't fully understand what you want to create, I have written something similar and looking at it might answer your question:
First I created a Command that does the long-running task:
class GenerateCardBarcodesCommand extends Command
{
protected function configure()
{
$this
->setName('app:generate-card-barcodes')
->setDescription('Generate the customer cards with barcodes')
->addArgument('id', InputArgument::REQUIRED, 'id of the Loy/Card entity')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$id = $input->getArgument('id');
// generate stuff and put them in the database
}
}
In the controller the Process is started and there's an ajax action
class CardController extends Controller
{
public function newAction(Request $request)
{
// run command in background to start generating barcodes
// NOTE: unset DYLD_LIBRARY_PATH is a fix for MacOSX develop using MAMP.
// #see http://stackoverflow.com/questions/19008960/phantomjs-on-mac-os-x-works-from-the-command-line-not-via-exec
$process = new Process(sprintf('unset DYLD_LIBRARY_PATH ; php ../../apps/spin/console spin:loy:generate-card-barcodes %d', $entity->getId()));
$process->start();
sleep(1); // wait for process to start
// check for errors and output them through flashbag
if (!$process->isRunning())
if (!$process->isSuccessful())
$this->get('session')->getFlashBag()->add('error', "Oops! The process fininished with an error:".$process->getErrorOutput());
// otherwise assume the process is still running. It's progress will be displayed on the card index
return $this->redirect($this->generateUrl('loy_card'));
}
public function ajaxCreateBarcodesAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $this->getEntity($id);
$count = (int)$em->getRepository('ExtendasSpinBundle:Loy\CustomerCard')->getCount($entity);
return new Response(floor($count / ($entity->getNoCards() / 100)));
}
}
// in the twig template the ajax is retrieved, which is simply a number from 0 to 100, which is used in the jquery ui progressbar.
{{ 'Processing'|trans }}...
<script type="text/javascript">
$(function() {
function pollLatestResponse() {
$.get("{{ path('loy_card_ajax_generate_barcodes', {'id': entity[0].id}) }}").done(function (perc) {
if (perc == 100)
{
clearInterval(pollTimer);
$('#download-{{entity[0].id}}').show();
$('#progress-{{entity[0].id}}').hide();
}
else
{
$('#progress-{{entity[0].id}}').progressbar("value", parseInt(perc));
}
});
}
var pollTimer;
$(document).ready(function () {
$('#progress-{{entity[0].id}}').progressbar({"value": false});
pollTimer = setInterval(pollLatestResponse, 2000);
});
});
</script>
I need to return from a function call once a React/Promise has been resolved. The basic idea is to fake a synchronous call from an ansynchronous one. This means that the outer function must return a value once a promise has been resolved or rejected.
This is to create a driver for RedBeanPHP using React/Mysql. I am aware that this will likely lead to CPU starvation in the React event loop.
My initial idea was to use a generator then call yield inside a \React\Promise\Deferred::then callback.
function synchronous()
{
$result = asynchronous();
}
function asynchronous()
{
$deferred = new \React\Promise\Deferred;
$sleep = function() use ($deferred)
{
sleep(5);
$deferred->resolve(true);
};
$deferred->then(function($ret) {
yield $ret;
});
$sleep();
}
The PHP generator class, AFAICT, is only directly constructable by the PHP engine itself. The then callback would need to directly invoke send on the generator of the asynchronous function for this to work.
PHP lacks both continuations as well as generator delegation, which would make it possible to call yield from inside a nested callback, making this entirely impossible to achieve for the moment.
ReactPhp offers the async tools package which has an await function.
Code can then become:
function synchronous()
{
$result = \React\Async\await(asynchronous());
}
function asynchronous()
{
$deferred = new \React\Promise\Deferred;
$sleep = function() use ($deferred)
{
sleep(5);
$deferred->resolve(true);
};
$sleep();
return $deferred->promise();
}