NAME

    RateLimitations - manage per-service rate limitations

SYNOPSIS

        use 5.010;
    
        use RateLimitations qw(
            rate_limited_services
            rate_limits_for_service
            within_rate_limits
            all_service_consumers
        );
    
        # Example using the built-in default "rl_internal_testing" service:
        #   rl_internal_testing:
        #       10s: 2
        #       5m:  6
    
        my @rl_services = rate_limited_services();
        # ("rl_internal_testing")
    
        my @test_limits = rate_limits_for_service('rl_internal_testing');
        # ([10 => 2], [300 => 6])
    
        foreach my $i (1 .. 6) {
            my $guy = ($i % 2) ? 'OddGuy' : 'EvenGuy';
            my $result = (
                within_rate_limits({
                        service  => 'rl_internal_testing',
                        consumer => $guy,
                    })) ? 'permitted' : 'denied';
            say $result . ' for ' . $guy;
        }
        # permitted for OddGuy
        # permitted for EvenGuy
        # permitted for OddGuy
        # permitted for EvenGuy
        # denied for OddGuy
        # denied for EvenGuy
    
        my $consumers = all_service_consumers();
        # { rl_internal_testing => ['EvenGuy', 'OddGuy']}

DESCRIPTION

    RateLimitations is a module to help enforce per-service rate limits.

    The rate limits are checked via a backing Redis store. This persistence
    allows for multiple processes to maintain a shared view of resource
    usage. Acceptable rates are defined in the
    /etc/perl_rate_limitations.yml file.

    Several utility functions are provided to help examine the inner state
    to help confirm proper operation.

    Nothing is exported from this package by default.

FUNCTIONS

    within_rate_limits({service => $service, consumer => $consumer_id})

      Returns 1 if $consumer_id is permitted further access to $service
      under the rate limiting rules for the service; 0 is returned if this
      access would exceed those limits.

      Will croak unless both elements are supplied and $service is valid.

      Note that this call will update the known request rate, even if it is
      eventually determined that the request is not within limits. This is
      a conservative approach since we cannot know for certain how the
      results of this call are used. As such, it is best to use this call
      only when legitimately gating service access and to allow a bit of
      extra slack in the permitted limits.

    verify_rate_limitations_config()

      Attempts to load the /etc/perl_rate_limitations.yml file and confirm
      that its contents make sense. Parsing the file in much the same way
      as importing the module, additional sanity checks are performed on
      the supplied rates.

      Returns 1 if the file appears to be OK; 0 otherwise.

    rate_limited_services()

      Returns an array of all known services which have applied rate
      limits.

    rate_limits_for_service($service)

      Returns an array of rate limits applied to requests for a known
      $service. Each member of the array is an array reference with two
      elements:

          [number_of_seconds, number_of_accesses_permitted_in_those_seconds]

    all_service_consumers()

      Returns a hash reference with all services and their consumers. May
      be useful for verifying consumer names are well-formed.

          { service1 => [consumer1, consumer2],
            service2 => [consumer1, consumer2],
          }

    flush_all_service_consumers()

      Clears the full list of consumers. Returns the number of items
      cleared.

CONFIG FILE FORMAT

    The services to be limited are defined in the
    /etc/perl_rate_limitations.yml file. This file should be laid out as
    follows:

        service_name:
            time: count
            time: count
        service_name:
            time: count
            time: count

    service_name is an arbitrary string to uniquely identify the service

    time is a string which can be interpreted by Time::Duration::Concise.
    This may include using an integer number of seconds.

    count is an integer which sets the maximum permitted service_name
    accesses per time

AUTHOR

    Binary.com <perl@binary.com>

COPYRIGHT

    Copyright 2015-

LICENSE

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

SEE ALSO

