[dancer-users] Problems writing a Plugin

Alfonso Pinto alfonso.pinto at gmail.com
Fri Oct 13 19:38:09 BST 2017


Hi Clive,

Your "my variable" should be equals to my "has _client".
Anyway, I found the issue. I was using Plack::Handler::Starman to start the
app:

my $server = new Plack::Handler::Starman(listen => ['0.0.0.0:5000'],
>> proctitle => 0);
>
> $server->run(MyWeb::API->to_app);
>
> Doing it that way makes starman to preloads the app in the master process
and does copy on write to the workers. That makes it use the same context
for all the workers.

What I did is to use the same mechanism as when you run dancer2 gen -a
MyWeb::App:

> use MyWeb::App;
> MyWeb::App->to_app;


Then I can run it from cli using the starman command. This way it doesn't
preload the app unless --preload-app option is used.
And now it's working.

Thank you very much for your time.

Regards,
Alfonso

On Fri, Oct 13, 2017 at 8:11 PM, Clive Eisen <clive at hildebrand.co.uk> wrote:

> Do it the way I did it with a my variable outside to hold your handler.
> Then you will get one per child (well i do anyway)
>
> --
> Clive
>
> On 13 Oct 2017, at 19:07, Alfonso Pinto <alfonso.pinto at gmail.com> wrote:
>
> Hi Clive,
>
> Thanks for the answer. I found 2 things:
> -  $client->set_identity = $plugin->config->{identity} . "-$$"; should be
>  $client->set_identity($plugin->config->{identity} . "-$$");
> - Using builders for the properties doesn't work, I've to use BUILD as you
> suggested.
>
> Now I've this:
>
> package Dancer2::Plugin::ZMQ;
>
>
>> use Dancer2::Plugin;
>
>
>> our $version = '0.01';
>
>
>> use ZMQ::FFI;
>
> use ZMQ::FFI::Constants qw(ZMQ_REQ);
>
>
>> has _context => (is => 'rw');
>
> has _client => (is => 'rw', plugin_keyword => 'zmq');
>
>
>> sub BUILD {
>
>     my $plugin = shift;
>
>     my $args = shift;
>
>
>>     $plugin->_context(ZMQ::FFI->new());
>
>     $plugin->_client($plugin->_context->socket(ZMQ_REQ));
>
>     $plugin->_client->set_identity($plugin->config->{identity} . "-$$");
>
>     $plugin->_client->connect($plugin->config->{host});
>
> }
>
>
>> 1;
>
>
>
> This works if you run the dancer app as a standalone process. If I run it
> with Starman that initialises several workers, it doesn't work as it tries
> to share the same instance between all the workers (you can't share ZMQ
> context between processes/threads).
> Is there any way to create one instance per process?
>
> Regards,
> Alfonso.
>
> On Fri, Oct 13, 2017 at 4:32 PM, Clive Eisen <clive at hildebrand.co.uk>
> wrote:
>
>> I do a very similar thing for a custom redis plugin I wrote
>>
>> You have to declare the object outside the BUILD and set it inside
>>
>> eg
>> package Dredis;
>> use Redis::Fast;
>> use Dancer2::Plugin;
>>
>> my $redii;
>>
>> sub BUILD {
>>         my ($plugin) = @_;
>> <snip lots of setup stuff>
>> $redii->{$r}{$i} = Redis::Fast->new( %opts );
>> }
>>
>> Then use $redi-> in the get/set methods
>> eg
>> sub dredis {
>>         my( $called, $plugin, $method, @args ) = @_;
>>
>>         return $redii->{$called}->$method(@args);
>> }
>> 1;
>>
>> --
>> Clive Eisen
>> GPG: 75056DD0
>>
>>
>>
>>
>>
>>
>> On 13 Oct 2017, at 14:29, Alfonso Pinto <alfonso.pinto at gmail.com> wrote:
>>
>> Dear all,
>>
>> I'm trying to write a Dancer2::Plugin to maintain ZMQ socket and send
>> some information to a backend when a request is received.
>>
>> This is the plugin :
>>
>>> package Dancer2::Plugin::ZMQ;
>>>
>>>
>>> use Dancer2::Plugin;
>>>
>>>
>>> use ZMQ::FFI;
>>>
>>> use ZMQ::FFI::Constants qw(ZMQ_REQ);
>>>
>>>
>>> has host => (is => 'ro');
>>>
>>> has identity => (is => 'ro');
>>>
>>>
>>> has _context => (is => 'ro', lazy_build => 1);
>>>
>>> sub _build_context {
>>>
>>>     my $plugin = shift;
>>>
>>>     return ZMQ::FFI->new();
>>>
>>> }
>>>
>>>
>>> has client => (is => 'ro', lazy_build => 1, plugin_keyword => 'zmq');
>>>
>>> sub _build_client {
>>>
>>>     my $plugin = shift;
>>>
>>>
>>>     my $client = $plugin->_context->socket(ZMQ_REQ);
>>>
>>>     $client->set_identity = $plugin->config->{identity} . "-$$";
>>>
>>>     $client->connect($plugin->config->{host});
>>>
>>>     return $client;
>>>
>>> }
>>>
>>>
>>> 1;
>>>
>>
>>  This is my config.yml:
>>
>> plugins:
>>>     ZMQ:
>>>         identity: "api-gw"
>>>         host: "tcp://proxy:6660"
>>
>>
>>
>> And this is how I use it in one route:
>>
>> post '/' => sub {
>>
>>     my $message = body_parameters->get('message');
>>
>>     zmq->send(message =>$message);
>>
>>     my $reply = zmq->recv();
>>
>>     return {"reply" => $reply};
>>
>> };
>>
>>
>>
>>
>> The issue is that I get this error:
>>
>>> Router exception: Can't call method "send" on an undefined
>>
>>
>> I don't understand why it's not keeping the client instantiated. What is
>> wrong withmy approach? What I don't want is to create a socket for each
>> request received.
>>
>> And before someone asks, the backend is working and replying. A simple
>> script like this one works in my setup:
>>
>> use v5.10;
>>> use ZMQ::FFI qw(ZMQ_REQ);
>>>
>>
>>
>> my $endpoint = "tcp://proxy:6660";
>>> my $ctx      = ZMQ::FFI->new();
>>>
>>
>>
>> my $s1 = $ctx->socket(ZMQ_REQ);
>>> $s1->connect($endpoint);
>>>
>>
>>
>> $s1->send('ohhai');
>>> print $s1->recv();
>>
>>
>> Thanks in advance.
>> Regards,
>> Alfonso
>> _______________________________________________
>> dancer-users mailing list
>> dancer-users at dancer.pm
>> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
>>
>>
>>
>> _______________________________________________
>> dancer-users mailing list
>> dancer-users at dancer.pm
>> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
>>
>>
> _______________________________________________
> dancer-users mailing list
> dancer-users at dancer.pm
> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
>
>
> _______________________________________________
> dancer-users mailing list
> dancer-users at dancer.pm
> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.preshweb.co.uk/pipermail/dancer-users/attachments/20171013/40768a66/attachment-0001.html>


More information about the dancer-users mailing list