/** * Dispatch a Photon request object and returns the request * object and the response object. * * @param $req Photon request object. * @return array(Photon request, Photon response) */ public static function dispatch($req) { Timer::start('photon.dispatch'); // FUTUREOPT: One can generate the lists at the initialisation // of the server to avoid the repetitive calls to // method_exists. $middleware = array(); foreach (Conf::f('middleware_classes', array()) as $mw) { $middleware[] = new $mw(); } $response = false; try { foreach ($middleware as $mw) { if (method_exists($mw, 'process_request')) { $response = $mw->process_request($req); if ($response !== false) { // $response is a response, the middleware has // preempted the request and the possible // corresponding view will not called. break; } } } if ($response === false) { $response = self::match($req); } $middleware = array_reverse($middleware); foreach ($middleware as $mw) { if (method_exists($mw, 'process_response')) { $response = $mw->process_response($req, $response); } } } catch (\Exception $e) { Event::send('\\photon\\core\\Dispatcher::dispatchException', null, $e); if (true !== Conf::f('debug', false)) { $response = new \photon\http\response\ServerError($e, $req); } else { $response = new \photon\http\response\ServerErrorDebug($e->getMessage()); $response->setContent($e, $req); } } $view_name = isset($req->view[0]['name']) ? $req->view[0]['name'] : 'not_defined'; Log::perf(array('photon.dispatch', $req->uuid, Timer::stop('photon.dispatch'), $view_name, array($req->method, $req->path))); return array($req, $response); }
/** * Process the request available on the socket. * * The socket is available for reading with recv(). */ public function processRequest($conn) { Timer::start('photon.process_request'); $uuid = request_uuid(); $mess = $conn->recv(); if ($mess->is_disconnect()) { // A client disconnect from mongrel2 before a answer was send // Use this event to cleanup your context (long polling socket, task queue, ...) $event_params = array('conn_id' => $mess->conn_id); Event::send('\\photon\\server\\Server\\processRequest::disconnect', null, $event_params); } else { // This could be converted to use server_id + listener // connection id, it will wrap but should provide enough // uniqueness to track the effect of a request in the app. $req = new \photon\http\Request($mess); $req->uuid = $uuid; $req->conn = $conn; list($req, $response) = \photon\core\Dispatcher::dispatch($req); // If the response is false, the view is simply not // sending an answer, most likely the work was pushed to // another backend. Yes, you do not need to reply after a // recv(). if (false !== $response) { if (is_string($response->content)) { $conn->reply($mess, $response->render()); } else { Log::debug(array('photon.process_request', $uuid, 'SendIterable')); $response->sendIterable($mess, $conn); } } } unset($mess); // Cleans the memory with the __destruct call. Log::perf(array('photon.process_request', $uuid, Timer::stop('photon.process_request'))); }
public function testTimerCount() { Timer::inc('sql_queries'); $this->assertEquals(1, Timer::get('sql_queries')); $this->assertEquals(3, Timer::get('not_set', 3)); Timer::inc('sql_queries'); $this->assertEquals(2, Timer::get('sql_queries')); }