Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Eight Point Oh

Eight Point Oh

Sebastian Riedel

September 08, 2018
Tweet

More Decks by Sebastian Riedel

Other Decks in Programming

Transcript

  1. 8.0

  2. openQA • 100+ Contributors • 320 Minion Workers • 2.7M

    Tests executed • 25 Years of Test Runtime • 700 Test Modules • 800 Bugs found
  3. Cavil • 110K Packages per Year • 27K License Patterns

    • 2TB of License Data • 122M Minion Jobs
  4. get '/slow' => sub { my $c = shift; sleep

    3; $c->render(text => 'Hello Mojo!'); };
  5. Mojo::IOLoop->subprocess( sub { my $subprocess = shift; sleep 3; return

    'Hello Mojo!'; }, sub { my ($subprocess, $error, @results) = @_; ... } );
  6. get '/slow' => sub { my $c = shift; Mojo::IOLoop->subprocess(

    sub { sleep 3; return 'Hello Mojo!'; }, sub { my ($subprocess, $error, $message) = @_; return $c->reply->exception($error) if $error; $c->render(text => $message); } ); };
  7. use Cwd qw(getcwd realpath); use File::Copy qw(copy move); use File::Find

    'find'; use File::Spec::Functions qw(abs2rel canonpath catfile file_name_is_absolute rel2abs splitdir); use File::Temp qw(tempdir tempfile);
  8. my $path = path('/home/sri/.vimrc'); # ["home", "sri", ".vimrc"] $path->to_array; #

    "/home/sri" $path->dirname; # ".vimrc" $path->basename;
  9. my $path = path('/home/sri'); for my $file ($path->list_tree->each) { say

    $file; } for my $file ($path->list->each) { say $file; }
  10. $path->basename; $path->child(...); $path->copy_to(...); $path->dirname; $path->is_abs; $path->list; $path->list_tree; $path->make_path; $path->move_to(...); $path->open(...);

    $path->realpath; $path->remove_tree; $path->sibling(...); $path->slurp; $path->spurt(...); $path->to_abs; $path->to_array; $path->to_rel(...); $path->to_string;
  11. package MyApp; use Mojo::Base 'Mojolicious'; sub startup { my $self

    = shift; my $config = $self->plugin('Config'); my $name = $config->{name}; my $r = $self->routes; $r->get('/' => {inline => '%= $name'}); } 1;
  12. 7.0

  13. use Test::More; use Test::Mojo; my $t = Test::Mojo->new(MyApp => {name

    => 'foo'}); $t->get_ok('/')->content_is('foo'); $t = Test::Mojo->new(MyApp => {name => 'bar'}); $t->get_ok('/')->content_is('bar'); done_testing; 8.0
  14. my $t = Test::Mojo->new('MyApp'); my $location_is = sub { my

    ($t, $value, $desc) = @_; $desc ||= "Location: $value"; local $Test::Builder::Level = $Test::Builder::Level + 1; return $t->success(is($t->tx->res->headers->location, $value, $desc)); }; $t->get_ok('/') ->status_is(302) ->$location_is('https://mojolicious.org'); 7.0
  15. package Test::Mojo::Role::Location; use Mojo::Base -role; use Test::More; sub location_is {

    my ($t, $value, $desc) = @_; $desc ||= "Location: $value"; local $Test::Builder::Level = $Test::Builder::Level + 1; return $t->success( is($t->tx->res->headers->location, $value, $desc)); } 1; 8.0
  16. my $followup_promise = $promise->then(sub { my $result = shift; ...

    return 1 + 1; }, sub { my $error = shift; ... return 2 + 2; });
  17. my $followup_promise = $promise->then(sub { my $result = shift; ...

    return $ua->get_p('https://mojolicious.org'); }, sub { my $error = shift; ... });
  18. $ua->get('https://mojolicious.org' => sub { my ($ua, $tx) = @_; say

    $tx->res->code; $ua->get('https://mojolicious.org' => sub { my ($ua, $tx) = @_; say $tx->res->code; $ua->get('https://mojolicious.org' => sub { my ($ua, $tx) = @_; say $tx->res->code; }); }); }); 7.0
  19. $ua->get_p('https://mojolicious.org')->then(sub { my $tx = shift; say $tx->res->code; return $ua->get_p('https://mojolicious.org');

    })->then(sub { my $tx = shift; say $tx->res->code; return $ua->get_p('https://mojolicious.org'); })->then(sub { my $tx = shift; say $tx->res->code; }); 8.0
  20. $ua->get_p('https://mojolicious.org')->then(sub { my $tx = shift; say $tx->res->code; return $ua->get_p('https://mojolicious.org');

    })->then(sub { my $tx = shift; say $tx->res->code; return $ua->get_p('https://mojolicious.org'); })->then(sub { my $tx = shift; say $tx->res->code; })->catch(sub { my $error = shift; ... });
  21. my $followup = Mojo::Promises->all(@promises); my $followup = Mojo::Promises->race(@promises); $promise =

    $promise->resolve(...); $promise = $promise->reject(...); my $followup = $promise->then(sub {...}, sub {...}); my $followup = $promise->catch(sub {...}); my $followup = $promise->finally(sub {...}); $promise->wait;
  22. HTTP/1.1 200 OK Date: Sat, 13 Sep 2014 16:48:29 GMT

    Content-Length: 11 Server: Mojolicious (Perl) Server-Timing: cpu;desc=CPU;dur=0.03, db;desc=PostgreSQL;dur=0.6 Hello Mojo!
  23. $c->timing->begin('stuff'); sleep 3; my $elapsed = $c->timing->elapsed('stuff'); my $rps =

    $c->timing->rps($elapsed); $c->app->log->debug("Stuff took $elapsed seconds ($rps/s)");
  24. $app->hook(before_server_start => sub { my ($server, $app) = @_; return

    unless $server->isa('Mojo::Server::Daemon'); say "Manager $$ started"; $server->on( spawn => sub { my ($server, $pid) = @_; say "Worker $pid started"; } ) if $server->isa('Mojo::Server::Prefork'); });
  25. $app->hook(before_dispatch => sub { my $c = shift; my $id

    = $c->req->headers->header('X-Request-Id'); $c->req->request_id($id); });
  26. ???

  27. use DBD::Pg ':async'; use Mojo::IOLoop; my $dbh = DBI->connect( 'dbi:Pg:dbname=postgres;host=127.0.0.1;port=5432',

    'postgres', '', { AutoCommit => 1, AutoInactiveDestroy => 1, PrintError => 0, PrintWarn => 0, RaiseError => 1 } ); my $sth = $dbh->prepare('select 1', {pg_async => PG_ASYNC}); $sth->execute; open my $handle, '<&', $dbh->{pg_socket} or die "Can't dup: $!"; Mojo::IOLoop->singleton->reactor->io( $handle => sub { return unless $dbh->pg_ready; my $result = $sth->pg_result; my $data = $sth->fetchall_arrayref; ... Mojo::IOLoop->stop; } ); Mojo::IOLoop->start;
  28. my $arrays = $results->arrays; my $hashes = $results->hashes; my $array

    = $results->array; my $hash = $results->hash; my $text = $results->text; my $names = $results->columns; my $num = $results->rows;
  29. my $users = $pg->db->query('select * from users')->hashes; for my $user

    ($users->each) { say $user->{first_name}; say $user->{last_name}; }
  30. $db->insert('users', {name => 'Joel'}); my $id = $db->select('users', '*', {name

    => 'Joel'})->hash->{id}; $db->update('users', {name => 'jberger'}, {id => $id}); $db->delete('users', {name => 'jberger'});
  31. $db->select_p('users', '*', {name => ‘Marcus’})->then( sub { my $results =

    shift; say $results->hash->{id}; }, sub { my $error = shift; warn $error; } );
  32. # "select * from users limit 10 offset 20" $db->select('users',

    '*', undef, {limit => 10, offset => 20});
  33. # "insert into t (a) values ('b') on conflict (a)

    do update set a = 'c'" $db->insert('t', {a => 'b'}, {on_conflict => [a => {a => 'c'}]}); # "select * from foo join bar on (bar.foo_id = foo.id)" $db->select(['foo', ['bar', foo_id => 'id']]); # "select * from some_table where id = 1 for update" $db->select('some_table', '*', {id => 1}, {for => 'update'});
  34. $pg->pubsub->listen(foo => sub { my ($pubsub, $payload) = @_; say

    "foo: $payload"; }); $pg->pubsub->notify(foo => 'PostgreSQL rocks!');
  35. -- 1 up create table if not exists posts (

    id serial primary key, title text, body text ); -- 1 down drop table if exists posts;
  36. -- 1 up create table if not exists posts (

    id serial primary key, title text, body text ); -- 2 up alter tabl posts add column slug text; -- 1 down drop table if exists posts;
  37. package Minion::Backend::MyBackend; use Mojo::Base 'Minion::Backend'; sub broadcast {...} sub dequeue

    {...} sub enqueue {...} sub fail_job {...} sub finish_job {...} sub history {...} sub list_jobs {...} sub list_locks {...} sub list_workers {...} sub lock {...} sub note {...} sub receive {...} sub register_worker {...} sub remove_job {...} sub repair {...} sub reset {...} sub retry_job {...} sub stats {...} sub unlock {...} sub unregister_worker {...}
  38. $minion->add_task(foo => sub { my ($job, @args) = @_; sleep

    5; say $job->finish({hello => 'mojo'}); });
  39. my $id_one = $minion->enqueue('resize', [...]); my $id_two = $minion->enqueue('resize', [...]);

    my $pack_id = $minion->enqueue( 'pack', [...], {parents => [$id_one ,$id_two]});
  40. $minion->add_task(foo => sub { my ($job, @args) = @_; warn

    'Some important information!'; die 'Hello Mojo!'; });