xtpu2 has asked for the wisdom of the Perl Monks concerning the following question:
I'm very new to event-based programming in Perl. I'm currently trying to get to grips with a Plack / Twiggy / AnyEvent / SockJS combination (details below). Unfortunately, I'm not doing so well.
I'm trying to write a program that will send the client a message whenever a certain event happens (in the production version, the event will be a database update, but for the purposes of this test, I'm trying to use an AnyEvent timer). However, I have no clue from which end to approach this. Here is the code I have so far (this is heavily based on the example code from the SockJS-perl docs):
#!/usr/bin/perl use strict; use warnings; use Plack::Builder; use SockJS; use AnyEvent; builder { mount '/echo' => SockJS->new( handler => sub { my ($session) = @_; $session->on( 'data' => sub { my $session = shift; $session->write('got your message'); } ); $session->write('connected'); my $w_cond = AnyEvent->condvar; my $w; $w = AnyEvent->timer( after => 0, interval => 5, cb => sub { undef $w; # cleanup $session->write('5 seconds have passed'); $w_cond->send(); } ); $w_cond->recv; }; ); };
This code is executed with:
plackup --server Twiggy::TLS --port 5000 --tks-key /path/to/key --tls-cert /path/to/cert app.psgiThis code doesn't work! Console.log outputs the following:
open connected close
It is obvious that $w->recv is the culprit because if I comment out that line, the server works and outputs 'got your message' when I send a message to it. However, in that case the timer doesn't work.
I know that SockJS is a module in very early development, and I have contacted the author for more information, but I have the feeling that my problem has nothing to do with SockJS, but with the way Plack, Twiggy and AnyEvent work. Hence my posting the question here on perlmonks. Any input / insight would be greatly appreciated (because not understanding this is driving me up the wall!!!)
For completeness, here is the client-side JavaScript code (copied 95% from the example on the SockJS module page):
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script> <script> var sock = new SockJS("https://0.0.0.0:5000/echo"); sock.onopen = function() { console.log("open"); }; sock.onmessage = function(e) { console.log(e.data); }; sock.onclose = function() { console.log("close"); }; </script>
**Update: The issue has been resolved!**
Final, working code:
#!/usr/bin/perl use strict; use warnings; use Plack::Builder; use SockJS; use AnyEvent; builder { mount '/echo' => SockJS->new( handler => sub { my ($session) = @_; $session->on( 'data' => sub { my $session = shift; $session->write('got your message'); } ); $session->write('connected'); my $w_cond = AnyEvent->condvar; $w_cond->cb( sub { warn $_[0]->recv } ); my $w; $w = AnyEvent->timer( after => 0, interval => 5, cb => sub { undef $w if (0); $session->write('5 seconds have passed'); $w_cond->send(); } ); }; ); };
|
|---|