/** * @brief redis协程调度 * @param type $callback */ public function execute($callback) { $method = array_shift($this->_arguments); array_push($this->_arguments, $callback); try { call_user_func_array(array($this->_redis, $method), $this->_arguments); } catch (\Exception $ex) { \Aha\Log\Sys::log()->error("[REDIS_COROUTINE_EXECUTE_EXCEPTION]" . $ex->getMessage()); } }
/** * @brief 接收响应数据的callback * @param \swoole_client $client * @param type $data */ public function onReceive(\swoole_client $client, $data) { if (null !== $this->_timer) { //\Aha\Network\Timer::del($this->_timer); } $response = array('errno' => \Aha\Network\Client::ERR_SUCESS, 'errmsg' => 'sucess', 'requestId' => $this->_requestId, 'const' => microtime(true) - $this->_const, 'data' => $data); try { call_user_func($this->_callback, $response); } catch (\Exception $ex) { \Aha\Log\Sys::log()->error("TcpClient callback failed![exception]" . $ex->getMessage()); } $this->_connectionManager(); }
/** * @brief barrier wait [multi concurrent] * @param type $data * @return string */ public function wait($data) { $this->_arrResponses[$data['requestId']] = $data; if (count($this->_arrResponses) !== count($this->_arrClients)) { return AHA_AGAIN; } $response = array('errno' => \Aha\Network\Client::ERR_SUCESS, 'errmsg' => 'sucess', 'requestId' => $this->_requestId, 'const' => microtime(true) - $this->_const, 'data' => $this->_arrResponses); try { call_user_func($this->_callback, $response); } catch (\Exception $ex) { \Aha\Log\Sys::log()->error("MultiClient callback failed![exception]" . $ex->getMessage()); } }
/** * @brief 读取管道中的消息包体 * @param \swoole_process $process */ public function readPipe(\swoole_process $process) { while (false !== ($content = $process->read())) { if (false === $content) { \Aha\Log\Sys::log()->error(array('IPC_PIPE_READ_ERR' => $content)); break; } else { $this->append($content); } if (strlen($content) < 8191) { break; } } }
/** * @brief 解析http response * @param \swoole_client $client * @param type $data * @return string */ protected function _unPackResponse(\swoole_client $client, $data) { $this->_buffer .= $data; if (empty($this->_responseHeader) && strrpos($this->_buffer, "\r\n\r\n")) { $this->_unPackResponseHeader(); } if (empty($this->_responseHeader)) { return AHA_AGAIN; } if (AHA_AGAIN === $this->_unPackResponseBody()) { return AHA_AGAIN; } if (null !== $this->_timer) { //\Aha\Network\Timer::del($this->_timer); } if (isset($this->_responseHeader['content-encoding'])) { $this->_responseBody = \Aha\Client\Http::gzDecode($this->_responseBody, $this->_responseHeader['content-encoding']); } $response = array('errno' => \Aha\Network\Client::ERR_SUCESS, 'errmsg' => 'sucess', 'requestId' => $this->_requestId, 'const' => microtime(true) - $this->_const, 'data' => array('header' => $this->_responseHeader, 'body' => $this->_responseBody)); try { call_user_func($this->_callback, $response); } catch (\Exception $ex) { \Aha\Log\Sys::log()->error("HttpClient callback failed![exception]" . $ex->getMessage()); } $this->_connectionManager(); }
/** * @brief 协程堆栈调度 * @return type */ public function run(\Generator $generator) { for (;;) { try { //异常处理 if (null !== $this->_exception) { $generator->throw($this->_exception); $this->_exception = null; continue; } //协程堆栈链的下一个元素 $current = $generator->current(); //协程堆栈链表的中断内嵌 if ($current instanceof \Generator) { $this->_coroutineStack->push($generator); $generator = $current; continue; } //syscall中断 if ($current instanceof \Aha\Coroutine\SystemCall) { return $current; } //retval中断 $isReturnValue = $current instanceof \Aha\Coroutine\RetVal; if (!$generator->valid() || $isReturnValue) { if ($this->_coroutineStack->isEmpty()) { return; } $generator = $this->_coroutineStack->pop(); $generator->send($isReturnValue ? $current->getvalue() : $this->_sendValue); $this->_sendValue = null; } //异步网络IO中断 if ($this->_isAhaInterrupt($current)) { $this->_coroutineStack->push($generator); $this->_ahaInterrupt($current); return; } //当前协程堆栈元素可能有多次yeild 但是与父协程只有一次通信的机会 在通信前运行完 $generator->send(is_null($current) ? $this->_sendValue : $current); $this->_sendValue = null; while ($generator->valid()) { $current = $generator->current(); $generator->send(is_null($current) ? $this->_sendValue : $current); $this->_sendValue = null; } //协程栈是空的 已经调度完毕 if ($this->_coroutineStack->isEmpty()) { return; } //把当前结果传给父协程栈 $generator = $this->_coroutineStack->pop(); $data = is_null($current) ? $this->_sendValue : $current; $this->_sendValue = null; $generator->send($data); } catch (\Exception $ex) { \Aha\Log\Sys::log()->error("[Coroutine_Task_Run_Exception]" . $ex->getMessage()); if ($this->_coroutineStack->isEmpty()) { return; } } } }
/** * @brief 当worker/task进程发生异常会在Manager进程内回调此函数 * 主要用于监控和报警 很有可能遇到了致命错误或者coredump */ public function onWorkerError(\swoole_server $server, $workerId, $workerPid, $exitCode) { \Aha\Log\Sys::log()->error("[onWorkerError_CALLBACK] [workerId]{$workerId} [workerPid]{$workerPid} [exitCode]{$exitCode}"); }
/** * @brief 在preDispatch 中触发 * @throws Exception */ public function dispatchLoop() { $action = $this->_objRouter->getAction(); $objAction = new $action($this); if (!is_subclass_of($objAction, '\\Aha\\Mvc\\Action')) { throw new \Exception("class {$action} is not extends \\Aha\\Mvc\\Action"); } try { call_user_func(array($objAction, 'before'), $this); } catch (\Exception $e) { \Aha\Log\Sys::log()->error('\\Aha\\Mvc\\Action dispatchLoop callback exception:' . $e->getMessage()); } }
/** * @brief query失败 释放资源 callback 上层调用query的时候也不用进行错误处理 * @param type $callback * @param type $dbSock */ protected function _queryFailedNotify($callback, $dbSock = null) { if (null !== $dbSock) { $this->_close($dbSock); } try { call_user_func($callback, false, false, false); } catch (\Exception $e) { \Aha\Log\Sys::log()->error("Mysqli _queryFailedNotify Exception: {$e->getMessage()}"); } }
/** * @brief commit或者rollback失败 * @return boolean */ private function _commitOrRollbackFailed() { try { call_user_func($this->_callback, false, false, false); } catch (\Exception $e) { \Aha\Log\Sys::log()->error("Mysqli transCallback Exception[commit failed]: {$e->getMessage()}"); } $this->_clean(); self::$_TransGc[] = $this; return false; }
/** * @brief 发生错误时的回调 * @param \swoole_client $client */ public function onError(\swoole_client $client) { $response = array('errno' => \Aha\Network\Client::ERR_UNEXPECT, 'errmsg' => array('errCode' => $client->errCode, 'error' => socket_strerror($client->errCode)), 'requestId' => $this->_requestId, 'const' => microtime(true) - $this->_const, 'data' => array()); if (is_callable($this->_callback)) { try { call_user_func($this->_callback, $response); } catch (\Exception $ex) { \Aha\Log\Sys::log()->error("Client onError![exception]" . $ex->getMessage()); } } if ($client->sock && $client->isConnected()) { $client->close(); } else { $this->_free(); } }
/** * @brief redis连接池close事件 * @param \swoole_client $cli * @return type */ public function onClose(\swoole_client $cli) { if (!empty($this->_package)) { \Aha\Log\Sys::log()->warning("Redis Warning: Maybe receive a Close event , " . "such as Redis server close the socket !"); return; } $callback = $this->_callback; $arguments = $this->_arguments; $this->_free(); try { call_user_func($callback, false, $arguments['callback'], $this, 'Redis closed timeout'); } catch (\Exception $ex) { \Aha\Log\Sys::log()->error("Redis Closed notify callback![exception]" . $ex->getMessage()); } }