gypark
gypark

Reputation: 622

mojolicious does not work in non-blocking way

At first, I'm sorry I'm not good at English.

I'm making a Mojolicious app.

My controller does some job using Mojo::UserAgent and uses the result when it makes the output.

my $ua = Mojo::UserAgent->new();
my $tx = $ua->head( $location );
my $result;

if ( $tx->res->code eq '200' ) {
    $result = 'good';
}
else {
    $result = 'bad';
}

# pass the result to the renderer's stash
$self->render( result => $result );

This code works well. It works on both my local machine and the server.

Next, I tried to make this $ua->head() non-blocking way, because it could take long time to complete. (I'm a novice and this is my first time to try non-blokcing code using Mojo, for your reference)

my $ua = Mojo::UserAgent->new();
my $result;

$self->render_later;
$ua->head( $location => sub {
    my ($ua, $tx) = @_;

    if ( $tx->res->code eq '200' ) {
        $result = 'good';
    }
    else {
        $result = 'bad';
    }
    $self->render( result => $result );
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

This approach also works well in my local machine (MacBook OSX 10.9.4, Perl 5.18, Standalone using morbo).

However, when I launch this code in the server, the server respond with "404 not found".

This server uses Nginx proxy, which forwards requests to working nodes.

browser -- Nginx -- Mojolicious App

So, I guess this proxy is related to my problem, but I have no idea how to fix it. I don't know even where I have to start from to find the exact cause.

Any advice would be appreciated.

P.S. I should have said "blocking method" works well both on my local machine and on the server. Only "non-blocking method" shows this problem.

Update (2014-08-21) : One of my friends who is a skillful Perl engineer said to me that it seems to be the problem between the event loop of Mojo and that of PSGI, that is, something like a compatibility problem. I can't understand what he said currently, but I'm trying to study more.

Upvotes: 1

Views: 837

Answers (2)

Logioniz
Logioniz

Reputation: 891

I think that proxy works well because you have http 404 (not http 502 or something else).

You must to run on your server mojolicious app under morbo too and using "print" debug your app.

I think that your controller with action not found or not found template.

By the way, what is $self->render(result = $result)? May be you want to write it $self->render(result => $result)?

So, if this is your problem then to detect this error you should look at log/development.conf or log/production.conf or in console where running app.


UPD.

I don't know, where problem, but this code will works well.

  my $result;

  $self->render_later;
  $self->ua->head('http://ya.ru' => sub {
      my ($ua, $tx) = @_;

      print $self->dumper($ua);


      if ( $tx->res->code eq '200' ) {
          $result = 'good';
      }
      else {
          $result = 'bad';
      }
      sleep 2;
      $self->render( data => $result );
  });
  Mojo::IOLoop->start unless Mojo::IOLoop->is_running;

So, $ua variable used from controller $self. So, may be it destroy when callback call by garbage collector. When you use $self->ua->... then ua object save in shared variable, so garbage collector not destroy it. Very interest example. Thanks.

Upvotes: 1

Chankey Pathak
Chankey Pathak

Reputation: 21676

From Mojolicious Cookbook

upstream myapp {
  server 127.0.0.1:8080;
}
server {
  listen 80;
  server_name localhost;
  location / {
    proxy_pass http://myapp;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto "http";
  }
}

Upvotes: 1

Related Questions