The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Mojo::Promise::Limiter - limit outstanding calls to Mojo::Promise

SYNOPSIS

  use Mojo::Promise::Limiter;
  use Mojo::Promise;
  use Mojo::IOLoop;

  my $limiter = Mojo::Promise::Limiter->new(2);

  my @job = 'a' .. 'e';

  Mojo::Promise->all(
    map { my $name = $_; $limiter->limit(sub { job($name) }) } @job,
  )->then(sub {
    my @result = @_;
    warn "\n";
    warn "results: ", (join ", ", map { $_->[0] } @result), "\n";
  })->wait;

  sub job {
    my $name = shift;
    my $text = "job $name";
    warn "started $text\n";
    return Mojo::Promise->new(sub {
      my $resolve = shift;
      Mojo::IOLoop->timer(0.1 => sub {
        warn "        $text finished\n";
        $resolve->($text);
      });
    });
  }

will outputs:

  started job a
  started job b
          job a finished
          job b finished
  started job c
  started job d
          job c finished
          job d finished
  started job e
          job e finished

  results: job a, job b, job c, job d, job e

DESCRIPTION

Mojo::Promise::Limiter allows you to limit outstanding calls to Mojo::Promises. This is a Perl port of https://github.com/featurist/promise-limit.

MOTIVATION

I sometimes want to limit outstanding calls to reduce load on external services, or to reduce some resource (cpu, memory, etc) usage. For example, without some mechanism to limit outstanding calls, the following code open 5 connections to metacpan.

  my $http = Mojo::UserAgent->new;
  Mojo::Promise->all_settled(
    $http->get_p("https://metacpan.org/release/App-cpm"),
    $http->get_p("https://metacpan.org/release/Minilla"),
    $http->get_p("https://metacpan.org/release/Mouse"),
    $http->get_p("https://metacpan.org/release/Perl6-Build"),
    $http->get_p("https://metacpan.org/release/Test-CI"),
  )->wait;

With Mojo::Promise::Limiter, you can easily limit concurrent connections. See eg/http.pl for real world example.

EVENTS

Mojo::Promise::Limiter inherits all events from Mojo::EventEmitter and can emit the following new ones.

run

  $limiter->on(run => sub {
    my ($limiter, $name) = @_;
    ...;
  });

remove

  $limiter->on(remove => sub {
    my ($limiter, $name) = @_;
    ...;
  });

queue

  $limiter->on(queue => sub {
    my ($limiter, $name) = @_;
    ...;
  });

dequeue

  $limiter->on(dequeue => sub {
    my ($limiter, $name) = @_;
    ...;
  });

METHODS

Mojo::Promise::Limiter inherits all methods from Mojo::EventEmitter and implements the following new ones.

new

  my $limiter = Mojo::Promise::Limiter->new($concurrency);

Constructs Mojo::Promise::Limiter object.

limit

  my $promise = $limiter->limit($sub);
  my $promise = $limiter->limit($sub, $name);

Limits calls to $sub based on concurrency, where $sub is a subroutine reference that must return a promise, and $name is an optional argument which will be used in events. $limiter->limit($sub) returns a promise that resolves or rejects the same value or error as $sub. All subroutine references are executed in the same order in which they were passed to $limiter->limit method.

SEE ALSO

https://github.com/featurist/promise-limit

AUTHOR

Shoichi Kaji <skaji@cpan.org>

COPYRIGHT AND LICENSE

Copyright 2020 Shoichi Kaji <skaji@cpan.org>

The ISC License