app.pl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. use Mojolicious::Lite;
  2. use Mango;
  3. use JSON::XS 'encode_json';
  4. use Scalar::Util 'looks_like_number';
  5. # configuration
  6. plugin JSONConfig => {
  7. file => 'app.conf',
  8. default => {
  9. database_host => 'localhost',
  10. hypnotoad => {
  11. graceful_timeout => 1,
  12. workers => 8,
  13. },
  14. hypnotoad_merge => {},
  15. },
  16. };
  17. {
  18. my $merge = app->config->{hypnotoad_merge};
  19. @{app->config->{hypnotoad}}{keys %$merge} = values %$merge;
  20. }
  21. # Database connections
  22. helper mango => sub { state $mango = Mango->new('mongodb://'. shift->config->{database_host}) };
  23. helper db => sub { state $db = shift->mango->db('hello_world') };
  24. helper world => sub { state $world = shift->db->collection('world') };
  25. helper fortune => sub { state $fortune = shift->db->collection('fortune') };
  26. # JSON::XS renderer
  27. helper render_json => sub { shift->render( data => encode_json(shift), format => 'json' ) };
  28. # Routes
  29. get '/json' => sub { shift->helpers->render_json({message => 'Hello, World!'}) };
  30. get '/db' => sub { shift->helpers->render_query(1, {single => 1}) };
  31. get '/queries' => sub {
  32. my $c = shift;
  33. $c->helpers->render_query(scalar $c->param('queries'));
  34. };
  35. get '/fortunes' => sub {
  36. my $c = shift->render_later;
  37. my $tx = $c->tx;
  38. $c->helpers->fortune->find->all(sub{
  39. my ($cursor, $err, $docs) = @_;
  40. push @$docs, { _id => 0, message => 'Additional fortune added at request time.' };
  41. $c->render( fortunes => docs => $docs ) unless $tx->is_finished;
  42. });
  43. };
  44. get '/updates' => sub {
  45. my $c = shift;
  46. $c->helpers->render_query(scalar $c->param('queries'), {update => 1});
  47. };
  48. get '/plaintext' => sub { shift->render( text => 'Hello, World!' ) };
  49. # Additional helpers (shared code)
  50. helper 'render_query' => sub {
  51. my ($self, $q, $args) = @_;
  52. $args ||= {};
  53. my $update = $args->{update};
  54. $self->render_later;
  55. $q = 1 unless looks_like_number($q);
  56. $q = 1 if $q < 1;
  57. $q = 500 if $q > 500;
  58. my $r = [];
  59. my $tx = $self->tx;
  60. my $delay = Mojo::IOLoop->delay;
  61. $delay->on(finish => sub{
  62. $r = $r->[0] if $args->{single};
  63. $self->helpers->render_json($r) unless $tx->is_finished;
  64. });
  65. my $world = $self->helpers->world;
  66. foreach (1 .. $q) {
  67. my $id = int rand 10_000;
  68. my $end = $delay->begin;
  69. $world->find_one({_id => $id} => sub {
  70. my ($world, $err, $doc) = @_;
  71. if ($update) { $doc->{randomNumber} = 1 + int rand 10_000 };
  72. push @$r, { id => $id, randomNumber => $doc->{randomNumber} };
  73. $update ? $world->save($doc, $end) : $end->();
  74. });
  75. }
  76. # use this line if not running under a Mojolicious server
  77. # $delay->wait unless $delay->ioloop->is_running;
  78. };
  79. app->start;
  80. __DATA__
  81. @@ fortunes.html.ep
  82. <!DOCTYPE html>
  83. <html>
  84. <head><title>Fortunes</title></head>
  85. <body>
  86. <table>
  87. <tr><th>id</th><th>message</th></tr>
  88. % foreach my $doc (sort { $a->{message} cmp $b->{message} } @$docs) {
  89. <tr>
  90. <td><%= $doc->{_id} %></td>
  91. <td><%= $doc->{message} %></td>
  92. </tr>
  93. % }
  94. </table>
  95. </body>
  96. </html>