0

I have a controller action which gets executed on one server. This action has to trigger two other services which can be on the same or other server (depending on the configured routes). Currently I always use HTTP requests. But if the services are on the same server I would rather like to call the appropriate controller (depending on the url, respecting custom routes) directly.

My code with requests looks like:

public function buildMultiple($platform, $name, $limit = null, $offset = null) {
    $config = $this->getDI()->get('config');

    $workerUrl = "{$config->application->WorkerUrl}/$platform/$name/compute/multiple/$limit/$offset";
    $response = HttpRequest::get($workerUrl);
    $data = json_decode($response)->data;

    $clientUrl = "{$config->application->ClientUrl}/$platform/$name/update/multiple";

    //TODO if the routes for the client are activated on this server then directly execute the controller
    //if($config->application->ClientRoutes) {
        // pseudocode:
        // $cont = $this->router->getControllerFromUri($clientUrl);
        // $result = $this->dispatcher($cont)->call($params, $postData);
        // return $result;
    //}
    // else:

    return HttpRequest::post($clientUrl, $data);
}
velop
  • 3,102
  • 1
  • 27
  • 30
  • So how to use HTTP requests if the routes don't exist on the local instance? Is that your question? – ʰᵈˑ May 09 '17 at 10:50
  • But action is an action, http endpoint, if you want it to be just generic method then move it to some generic method, don't really see problem. – Juri May 09 '17 at 10:58
  • @Juri the problem is that my router is routing to different controllers, depending on the url. If I want to call the appropriate controller and method I would have to duplicate the behaviour of the router. I would hope Phalcon has this already implemented in some way (see my updated pseudocode) – velop May 09 '17 at 14:19
  • Yes, just move your code which should be executed in both actions to seperated code. There is `$this->dispatcher->forward` but as the name tells it's forwarding action execution to other action. Like return here actually won't do anything. – Juri May 10 '17 at 09:57
  • Could you add some clarification. When you say same server do you mean same server different application? Or same application? If same application then could you not forward to the appropriate controller. If different application how about a hooks controller that can then forward? Or use a beanstalkd message queu with a background tasks that produce and consume? – baychae May 09 '17 at 23:57

1 Answers1

0

I found a possible solution:

public function buildMultiple($platform, $name, $limit = null, $offset = null) {
    $workerUrl = "/$platform/$name/compute/multiple/$limit/$offset";

    if($config->application->mviewWorkerRoutes) {
        $response = RoutesToControllerMapper::call($this, $workerUrl, [$platform, $name, $limit, $offset]);
        $data = $response['data'];
    }
    else {
        $response = HttpRequest::get($config->application->mviewWorkerUrl.$workerUrl, ['changed' => $changedFields]);
        $data = json_decode($response)->data;
    }

    $clientUrl = "/$platform/$name/update/multiple";

    return $config->application->mviewClientRoutes ?
        RoutesToControllerMapper::call($this, $clientUrl, [$platform, $name, $data]) :
        HttpRequest::post($config->application->mviewClientUrl.$clientUrl, $data);
}

whereas RoutesToControllerMapper look like:

class RoutesToControllerMapper
{
    public static function call($controller, $url, $arguments) {
        /** @var Micro $app */
        $app = $controller->getDI()->getApplication();
        /** @var Micro\LazyLoader $loader */
        list($loader, $method) = RoutesToControllerMapper::map($app, $url);
        return $loader->callMethod($method, $arguments);
    }

    /**
     * @param Micro $app
     */
    public static function map($app, $uri) {
        foreach($app->getRouter()->getRoutes() as $route) {
            if(preg_match($route->getCompiledPattern(), $uri) === 1) {
                $lastMatchedRoute = $route;
            }
        }

        if(!isset($lastMatchedRoute)) {
            return null;
        }

        $handler = $app->getHandlers()[$lastMatchedRoute->getRouteId()];
        /** @var Micro\LazyLoader $lazyLoader */
        $lazyLoader = $handler[0];
        return [$lazyLoader, $handler['1']];
    }
}
velop
  • 3,102
  • 1
  • 27
  • 30