mojolicious / mojo-pg

Mojolicious :heart: PostgreSQL
https://metacpan.org/release/Mojo-Pg
Artistic License 2.0
99 stars 46 forks source link

$pubsub->listen can not be used in the startup #28

Closed JianleiZhang closed 8 years ago

JianleiZhang commented 8 years ago

cann't use $pubsub->listen in startup:

sub startup {
  my $self = shift;
  $self->helper(pg => sub {state $pg = Mojo::Pg->new('postgresql:///db')});
    $self->pg->pubsub->listen(
    permission => sub {
      my ($pubsub, $payload) = @_;
      $self->get_permission_cache;
    });
...
}

However, such this statement in the help is the performance of normal:

$self->attr('permission');
  $self->helper(
    get_permission_cache => sub {
      $self->{permission} = {};
      Mojo::IOLoop->delay(
    sub {
      my $delay = shift;
      my $sql   = "SELECT roles.id,key FROM roles " .
                  "JOIN permissions ON permissions.id = ANY(roles.permissions)";
      $self->pg->db->query($sql, $delay->begin);
    },
    sub {
      my ($delay, $err, $result) = @_;
      if ($err or not $result->rows){
        # 考虑是否退出?
      }
      foreach ($result->hash){
        $self->{permission}->{$_->{key}}->{$_->{id}} = 1;
      }

      $self->pg->pubsub->unlisten('permission');
      $self->pg->pubsub->listen(
        permission => sub {
          my ($pubsub, $payload) = @_;
          $self->get_permission_cache;
        });
    });
    });
jberger commented 8 years ago

updated formatting

jberger commented 8 years ago

I don't understand the problem. Certainly listen does work in the startup method

JianleiZhang commented 8 years ago

sorry, I forget the running environment. It does not behave properly inside the hypnotoad server.

jberger commented 8 years ago

Until you have more details this has to be closed as not reproducible. It may be reopened with more details or a running example.

jberger commented 8 years ago

For the record, the pubsub system only works while the loop is running, so I guess I should say, listen works but you won't see any results until the loop starts; which happens after startup completes. In your delay example, you might try adding ->wait to the end to make it portable between before and after the loop starts.

JianleiZhang commented 8 years ago

I have a few tests:

Test 1)

sub startup {
  my $self = shift;
  $self->config(hypnotoad => {workers => 4});
  $self->helper(
    pg => sub {
      state $pg = Mojo::Pg->new('postgresql:///db')});

  $self->pg->pubsub->listen(
    cache => sub {
      my ($pubsub, $payload) = @_;
      $self->log->info($payload);
    });
}

Try to send a notify in other controller.

  $self->pg->pubsub->notify(cache => 'update!');

Nothing happens.

Test 2)

  $self->pg->pubsub->on(
    reconnect => sub {
      my ($pubsub, $db) = @_;
      $pubsub->listen(
        cache => sub {
          my ($pubsub, $payload) = @_;
          $self->log->info($payload);
        });
    });

Only one info contain the $payload when send notify once.

Test 3)

  $self->helper(
    test_pubsub => sub {
      Mojo::IOLoop->delay(
        sub {
          my $delay = shift;
          my $sql   = 'SELECT 1 + 1';
          $self->pg->db->query($sql, $delay->begin);
        },
        sub {
          $self->pg->pubsub->unlisten('cache');
          $self->pg->pubsub->listen(
            cache => sub {
              my ($pubsub, $payload) = @_;
              $self->log->info($payload);
            });
        });
    });

    $self->test_pubsub;

4 info contain the $payload, maybe from the 4 workers.

This is what I need.

also test redis pub/sub

  sub startup {
    my $self = shift;
    $self->config(hypnotoad => {workers => 4});
    $self->helper(redis => sub {state $redis = Mojo::Redis2->new()});

    $self->redis->subscribe(['cache']);
    $self->redis->on(
      message => sub {
        my (undef, $message, $channel) = @_;
        if ($channel eq 'cache') {
          $self->log->info($message);
        }
      });
  }

Only 3 info contain the $message, I don't know why.

kraih commented 8 years ago

There is fork-safety code in Mojo::Pg::PubSub (https://github.com/kraih/mojo-pg/blob/master/lib/Mojo/Pg/PubSub.pm#L31), so this might be a bug if that code doesn't work. Afraid i don't have time to take a closer look at it now.

kraih commented 8 years ago

There were bugs, but the behavior described here is intended i'm afraid. I've added a note to the docs. https://github.com/kraih/mojo-pg/commit/74d26c4d6160717caa0c2f39332ac892bbf779ca