/** * This method is final because most queries will need to construct a * @{class:DiffusionRequest} and use it. Consolidating this codepath and * enforcing @{method:getDiffusionRequest} works when we need it is good. * * @{method:getResult} should be overridden by subclasses as necessary, e.g. * there is a common operation across all version control systems that * should occur after @{method:getResult}, like formatting a timestamp. */ protected final function execute(ConduitAPIRequest $request) { $drequest = DiffusionRequest::newFromDictionary(array('user' => $request->getUser(), 'callsign' => $request->getValue('callsign'), 'branch' => $request->getValue('branch'), 'path' => $request->getValue('path'), 'commit' => $request->getValue('commit'))); // Figure out whether we're going to handle this request on this device, // or proxy it to another node in the cluster. // If this is a cluster request and we need to proxy, we'll explode here // to prevent infinite recursion. $is_cluster_request = $request->getIsClusterRequest(); $repository = $drequest->getRepository(); $client = $repository->newConduitClient($request->getUser(), $is_cluster_request); if ($client) { // We're proxying, so just make an intracluster call. return $client->callMethodSynchronous($this->getAPIMethodName(), $request->getAllParameters()); } else { // We pass this flag on to prevent proxying of any other Conduit calls // which we need to make in order to respond to this one. Although we // could safely proxy them, we take a big performance hit in the common // case, and doing more proxying wouldn't exercise any additional code so // we wouldn't gain a testability/predictability benefit. $drequest->setIsClusterRequest($is_cluster_request); $this->setDiffusionRequest($drequest); return $this->getResult($request); } }
/** * This method is final because most queries will need to construct a * @{class:DiffusionRequest} and use it. Consolidating this codepath and * enforcing @{method:getDiffusionRequest} works when we need it is good. * * @{method:getResult} should be overridden by subclasses as necessary, e.g. * there is a common operation across all version control systems that * should occur after @{method:getResult}, like formatting a timestamp. */ protected final function execute(ConduitAPIRequest $request) { $identifier = $request->getValue('repository'); if ($identifier === null) { $identifier = $request->getValue('callsign'); } $drequest = DiffusionRequest::newFromDictionary(array('user' => $request->getUser(), 'repository' => $identifier, 'branch' => $request->getValue('branch'), 'path' => $request->getValue('path'), 'commit' => $request->getValue('commit'))); if (!$drequest) { throw new Exception(pht('Repository "%s" is not a valid repository.', $identifier)); } // Figure out whether we're going to handle this request on this device, // or proxy it to another node in the cluster. // If this is a cluster request and we need to proxy, we'll explode here // to prevent infinite recursion. $is_cluster_request = $request->getIsClusterRequest(); $viewer = $request->getUser(); $repository = $drequest->getRepository(); $client = $repository->newConduitClient($viewer, $is_cluster_request); if ($client) { // We're proxying, so just make an intracluster call. return $client->callMethodSynchronous($this->getAPIMethodName(), $request->getAllParameters()); } else { // We pass this flag on to prevent proxying of any other Conduit calls // which we need to make in order to respond to this one. Although we // could safely proxy them, we take a big performance hit in the common // case, and doing more proxying wouldn't exercise any additional code so // we wouldn't gain a testability/predictability benefit. $drequest->setIsClusterRequest($is_cluster_request); $this->setDiffusionRequest($drequest); // TODO: Allow web UI queries opt out of this if they don't care about // fetching the most up-to-date data? Synchronization can be slow, and a // lot of web reads are probably fine if they're a few seconds out of // date. id(new DiffusionRepositoryClusterEngine())->setViewer($viewer)->setRepository($repository)->synchronizeWorkingCopyBeforeRead(); return $this->getResult($request); } }