- where in the RT code would be the best place to add the WEBSOCKET REST
extension (into the routing) + it needs an main loop waiting for
‘ticket’-table changes
You’ll probably want to use Plack::App::WebSocket with an event-based PSGI server (probably Twiggy). RT is typically deployed with FastCGI or similar, so you have your work cut out for you there.
You’ll either want to have good documentation around switching an RT deployment from FastCGI to Twiggy, or have your users deploy a standalone Twiggy server alongside their RT http server.
hm. this leaves me with three more questions:
- could you please point out what i need to do in order to use twiggy
instead of ‘the usual’ deployment method?
right now i call the server like this:
plackup /tmp/rt4/opt/rt4/sbin/standalone_httpd --port 8080
Twiggy: Accepting connections at http://0.0.0.0:8080/
…
so this is probably answered now. can i run the server like this in
production?
i had a lengthily discussion about this on irc#perl:
(23:56) < mst> well, you could run the two side by side
(23:56) < mst> you should be running two daemons anyway
(23:56) < mst> you don’t want your websocket handler in the same
process as the main RT code
as well as:
(23:58) < hobbs> yeah. Even if you switch the server, RT will do all
kinds of things that will jam up the loop and make your websockets useless
(23:58) < hobbs> or at least perform very badly
any comment on using ‘plack’ instead of ‘psgi’/‘fcgi’ with websockets
implemented like shown in Plack::App::WebSocket?
regarding WS:
i’ve been playing with Plack::App::WebSocket a lot. mainly with this
example:
Plack-Middleware-WebSocket/eg/echo/app.psgi at master · motemen/Plack-Middleware-WebSocket · GitHub
and i’m currently having trouble with two things:
got that working, too. was actually pretty simple:
i just had to add a mount “/websocket” like this:
Called by RT::Interface::Web::Handler->PSGIApp
sub PSGIWrap {
print STDERR “REST2.pm: qknight was here: sub PSGIWrap”, “\n\n”;
my ($class, $app) = @;
return builder {
mount $REST_PATH => $class->to_app;
mount ‘/’ => $app;
mount “/websocket” => Plack::App::WebSocket->new(
on_error => sub {
my $env = shift;
print STDERR “plack_app_websocket.psgi: qknight was here:
/websocket on_error”, “\n\n”;
return [500,
[“Content-Type” => “text/plain”],
["Error: " .
$env->{“plack.app.websocket.error”}]];
},
on_establish => sub {
print STDERR “plack_app_websocket.psgi: qknight was here:
/on_established”, “\n\n”;
my $conn = shift; ##
Plack::App::WebSocket::Connection object
my $env = shift; ## PSGI env
push(@WSConnections, $conn);
$conn->on(
message => sub {
my ($conn, $msg) = @;
print STDERR “plack_app_websocket.psgi: qknight was here:
message: $msg”, “\n\n”;
foreach (@WSConnections) {
$->send($msg);
}
},
finish => sub {
# most epic remove function ever OMFG
(qknight)
my @l;
foreach(@WSConnections) {
if ($ != $conn) {
push(@l, $_)
}
}
@WSConnections = @l;
undef $conn;
warn “Bye!!\n”;
},
);
}
)->to_app;
};
}
since my @WSConnections; is a global object i can now send messages to
all attached clients yay!
with using a singleton, like shown here:
Class::Singleton - Implementation of a "Singleton" class - metacpan.org
i should be able to create a perl based WSClass which can be used from
all the RT-codebase as:
- Instrumenting RT::Record::Create and
- RT::Record::_Set generally, or
- RT:
:Create and
- RT:
:_Set specifically
as you pointed out in order to circumvent the MySQL-only solution.