Rate Limiting SOAP client in PHP

I’ve recently had the requirement to rate limit SOAP calls to a remote API, so having done the work I though I’d document it here.

I’ve left in one method in the code below which is specific to my use – SearchAccounts(). The reason for this is that I though I’d show how I go about using it, in that I don’t leave calls up to the magical methods that the SoapClient itself provides, but rather re-define the functions in my own class so that I can generate API docs locally. It is of course up to you if you want to use this method.

class ApmSoapClient extends SoapClient
{

    /**
     * @var int    Number of microseconds to wait before consecutive calls
     */
    private $rateLimit = 100;

    /**
     * @var float Stores the time of last call, used for ratelimiting
     */
    private $lastcall;

    public function __construct($wsdl, $username, $password)
    {
        parent::__construct($wsdl, array(
            'login' => $username,
            'password' => $password,
            'classmap' => array(
                'Mailbox'      => 'Mailbox',
                'Account'      => 'Account',
                'MailboxAlias' => 'MailboxAlias',
                'Domain'       => 'Domain',
            )
        ));
    }

    /**
     * Returns $rateLimit.
     * @see ApmSoapClient::$rateLimit
     */
    public function getRateLimit()
    {
        return $this->rateLimit;
    }

    /**
     * Sets $rateLimit.
     * @param object $rateLimit
     * @see ApmSoapClient::$rateLimit
     */
    public function setRateLimit($rateLimit)
    {
        $this->rateLimit = $rateLimit;
    }


    public function __call($func, $args)
    {
        return $this->__soapCall($func, $args);
    }

    public function __soapCall($func, $args)
    {
        if ($this->lastcall && $this->rateLimit)
        {
            if (($this->lastcall + ($this->rateLimit / 1000)) > microtime(true))
            {
                $msSleep = (($this->lastcall + ($this->rateLimit / 1000))
                   - microtime(true)) * 1000 * 1000;
                usleep((int)$msSleep);
            }
        }
        $this->lastcall = microtime(true);

        return parent::__soapCall($func, $args);
    }

    /**
     *
     * @return array
     * @param String  $ref          Your account reference
     * @param String  $statis       1 = On, 0 = Off
     * @param Integer $overquota    1 = Users over quota, 0 = Any user
     * @param String  $after_date   Only users created after this date
     * @param String  $before_date  Only users created before this date
     * @param String  $email        A valid email address
     */
    public function SearchAccounts($ref, $statis, $overquota, $after_date, $before_date, $email)
    {
        $args = func_get_args();
        return $this->__call('SearchAccounts', $args);
    }
}

2 thoughts on “Rate Limiting SOAP client in PHP”

  1. indeed it does – i programmed it for a batch job run from the CLI. You could move the rate limiting into shared memory, but I imagine if you’re doing lots of SOAP requests for a single web request, you need to look at the issue from a different angle.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.