Skip to content

Commit

Permalink
add support for Mojo::Promise
Browse files Browse the repository at this point in the history
  • Loading branch information
oetiker committed Nov 26, 2018
1 parent 8896578 commit 9056873
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 13 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ MYMETA.yml
nytprof.out
pm_to_blib
thirdparty/
*.gz
*.tar
*~
*.log
setup/build-devel.sh
dist.sh
MYMETA.json
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
language: perl

perl:
- "5.18"
- "5.28"
- "5.22"
- "5.16"
- "5.14"
- "5.12"
- "5.10"

before_install:
Expand Down
3 changes: 3 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Revision history for Mojolicious::Pugin::Qooxdoo

1.0.0 2018-11-26
- add support for Mojo::Promise responses

0.907 2018-05-01
- fixed placeholder syntax to not use deprecated braces anymore

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The Artistic License 2.0

Copyright (c) 2013 Tobias Oetiker
Copyright (c) 2018 Tobias Oetiker

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Expand Down
28 changes: 27 additions & 1 deletion Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use 5.010001;
use strict;
use warnings;
use ExtUtils::MakeMaker;
use FindBin;

WriteMakefile(
NAME => 'Mojolicious::Plugin::Qooxdoo',
Expand All @@ -11,7 +12,7 @@ WriteMakefile(
AUTHOR => 'Tobias Oetiker <tobi@oetiker.ch>',
LICENSE => 'artistic_2',
PREREQ_PM => {
'Mojolicious' => '7.26'
'Mojolicious' => '8'
},
META_MERGE => {
requires => {perl => '5.010001'},
Expand All @@ -25,3 +26,28 @@ WriteMakefile(
# EXE_FILES => ['script/hypnotoad', 'script/mojo', 'script/morbo'],
test => {TESTS => 't/*.t'}
);

sub MY::postamble {
my $self = shift;
my %r = (%{ $self->{PREREQ_PM} || {} }, %{ $self->{BUILD_REQUIRES} || {} }, %{ $self->{TEST_REQUIRES} || {} } );
my $modules = join " ", grep !/^perl\~/, map { $r{$_} ? $_ .'~'. $r{$_} : $_ } keys %r;
my $tpd = "$FindBin::RealBin/thirdparty";
warn "** call 'make thirdparty' to build missing dependencies ...\n";
return <<"EOF";
#all:: README.md README
#README.md: $self->{VERSION_FROM}
# \$(PERL) -I$tpd/lib/perl5 -MPod::Markdown::Github -e 'binmode(STDOUT, ":utf8");Pod::Markdown::Github->new->filter(q{$self->{VERSION_FROM}})' > README.md
#README: README.md
# cp README.md README
thirdparty: $tpd/touch
mkdir -p $tpd
$tpd/touch: Makefile
\$(NOECHO) \$(ECHO) "*** INSTALLING MISSING BITS FOR TESTING ***"
curl -L https://cpanmin.us | PERL_CPANM_HOME=$tpd \$(PERL) - -q --notest --local-lib-contained $tpd $modules && touch $tpd/touch
EOF
}
22 changes: 22 additions & 0 deletions example/lib/QxExample/JsonRpcService.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package QxExample::JsonRpcService;
use strict;

use Mojo::Base 'Mojolicious::Plugin::Qooxdoo::JsonRpcController';
use Mojo::Promise;

=head1 NAME
Expand Down Expand Up @@ -29,6 +30,8 @@ our %allow_access = (
echo => 1,
async => 1,
asyncException => 1,
async_p => 1,
asyncException_p => 1,
);

sub allow_rpc_access {
Expand Down Expand Up @@ -72,6 +75,25 @@ sub asyncException {
});
}

sub async_p {
my $self = shift;
my $text = shift;
my $p = Mojo::Promise->new;
Mojo::IOLoop->timer('1.5' => sub {
$p->resolve("Delayed $text for 1.5 seconds!");
});
return $p;
}

sub asyncException_p {
my $self = shift;
my $p = Mojo::Promise->new;
Mojo::IOLoop->timer('1' => sub {
$p->reject(QxExample::Exception->new(code=>334, message=>"a simple error"));
});
return $p;
}

package QxExample::Exception;

use Mojo::Base -base;
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Plugin/Qooxdoo.pm
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use Mojo::Base 'Mojolicious::Plugin';
use File::Spec::Functions qw(splitdir updir catdir file_name_is_absolute);
use Cwd qw(abs_path);

our $VERSION = '0.908';
our $VERSION = '1.0.0';

sub register {
my ($self, $app, $conf) = @_;
Expand Down
51 changes: 44 additions & 7 deletions lib/Mojolicious/Plugin/Qooxdoo/JsonRpcController.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use warnings;

use Mojo::JSON qw(encode_json decode_json);
use Mojo::Base 'Mojolicious::Controller';
use Mojo::Promise;

use Encode;


Expand Down Expand Up @@ -140,16 +142,31 @@ sub dispatch {
}
# reply
no strict 'refs';
$self->$method(@$params);
return $self->$method(@$params);
};
if ($@){
$self->renderJsonRpcError($@);
}
else {
# do NOT render if
if (not $self->stash->{'mojo.rendered'}){
$self->renderJsonRpcResult($reply);
}
if (eval { $reply->isa('Mojo::Promise') }){
$reply->then(
sub {
my $ret = shift;
$self->renderJsonRpcResult($ret);
},
sub {
my $err = shift;
$self->renderJsonRpcError($err);
}
);
$self->render_later;
}
else {
# do NOT render if
if (not $self->stash->{'mojo.rendered'}){
$self->renderJsonRpcResult($reply);
}
}
}
}

Expand Down Expand Up @@ -243,7 +260,8 @@ Mojolicious::Plugin::Qooxdoo::JsonRpcController - A controller base class for Qo
package MyApp::MyJsonRpcController;
use Mojo::Base qw(Mojolicious::Plugin::Qooxdoo::JsonRpcController);
use Mojo::Promise;
has service => sub { 'Test' };
out %allow = ( echo => 1, bad => 1, async => 1);
Expand Down Expand Up @@ -281,6 +299,21 @@ Mojolicious::Plugin::Qooxdoo::JsonRpcController - A controller base class for Qo
});
}
sub async_p {
my $self=shift;
my $p = Mojo::Promise->new;
xyzWithCallback(callback => sub {
eval {
local $SIG{__DIE__};
$p->resolve('Late Reply');
}
if ($@) {
$p->reject($@);
}
});
return $p;
}
package MyException;
use Mojo::Base -base;
Expand Down Expand Up @@ -317,12 +350,16 @@ request.
=head2 Async Processing
If you want to do asyncronoous data processing, call the C<render_later> method
If you want to do async data processing, call the C<render_later> method
to let the dispatcher know that it should not bother with trying to render anyting.
In the callback, call the C<renderJsonRpcResult> method to render your result. Note
that you have to take care of any exceptions in the callback yourself and use
the C<renderJsonRpcError> method to send the exception to the client.
=head2 Mojo::Promise Support
If your method returns a promise, all will workout as expected. See the example above.
=head2 Debugging
To see full details of your rpc request and the answers sent back to the
Expand Down
6 changes: 6 additions & 0 deletions t/simple.t
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ $t->post_ok('/root/jsonrpc','{"id":1,"service":"rpc","method":"async","params":[
$t->post_ok('/root/jsonrpc','{"id":1,"service":"rpc","method":"asyncException","params":[]}')
->json_is('',{id=>1,error=>{origin=>2,code=>334,message=>'a simple error'}},'async exception');

$t->post_ok('/root/jsonrpc','{"id":1,"service":"rpc","method":"async_p","params":["hello"]}')
->json_is('',{id=>1,result=>'Delayed hello for 1.5 seconds!'},'promise request');

$t->post_ok('/root/jsonrpc','{"id":1,"service":"rpc","method":"asyncException_p","params":[]}')
->json_is('',{id=>1,error=>{origin=>2,code=>334,message=>'a simple error'}},'promise exception');

$t->get_ok('/root/jsonrpc?_ScriptTransport_id=1&_ScriptTransport_data="id":1,"service":"rpc","method":"echo","params":["hello"]}')
->content_like(qr/Invalid json/, 'invalid json get request')
->status_is(500);
Expand Down

0 comments on commit 9056873

Please sign in to comment.