Last active
July 13, 2020 14:51
-
-
Save jberger/5605062 to your computer and use it in GitHub Desktop.
OUTDATED (see comment): Chat using Mojo + Mojo::Redis
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use Mojolicious::Lite; | |
use Mojo::Redis; | |
use Mojo::JSON 'j'; | |
sub handler { | |
my $tag = shift; | |
return sub { | |
my $message = $_[1] || "Closed"; | |
app->log->debug( "$tag: $message" ) | |
}; | |
} | |
app->attr( _redis => sub { | |
my $redis = Mojo::Redis->new; | |
$redis->on( error => handler("Pub Error") ); | |
$redis->on( close => handler("Pub") ); | |
return $redis; | |
}); | |
helper redis => sub { shift->app->_redis }; | |
app->attr( _chat => sub { | |
my $redis = shift->redis; | |
my $chat = $redis->new($redis); #clone | |
$chat->subscribe('chat'); | |
$chat->on( error => handler("Sub Error") ); | |
$chat->on( close => handler("Sub") ); | |
return $chat; | |
}); | |
helper chat => sub { | |
my ($self, $cb) = @_; | |
my $chat = $self->app->_chat; | |
$chat->on( message => $cb ); | |
}; | |
any '/' => sub { | |
my $c = shift; | |
my $name = $c->session('name'); | |
if ( my $new_name = $c->param('name') ) { | |
$c->session( name => $new_name ); | |
$name = $new_name; | |
} elsif ( ! defined $name ) { | |
return $c->redirect_to('login'); | |
} | |
$c->render('chat'); | |
}; | |
any '/login'; | |
any '/logout' => sub { | |
my $c = shift; | |
$c->session( expires => 1 ); | |
$c->redirect_to('/'); | |
}; | |
websocket '/ws/chat' => sub { | |
my $c = shift; | |
my $name = $c->session('name'); | |
Mojo::IOLoop->stream($c->tx->connection)->timeout(60*60); | |
$c->chat( sub { | |
my ($s, $chan, $message) = @_; | |
$c->app->log->debug( "Got: $message" ); | |
$c->send({ text => $message }); | |
} ); | |
$c->on( json => sub { | |
my ($ws, $data) = @_; | |
$data->{name} = $name; | |
my $json = j($data); | |
$ws->app->log->debug( "Publishing: $json" ); | |
$c->redis->publish( chat => $json ); | |
}); | |
#my $r = Mojo::IOLoop->recurring( 1 => sub { | |
# state $i = 1; | |
# $c->send({ json => { name => 'Joel', message => $i++ }}); | |
#}); | |
#$c->on( finish => sub { Mojo::IOLoop->remove($r) } ); | |
}; | |
app->start; | |
__DATA__ | |
@@ layouts/basic.html.ep | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title><%= title %></title> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> | |
</head> | |
<body> | |
%= content | |
</body> | |
</html> | |
@@ login.html.ep | |
% layout 'basic'; | |
% title 'Login'; | |
%= form_for '/' => method => POST => begin | |
%= text_field 'name' | |
%= submit_button 'Login' | |
% end | |
@@ chat.html.ep | |
% layout 'basic'; | |
% title 'Mojo+Redis Chat'; | |
<input type="text" id="text"><button onclick="send()">Send</button><button onclick="disconnect()">Disconnect</button> | |
<div id="log"></div> | |
%= javascript begin | |
var ws; | |
var nows = 0; | |
function connect () { | |
if (!("WebSocket" in window)) { | |
nows = 1; | |
alert('Your browser does not support WebSockets!'); | |
return; | |
} | |
ws = new WebSocket('<%= url_for('wschat')->to_abs %>'); | |
ws.onmessage = function (e) { | |
console.log(e); | |
var data = JSON.parse(e.data); | |
$('#log').prepend('<p>' + data.name + ': ' + data.message + '</p>'); | |
}; | |
} | |
function send () { | |
var text = $('#text'); | |
ws.send(JSON.stringify({ message: text.val() })); | |
text.val(''); | |
} | |
function disconnect () { ws.close() } | |
$(function(){connect()}); | |
% end |
There is a long history of the Mojo::Redis module. Originally there was Mojo::Redis. Then to avoid breaking users of that module, when a new api was desired, the authors released Mojo::Redis2. Finally when yet another breaking version was wanted, the authors decided to reuse Mojo::Redis rather than make Mojo::Redis3 as anecdotally everyone had now moved to using 2 and the original name was simpler. It does leave some outliers of course and this is one. Thanks for seeing it.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just a quick note as searching for Mojo Redis chat|subscribe example in Google brings up this hist near top - the
NB - Mojo-Redis pubsub api changed since this was written specifically
->subscribe
In app defined helper:
$self->helper( redis => sub { state $r = Mojo::Redis->new } );
In Controller websocket handle