Skip to content

Commit

Permalink
* Add settings to keep the multi handle alive to respect Apple recomm…
Browse files Browse the repository at this point in the history
…endations to keep connections for high senders. Also move previously added settings from constructor to setters.
  • Loading branch information
ahfeel committed Nov 7, 2017
1 parent 0bf44ff commit ccc47b3
Showing 1 changed file with 86 additions and 9 deletions.
95 changes: 86 additions & 9 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,43 @@ class Client
private $isProductionEnv;

/**
* Number of concurrent requests to multiplex in the same connection
* Number of concurrent requests to multiplex in the same connection.
*
* @var int
*/
private $nbConcurrentRequests = 20;

/**
* Number of maximum concurrent connections established to the APNS servers.
*
* @var int
*/
private $maxConcurrentConnections = 1;

/**
* Flag to know if we should automatically close connections to the APNS servers or keep them alive.
*
* @var bool
*/
private $nbConcurrentRequests;
private $autoCloseConnections = true;

/**
* Current curl_multi handle instance.
*
* @var Object
*/
private $curlMultiHandle;

/**
* Client constructor.
*
* @param AuthProviderInterface $authProvider
* @param bool $isProductionEnv
*/
public function __construct(AuthProviderInterface $authProvider, bool $isProductionEnv = false, int $nbConcurrentRequests = 10)
public function __construct(AuthProviderInterface $authProvider, bool $isProductionEnv = false)
{
$this->authProvider = $authProvider;
$this->isProductionEnv = $isProductionEnv;
$this->nbConcurrentRequests = $nbConcurrentRequests;
}

/**
Expand All @@ -65,13 +85,18 @@ public function __construct(AuthProviderInterface $authProvider, bool $isProduct
*/
public function push(): array
{
$mh = curl_multi_init();
if (!$this->curlMultiHandle) {
$this->curlMultiHandle = curl_multi_init();

if (!defined('CURLPIPE_MULTIPLEX')) {
define('CURLPIPE_MULTIPLEX', 2);
}

if (!defined('CURLPIPE_MULTIPLEX')) {
define('CURLPIPE_MULTIPLEX', 2);
curl_multi_setopt($this->curlMultiHandle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt($this->curlMultiHandle, CURLMOPT_MAX_HOST_CONNECTIONS, $this->maxConcurrentConnections);
}

curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
$mh = $this->curlMultiHandle;

$i = 0;
while (!empty($this->notifications) && $i++ < $this->nbConcurrentRequests) {
Expand All @@ -98,6 +123,7 @@ public function push(): array
$statusCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
$responseCollection[] = new Response($statusCode, $headers, $body, $token);
curl_multi_remove_handle($mh, $handle);
curl_close($handle);

if (!empty($this->notifications)) {
$notification = array_pop($this->notifications);
Expand All @@ -106,11 +132,19 @@ public function push(): array
}
} while ($running);

curl_multi_close($mh);
if ($this->autoCloseConnections) {
curl_multi_close($mh);
$this->curlMultiHandle = null;
}

return $responseCollection;
}

/**
* Prepares a curl handle from a Notification object.
*
* @param Notification $notification
*/
private function prepareHandle(Notification $notification)
{
$request = new Request($notification, $this->isProductionEnv);
Expand Down Expand Up @@ -162,4 +196,47 @@ public function getNotifications(): array
{
return $this->notifications;
}

/**
* Close the current curl multi handle.
*/
public function close()
{
if ($this->curlMultiHandle) {
curl_multi_close($this->curlMultiHandle);
$this->curlMultiHandle = null;
}
}

/**
* Set the number of concurrent requests sent through the multiplexed connections.
*
* @param int $nbConcurrentRequests
*/
public function setNbConcurrentRequests($nbConcurrentRequests)
{
$this->nbConcurrentRequests = $nbConcurrentRequests;
}


/**
* Set the number of maximum concurrent connections established to the APNS servers.
*
* @param int $nbConcurrentRequests
*/
public function setMaxConcurrentConnections($maxConcurrentConnections)
{
$this->maxConcurrentConnections = $maxConcurrentConnections;
}

/**
* Set wether or not the client should automatically close the connections. Apple recommends keeping
* connections open if you send more than a few notification per minutes.
*
* @param bool $nbConcurrentRequests
*/
public function setAutoCloseConnections($autoCloseConnections)
{
$this->autoCloseConnections = $autoCloseConnections;
}
}

0 comments on commit ccc47b3

Please sign in to comment.