Batching multiple notifications
The group you are posting to is a
Usenet group . Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
From:
mlunoe <michael.lu... @gmail.com>
Date: Fri, 2 Mar 2012 03:51:38 -0800 (PST)
Local: Fri, Mar 2 2012 6:51 am
Subject: Batching multiple notifications
I am very excited about this library. Thank you so much for all the
work you put into this!
At first it seemed very capable of handling multiple notifications as
it can handle many applications. However, on further inspection I
found that it does not batch notifications as Apple encourages you to
do on their apns guide (https://developer.apple.com/library/mac/
#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/
CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it
opens a stream, sends a notification and closes the stream, which can
be optimised. Here are the code that opens a stream, sends all the
queued messages (in a batch) and closes the stream:
////////////// BEGIN NEW ADDITION ////////////////
/**
* True if running in sandbox
*
* @var bool
* @access private
*/
private $isSandbox = true;
/**
* The limit of how many messages to send
* @var int
* @access private
*/
private $limit = 100;
private function _checkMessage($pid, $message, $token, $development) {
return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0 &&
strlen($development)!=0;
}
////////////// END NEW ADDITION ////////////////
////////////// BEGIN REPLACE EXISTING ////////////////
private function _fetchMessages(){
// only send one message per user... oldest message first
$sql = "SELECT
`apns_messages`.`pid`,
`apns_messages`.`message`,
`apns_devices`.`devicetoken`
FROM `apns_messages`
LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
`apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
`apns_messages`.`clientid`)
WHERE `apns_messages`.`status`='queued'
AND `apns_messages`.`delivery` <= NOW()
AND `apns_devices`.`status`='active'
AND `apns_devices`.`development`=".($this->isSandbox ?
"'sandbox'":"'production'").
" GROUP BY `apns_messages`.`fk_device`
ORDER BY `apns_messages`.`created` ASC
LIMIT ".$this->limit.";";
$development = $this->isSandbox ? 'sandbox': 'production';
if($result = $this->db->query($sql)){
if($result->num_rows){
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $this-
>apnsData[$development]['certificate']);
$fp = stream_socket_client($this->apnsData[$development]['ssl'],
$error, $errorString, 100, (STREAM_CLIENT_CONNECT|
STREAM_CLIENT_PERSISTENT), $ctx);
while($row = $result->fetch_array(MYSQLI_ASSOC)){
$pid = $this->db->prepare($row['pid']);
$message = stripslashes($this->db->prepare($row['message']));
$token = $this->db->prepare($row['devicetoken']);
if(!$fp){
$this->_pushFailed($pid);
$this->_triggerError("Failed to connect to APNS: {$error}
{$errorString}.");
}
else if(!$this->_checkMessage($pid, $message, $token,
$development)) {
$this->_pushFailed($pid);
$this->_triggerError("Invalid message for device pid: ".
$pid.".");
}
else {
$this->_pushMessage($fp, $pid, $message, $token, $development);
}
}
fclose($fp);
$this->_checkFeedback($development);
}
}
}
private function _flushMessages(){
// send all the messages for each device
$sql = "SELECT
`apns_messages`.`pid`,
`apns_messages`.`message`,
`apns_devices`.`devicetoken`
FROM `apns_messages`
LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
`apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
`apns_messages`.`clientid`)
WHERE `apns_messages`.`status`='queued'
AND `apns_messages`.`delivery` <= NOW()
AND `apns_devices`.`status`='active'
AND `apns_devices`.`development`=".($this->isSandbox ?
"'sandbox'":"'production'").
" ORDER BY `apns_messages`.`created` ASC
LIMIT ".$this->limit.";";
$development = $this->isSandbox ? 'sandbox': 'production';
if($result = $this->db->query($sql)){
//var_dump ($result);
if($result->num_rows){
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $this-
>apnsData[$development]['certificate']);
$fp = stream_socket_client($this->apnsData[$development]['ssl'],
$error, $errorString, 100, (STREAM_CLIENT_CONNECT|
STREAM_CLIENT_PERSISTENT), $ctx);
while($row = $result->fetch_array(MYSQLI_ASSOC)){
$pid = $this->db->prepare($row['pid']);
$message = stripslashes($this->db->prepare($row['message']));
$token = $this->db->prepare($row['devicetoken']);
if(!$fp){
$this->_pushFailed($pid);
$this->_triggerError("Failed to connect to APNS: {$error}
{$errorString}.");
}
else if(!$this->_checkMessage($pid, $message, $token,
$development)) {
$this->_pushFailed($pid);
$this->_triggerError("Invalid message for device pid: ".
$pid.".");
}
else {
$this->_pushMessage($fp, $pid, $message, $token, $development);
}
}
fclose($fp);
$this->_checkFeedback($development);
}
}
}
private function _pushMessage($fp, $pid, $message, $token,
$development){
$msg = chr(0).pack("n",32).pack('H*',
$token).pack("n",strlen($message)).$message;
$fwrite = fwrite($fp, $msg);
if(!$fwrite) {
$this->_pushFailed($pid);
$this->_triggerError("Failed writing to stream.", E_USER_ERROR);
}
else {
$this->_pushSuccess($pid);
}
}
////////////// END REPLACE EXISTING ////////////////
Hope you can use this for your own projects!
Regards Michael
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Guillaume <guilla... @gmail.com>
Date: Wed, 14 Mar 2012 06:43:42 -0700 (PDT)
Local: Wed, Mar 14 2012 9:43 am
Subject: Re: Batching multiple notifications
_flushMessages() and _fetchMessages() are same functions?
With theses modifications it seems it's possible to send push quickly.
But if I have 90,000 tokens, and so I put the $limit = 100000; the
$msg to send will be too large, no ?
On 2 mar, 12:51, mlunoe <michael.lu... @gmail.com> wrote:
> I am very excited about this library. Thank you so much for all the
> work you put into this!
> At first it seemed very capable of handling multiple notifications as
> it can handle many applications. However, on further inspection I
> found that it does not batch notifications as Apple encourages you to
> do on their apns guide (https://developer.apple.com/library/mac/
> #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/
> CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it
> opens a stream, sends a notification and closes the stream, which can
> be optimised. Here are the code that opens a stream, sends all the
> queued messages (in a batch) and closes the stream:
> ////////////// BEGIN NEW ADDITION ////////////////
> /**
> * True if running in sandbox
> *
> * @var bool
> * @access private
> */
> private $isSandbox = true;
> /**
> * The limit of how many messages to send
> * @var int
> * @access private
> */
> private $limit = 100;
> private function _checkMessage($pid, $message, $token, $development) {
> return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0 &&
> strlen($development)!=0;
> }
> ////////////// END NEW ADDITION ////////////////
> ////////////// BEGIN REPLACE EXISTING ////////////////
> private function _fetchMessages(){
> // only send one message per user... oldest message first
> $sql = "SELECT
> `apns_messages`.`pid`,
> `apns_messages`.`message`,
> `apns_devices`.`devicetoken`
> FROM `apns_messages`
> LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> `apns_messages`.`clientid`)
> WHERE `apns_messages`.`status`='queued'
> AND `apns_messages`.`delivery` <= NOW()
> AND `apns_devices`.`status`='active'
> AND `apns_devices`.`development`=".($this->isSandbox ?
> "'sandbox'":"'production'").
> " GROUP BY `apns_messages`.`fk_device`
> ORDER BY `apns_messages`.`created` ASC
> LIMIT ".$this->limit.";";
> $development = $this->isSandbox ? 'sandbox': 'production';
> if($result = $this->db->query($sql)){
> if($result->num_rows){
> $ctx = stream_context_create();
> stream_context_set_option($ctx, 'ssl', 'local_cert', $this->apnsData[$development]['certificate']);
> $fp = stream_socket_client($this->apnsData[$development]['ssl'],
> $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> STREAM_CLIENT_PERSISTENT), $ctx);
> while($row = $result->fetch_array(MYSQLI_ASSOC)){
> $pid = $this->db->prepare($row['pid']);
> $message = stripslashes($this->db->prepare($row['message']));
> $token = $this->db->prepare($row['devicetoken']);
> if(!$fp){
> $this->_pushFailed($pid);
> $this->_triggerError("Failed to connect to APNS: {$error}
> {$errorString}.");
> }
> else if(!$this->_checkMessage($pid, $message, $token,
> $development)) {
> $this->_pushFailed($pid);
> $this->_triggerError("Invalid message for device pid: ".
> $pid.".");
> }
> else {
> $this->_pushMessage($fp, $pid, $message, $token, $development);
> }
> }
> fclose($fp);
> $this->_checkFeedback($development);
> }
> }
> }
> private function _flushMessages(){
> // send all the messages for each device
> $sql = "SELECT
> `apns_messages`.`pid`,
> `apns_messages`.`message`,
> `apns_devices`.`devicetoken`
> FROM `apns_messages`
> LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> `apns_messages`.`clientid`)
> WHERE `apns_messages`.`status`='queued'
> AND `apns_messages`.`delivery` <= NOW()
> AND `apns_devices`.`status`='active'
> AND `apns_devices`.`development`=".($this->isSandbox ?
> "'sandbox'":"'production'").
> " ORDER BY `apns_messages`.`created` ASC
> LIMIT ".$this->limit.";";
> $development = $this->isSandbox ? 'sandbox': 'production';
> if($result = $this->db->query($sql)){
> //var_dump ($result);
> if($result->num_rows){
> $ctx = stream_context_create();
> stream_context_set_option($ctx, 'ssl', 'local_cert', $this->apnsData[$development]['certificate']);
> $fp = stream_socket_client($this->apnsData[$development]['ssl'],
> $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> STREAM_CLIENT_PERSISTENT), $ctx);
> while($row = $result->fetch_array(MYSQLI_ASSOC)){
> $pid = $this->db->prepare($row['pid']);
> $message = stripslashes($this->db->prepare($row['message']));
> $token = $this->db->prepare($row['devicetoken']);
> if(!$fp){
> $this->_pushFailed($pid);
> $this->_triggerError("Failed to connect to APNS: {$error}
> {$errorString}.");
> }
> else if(!$this->_checkMessage($pid, $message, $token,
> $development)) {
> $this->_pushFailed($pid);
> $this->_triggerError("Invalid message for device pid: ".
> $pid.".");
> }
> else {
> $this->_pushMessage($fp, $pid, $message, $token, $development);
> }
> }
> fclose($fp);
> $this->_checkFeedback($development);
> }
> }
> }
> private function _pushMessage($fp, $pid, $message, $token,
> $development){
> $msg = chr(0).pack("n",32).pack('H*',
> $token).pack("n",strlen($message)).$message;
> $fwrite = fwrite($fp, $msg);
> if(!$fwrite) {
> $this->_pushFailed($pid);
> $this->_triggerError("Failed writing to stream.", E_USER_ERROR);
> }
> else {
> $this->_pushSuccess($pid);
> }
> }
> ////////////// END REPLACE EXISTING ////////////////
> Hope you can use this for your own projects!
> Regards Michael
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
yossi cohen <yossi.c... @gmail.com>
Date: Thu, 15 Mar 2012 11:32:33 +0200
Local: Thurs, Mar 15 2012 5:32 am
Subject: Re: [easyapns:749] Batching multiple notifications
Hi Michael,
Thank you for the mail
I have APNS package on my server for few month now , but I never tested a real broadcast is I have 70,000 users and I don't want it to take hours to sending
I want to use your suggestion for modification for my first try for broadcast
- did you use it already ?, if yes do you have idea how much it will take to send 70,000 messages ? - it is just to replace the current code with those you sent in your mail ?
Thanks!, Spring
2012/3/2 mlunoe <michael.lu... @gmail.com>
> I am very excited about this library. Thank you so much for all the
> work you put into this!
> At first it seemed very capable of handling multiple notifications as > it can handle many applications. However, on further inspection I > found that it does not batch notifications as Apple encourages you to > do on their apns guide (https://developer.apple.com/library/mac/ > #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ > CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it > opens a stream, sends a notification and closes the stream, which can > be optimised. Here are the code that opens a stream, sends all the > queued messages (in a batch) and closes the stream:
> ////////////// BEGIN NEW ADDITION ////////////////
> /** > * True if running in sandbox > * > * @var bool > * @access private > */ > private $isSandbox = true;
> /** > * The limit of how many messages to send > * @var int > * @access private > */ > private $limit = 100;
> private function _checkMessage($pid, $message, $token, $development) { > return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0 > && > strlen($development)!=0; > }
> ////////////// END NEW ADDITION ////////////////
> ////////////// BEGIN REPLACE EXISTING ////////////////
> private function _fetchMessages(){ > // only send one message per user... oldest message first > $sql = "SELECT > `apns_messages`.`pid`, > `apns_messages`.`message`, > `apns_devices`.`devicetoken` > FROM `apns_messages` > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > `apns_messages`.`clientid`) > WHERE `apns_messages`.`status`='queued' > AND `apns_messages`.`delivery` <= NOW() > AND `apns_devices`.`status`='active' > AND > `apns_devices`.`development`=".($this->isSandbox ? > "'sandbox'":"'production'"). > " GROUP BY `apns_messages`.`fk_device` > ORDER BY `apns_messages`.`created` ASC > LIMIT ".$this->limit.";"; > $development = $this->isSandbox ? 'sandbox': 'production'; > if($result = $this->db->query($sql)){ > if($result->num_rows){ > $ctx = stream_context_create(); > stream_context_set_option($ctx, 'ssl', > 'local_cert', $this- > >apnsData[$development]['certificate']); > $fp = > stream_socket_client($this->apnsData[$development]['ssl'], > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > STREAM_CLIENT_PERSISTENT), $ctx);
> while($row = $result->fetch_array(MYSQLI_ASSOC)){ > $pid = $this->db->prepare($row['pid']); > $message = > stripslashes($this->db->prepare($row['message'])); > $token = > $this->db->prepare($row['devicetoken']);
> if(!$fp){ > $this->_pushFailed($pid); > $this->_triggerError("Failed to > connect to APNS: {$error} > {$errorString}."); > } > else if(!$this->_checkMessage($pid, > $message, $token, > $development)) { > $this->_pushFailed($pid); > $this->_triggerError("Invalid > message for device pid: ". > $pid."."); > } > else { > $this->_pushMessage($fp, $pid, > $message, $token, $development);
> } > } > fclose($fp);
> $this->_checkFeedback($development); > } > } > }
> private function _flushMessages(){ > // send all the messages for each device > $sql = "SELECT > `apns_messages`.`pid`, > `apns_messages`.`message`, > `apns_devices`.`devicetoken` > FROM `apns_messages` > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > `apns_messages`.`clientid`) > WHERE `apns_messages`.`status`='queued' > AND `apns_messages`.`delivery` <= NOW() > AND `apns_devices`.`status`='active' > AND > `apns_devices`.`development`=".($this->isSandbox ? > "'sandbox'":"'production'"). > " ORDER BY `apns_messages`.`created` ASC > LIMIT ".$this->limit.";"; > $development = $this->isSandbox ? 'sandbox': 'production'; > if($result = $this->db->query($sql)){ > //var_dump ($result); > if($result->num_rows){ > $ctx = stream_context_create(); > stream_context_set_option($ctx, 'ssl', > 'local_cert', $this- > >apnsData[$development]['certificate']); > $fp = > stream_socket_client($this->apnsData[$development]['ssl'], > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > STREAM_CLIENT_PERSISTENT), $ctx); > while($row = $result->fetch_array(MYSQLI_ASSOC)){ > $pid = $this->db->prepare($row['pid']); > $message = > stripslashes($this->db->prepare($row['message'])); > $token = > $this->db->prepare($row['devicetoken']);
> if(!$fp){ > $this->_pushFailed($pid); > $this->_triggerError("Failed to > connect to APNS: {$error} > {$errorString}."); > } > else if(!$this->_checkMessage($pid, > $message, $token, > $development)) { > $this->_pushFailed($pid); > $this->_triggerError("Invalid > message for device pid: ". > $pid."."); > } > else { > $this->_pushMessage($fp, $pid, > $message, $token, $development);
> } > } > fclose($fp);
> $this->_checkFeedback($development); > } > } > }
> private function _pushMessage($fp, $pid, $message, $token, > $development){ > $msg = chr(0).pack("n",32).pack('H*', > $token).pack("n",strlen($message)).$message; > $fwrite = fwrite($fp, $msg); > if(!$fwrite) { > $this->_pushFailed($pid); > $this->_triggerError("Failed writing to stream.", > E_USER_ERROR); > } > else { > $this->_pushSuccess($pid); > } > }
> ////////////// END REPLACE EXISTING ////////////////
> Hope you can use this for your own projects!
> Regards Michael
> -- > You received this message because you are subscribed to the Google > Groups "Easy APNS" group. > To post to this group, send email to easyapns@googlegroups.com > To unsubscribe from this group, send email to > easyapns+unsubscribe@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/easyapns?hl=en
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Yossi Cohen <yossi.c... @gmail.com>
Date: Thu, 15 Mar 2012 11:14:54 +0200
Local: Thurs, Mar 15 2012 5:14 am
Subject: Re: [easyapns:749] Batching multiple notifications
Dear Michael ,
Thank you for your mail, I'm also like much APNS packages if works for m
On Mar 2, 2012, at 13:51, mlunoe <michael.lu... @gmail.com> wrote:
> I am very excited about this library. Thank you so much for all the
> work you put into this!
> At first it seemed very capable of handling multiple notifications as > it can handle many applications. However, on further inspection I > found that it does not batch notifications as Apple encourages you to > do on their apns guide (https://developer.apple.com/library/mac/ > #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ > CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it > opens a stream, sends a notification and closes the stream, which can > be optimised. Here are the code that opens a stream, sends all the > queued messages (in a batch) and closes the stream:
> ////////////// BEGIN NEW ADDITION ////////////////
> /** > * True if running in sandbox > * > * @var bool > * @access private > */ > private $isSandbox = true;
> /** > * The limit of how many messages to send > * @var int > * @access private > */ > private $limit = 100;
> private function _checkMessage($pid, $message, $token, $development) { > return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0 && > strlen($development)!=0; > }
> ////////////// END NEW ADDITION ////////////////
> ////////////// BEGIN REPLACE EXISTING ////////////////
> private function _fetchMessages(){ > // only send one message per user... oldest message first > $sql = "SELECT > `apns_messages`.`pid`, > `apns_messages`.`message`, > `apns_devices`.`devicetoken` > FROM `apns_messages` > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > `apns_messages`.`clientid`) > WHERE `apns_messages`.`status`='queued' > AND `apns_messages`.`delivery` <= NOW() > AND `apns_devices`.`status`='active' > AND `apns_devices`.`development`=".($this->isSandbox ? > "'sandbox'":"'production'"). > " GROUP BY `apns_messages`.`fk_device` > ORDER BY `apns_messages`.`created` ASC > LIMIT ".$this->limit.";"; > $development = $this->isSandbox ? 'sandbox': 'production'; > if($result = $this->db->query($sql)){ > if($result->num_rows){ > $ctx = stream_context_create(); > stream_context_set_option($ctx, 'ssl', 'local_cert', $this- >> apnsData[$development]['certificate']); > $fp = stream_socket_client($this->apnsData[$development]['ssl'], > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > STREAM_CLIENT_PERSISTENT), $ctx);
> while($row = $result->fetch_array(MYSQLI_ASSOC)){ > $pid = $this->db->prepare($row['pid']); > $message = stripslashes($this->db->prepare($row['message'])); > $token = $this->db->prepare($row['devicetoken']);
> if(!$fp){ > $this->_pushFailed($pid); > $this->_triggerError("Failed to connect to APNS: {$error} > {$errorString}."); > } > else if(!$this->_checkMessage($pid, $message, $token, > $development)) { > $this->_pushFailed($pid); > $this->_triggerError("Invalid message for device pid: ". > $pid."."); > } > else { > $this->_pushMessage($fp, $pid, $message, $token, $development);
> } > } > fclose($fp);
> $this->_checkFeedback($development); > } > } > }
> private function _flushMessages(){ > // send all the messages for each device > $sql = "SELECT > `apns_messages`.`pid`, > `apns_messages`.`message`, > `apns_devices`.`devicetoken` > FROM `apns_messages` > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > `apns_messages`.`clientid`) > WHERE `apns_messages`.`status`='queued' > AND `apns_messages`.`delivery` <= NOW() > AND `apns_devices`.`status`='active' > AND `apns_devices`.`development`=".($this->isSandbox ? > "'sandbox'":"'production'"). > " ORDER BY `apns_messages`.`created` ASC > LIMIT ".$this->limit.";"; > $development = $this->isSandbox ? 'sandbox': 'production'; > if($result = $this->db->query($sql)){ > //var_dump ($result); > if($result->num_rows){ > $ctx = stream_context_create(); > stream_context_set_option($ctx, 'ssl', 'local_cert', $this- >> apnsData[$development]['certificate']); > $fp = stream_socket_client($this->apnsData[$development]['ssl'], > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > STREAM_CLIENT_PERSISTENT), $ctx); > while($row = $result->fetch_array(MYSQLI_ASSOC)){ > $pid = $this->db->prepare($row['pid']); > $message = stripslashes($this->db->prepare($row['message'])); > $token = $this->db->prepare($row['devicetoken']);
> if(!$fp){ > $this->_pushFailed($pid); > $this->_triggerError("Failed to connect to APNS: {$error} > {$errorString}."); > } > else if(!$this->_checkMessage($pid, $message, $token, > $development)) { > $this->_pushFailed($pid); > $this->_triggerError("Invalid message for device pid: ". > $pid."."); > } > else { > $this->_pushMessage($fp, $pid, $message, $token, $development);
> } > } > fclose($fp);
> $this->_checkFeedback($development); > } > } > }
> private function _pushMessage($fp, $pid, $message, $token, > $development){ > $msg = chr(0).pack("n",32).pack('H*', > $token).pack("n",strlen($message)).$message; > $fwrite = fwrite($fp, $msg); > if(!$fwrite) { > $this->_pushFailed($pid); > $this->_triggerError("Failed writing to stream.", E_USER_ERROR); > } > else { > $this->_pushSuccess($pid); > } > }
> ////////////// END REPLACE EXISTING ////////////////
> Hope you can use this for your own projects!
> Regards Michael
> -- > You received this message because you are subscribed to the Google > Groups "Easy APNS" group. > To post to this group, send email to easyapns@googlegroups.com > To unsubscribe from this group, send email to > easyapns+unsubscribe@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/easyapns?hl=en
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
mlunoe <michael.lu... @gmail.com>
Date: Mon, 7 May 2012 02:08:37 -0700 (PDT)
Local: Mon, May 7 2012 5:08 am
Subject: Re: Batching multiple notifications
No, there is actually no difference. In the php source of easy apns
they have both _fetchMessages() and _flushMessages(), where the first
takes 100 messages at a time and the latter takes $this->limit, so it
is adjustable. I ended up deleting one of them to use only the
adjustable as they where the same.
On Mar 14, 3:43 pm, Guillaume <guilla... @gmail.com> wrote:
> _flushMessages() and _fetchMessages() are same functions?
> With theses modifications it seems it's possible to send push quickly.
> But if I have 90,000 tokens, and so I put the $limit = 100000; the
> $msg to send will be too large, no ?
> On 2 mar, 12:51, mlunoe <michael.lu... @gmail.com> wrote:
> > I am very excited about this library. Thank you so much for all the
> > work you put into this!
> > At first it seemed very capable of handling multiple notifications as
> > it can handle many applications. However, on further inspection I
> > found that it does not batch notifications as Apple encourages you to
> > do on their apns guide (https://developer.apple.com/library/mac/
> > #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/
> > CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it
> > opens a stream, sends a notification and closes the stream, which can
> > be optimised. Here are the code that opens a stream, sends all the
> > queued messages (in a batch) and closes the stream:
> > ////////////// BEGIN NEW ADDITION ////////////////
> > /**
> > * True if running in sandbox
> > *
> > * @var bool
> > * @access private
> > */
> > private $isSandbox = true;
> > /**
> > * The limit of how many messages to send
> > * @var int
> > * @access private
> > */
> > private $limit = 100;
> > private function _checkMessage($pid, $message, $token, $development) {
> > return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0 &&
> > strlen($development)!=0;
> > }
> > ////////////// END NEW ADDITION ////////////////
> > ////////////// BEGIN REPLACE EXISTING ////////////////
> > private function _fetchMessages(){
> > // only send one message per user... oldest message first
> > $sql = "SELECT
> > `apns_messages`.`pid`,
> > `apns_messages`.`message`,
> > `apns_devices`.`devicetoken`
> > FROM `apns_messages`
> > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> > `apns_messages`.`clientid`)
> > WHERE `apns_messages`.`status`='queued'
> > AND `apns_messages`.`delivery` <= NOW()
> > AND `apns_devices`.`status`='active'
> > AND `apns_devices`.`development`=".($this->isSandbox ?
> > "'sandbox'":"'production'").
> > " GROUP BY `apns_messages`.`fk_device`
> > ORDER BY `apns_messages`.`created` ASC
> > LIMIT ".$this->limit.";";
> > $development = $this->isSandbox ? 'sandbox': 'production';
> > if($result = $this->db->query($sql)){
> > if($result->num_rows){
> > $ctx = stream_context_create();
> > stream_context_set_option($ctx, 'ssl', 'local_cert', $this->apnsData[$development]['certificate']);
> > $fp = stream_socket_client($this->apnsData[$development]['ssl'],
> > $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> > STREAM_CLIENT_PERSISTENT), $ctx);
> > while($row = $result->fetch_array(MYSQLI_ASSOC)){
> > $pid = $this->db->prepare($row['pid']);
> > $message = stripslashes($this->db->prepare($row['message']));
> > $token = $this->db->prepare($row['devicetoken']);
> > if(!$fp){
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed to connect to APNS: {$error}
> > {$errorString}.");
> > }
> > else if(!$this->_checkMessage($pid, $message, $token,
> > $development)) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Invalid message for device pid: ".
> > $pid.".");
> > }
> > else {
> > $this->_pushMessage($fp, $pid, $message, $token, $development);
> > }
> > }
> > fclose($fp);
> > $this->_checkFeedback($development);
> > }
> > }
> > }
> > private function _flushMessages(){
> > // send all the messages for each device
> > $sql = "SELECT
> > `apns_messages`.`pid`,
> > `apns_messages`.`message`,
> > `apns_devices`.`devicetoken`
> > FROM `apns_messages`
> > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> > `apns_messages`.`clientid`)
> > WHERE `apns_messages`.`status`='queued'
> > AND `apns_messages`.`delivery` <= NOW()
> > AND `apns_devices`.`status`='active'
> > AND `apns_devices`.`development`=".($this->isSandbox ?
> > "'sandbox'":"'production'").
> > " ORDER BY `apns_messages`.`created` ASC
> > LIMIT ".$this->limit.";";
> > $development = $this->isSandbox ? 'sandbox': 'production';
> > if($result = $this->db->query($sql)){
> > //var_dump ($result);
> > if($result->num_rows){
> > $ctx = stream_context_create();
> > stream_context_set_option($ctx, 'ssl', 'local_cert', $this->apnsData[$development]['certificate']);
> > $fp = stream_socket_client($this->apnsData[$development]['ssl'],
> > $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> > STREAM_CLIENT_PERSISTENT), $ctx);
> > while($row = $result->fetch_array(MYSQLI_ASSOC)){
> > $pid = $this->db->prepare($row['pid']);
> > $message = stripslashes($this->db->prepare($row['message']));
> > $token = $this->db->prepare($row['devicetoken']);
> > if(!$fp){
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed to connect to APNS: {$error}
> > {$errorString}.");
> > }
> > else if(!$this->_checkMessage($pid, $message, $token,
> > $development)) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Invalid message for device pid: ".
> > $pid.".");
> > }
> > else {
> > $this->_pushMessage($fp, $pid, $message, $token, $development);
> > }
> > }
> > fclose($fp);
> > $this->_checkFeedback($development);
> > }
> > }
> > }
> > private function _pushMessage($fp, $pid, $message, $token,
> > $development){
> > $msg = chr(0).pack("n",32).pack('H*',
> > $token).pack("n",strlen($message)).$message;
> > $fwrite = fwrite($fp, $msg);
> > if(!$fwrite) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed writing to stream.", E_USER_ERROR);
> > }
> > else {
> > $this->_pushSuccess($pid);
> > }
> > }
> > ////////////// END REPLACE EXISTING ////////////////
> > Hope you can use this for your own projects!
> > Regards Michael
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
mlunoe <michael.lu... @gmail.com>
Date: Mon, 7 May 2012 02:11:29 -0700 (PDT)
Local: Mon, May 7 2012 5:11 am
Subject: Re: Batching multiple notifications
They are the same. In apns php source they vary by _fetchMessages()
always takes $this->limit messages at a time, whereas _flushMessages()
takes all of them. I ended up only using _fetchMessages(), because I
can better control what happens.
On Mar 14, 3:43 pm, Guillaume <guilla... @gmail.com> wrote:
> _flushMessages() and _fetchMessages() are same functions?
> With theses modifications it seems it's possible to send push quickly.
> But if I have 90,000 tokens, and so I put the $limit = 100000; the
> $msg to send will be too large, no ?
> On 2 mar, 12:51, mlunoe <michael.lu... @gmail.com> wrote:
> > I am very excited about this library. Thank you so much for all the
> > work you put into this!
> > At first it seemed very capable of handling multiple notifications as
> > it can handle many applications. However, on further inspection I
> > found that it does not batch notifications as Apple encourages you to
> > do on their apns guide (https://developer.apple.com/library/mac/
> > #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/
> > CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it
> > opens a stream, sends a notification and closes the stream, which can
> > be optimised. Here are the code that opens a stream, sends all the
> > queued messages (in a batch) and closes the stream:
> > ////////////// BEGIN NEW ADDITION ////////////////
> > /**
> > * True if running in sandbox
> > *
> > * @var bool
> > * @access private
> > */
> > private $isSandbox = true;
> > /**
> > * The limit of how many messages to send
> > * @var int
> > * @access private
> > */
> > private $limit = 100;
> > private function _checkMessage($pid, $message, $token, $development) {
> > return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0 &&
> > strlen($development)!=0;
> > }
> > ////////////// END NEW ADDITION ////////////////
> > ////////////// BEGIN REPLACE EXISTING ////////////////
> > private function _fetchMessages(){
> > // only send one message per user... oldest message first
> > $sql = "SELECT
> > `apns_messages`.`pid`,
> > `apns_messages`.`message`,
> > `apns_devices`.`devicetoken`
> > FROM `apns_messages`
> > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> > `apns_messages`.`clientid`)
> > WHERE `apns_messages`.`status`='queued'
> > AND `apns_messages`.`delivery` <= NOW()
> > AND `apns_devices`.`status`='active'
> > AND `apns_devices`.`development`=".($this->isSandbox ?
> > "'sandbox'":"'production'").
> > " GROUP BY `apns_messages`.`fk_device`
> > ORDER BY `apns_messages`.`created` ASC
> > LIMIT ".$this->limit.";";
> > $development = $this->isSandbox ? 'sandbox': 'production';
> > if($result = $this->db->query($sql)){
> > if($result->num_rows){
> > $ctx = stream_context_create();
> > stream_context_set_option($ctx, 'ssl', 'local_cert', $this->apnsData[$development]['certificate']);
> > $fp = stream_socket_client($this->apnsData[$development]['ssl'],
> > $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> > STREAM_CLIENT_PERSISTENT), $ctx);
> > while($row = $result->fetch_array(MYSQLI_ASSOC)){
> > $pid = $this->db->prepare($row['pid']);
> > $message = stripslashes($this->db->prepare($row['message']));
> > $token = $this->db->prepare($row['devicetoken']);
> > if(!$fp){
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed to connect to APNS: {$error}
> > {$errorString}.");
> > }
> > else if(!$this->_checkMessage($pid, $message, $token,
> > $development)) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Invalid message for device pid: ".
> > $pid.".");
> > }
> > else {
> > $this->_pushMessage($fp, $pid, $message, $token, $development);
> > }
> > }
> > fclose($fp);
> > $this->_checkFeedback($development);
> > }
> > }
> > }
> > private function _flushMessages(){
> > // send all the messages for each device
> > $sql = "SELECT
> > `apns_messages`.`pid`,
> > `apns_messages`.`message`,
> > `apns_devices`.`devicetoken`
> > FROM `apns_messages`
> > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> > `apns_messages`.`clientid`)
> > WHERE `apns_messages`.`status`='queued'
> > AND `apns_messages`.`delivery` <= NOW()
> > AND `apns_devices`.`status`='active'
> > AND `apns_devices`.`development`=".($this->isSandbox ?
> > "'sandbox'":"'production'").
> > " ORDER BY `apns_messages`.`created` ASC
> > LIMIT ".$this->limit.";";
> > $development = $this->isSandbox ? 'sandbox': 'production';
> > if($result = $this->db->query($sql)){
> > //var_dump ($result);
> > if($result->num_rows){
> > $ctx = stream_context_create();
> > stream_context_set_option($ctx, 'ssl', 'local_cert', $this->apnsData[$development]['certificate']);
> > $fp = stream_socket_client($this->apnsData[$development]['ssl'],
> > $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> > STREAM_CLIENT_PERSISTENT), $ctx);
> > while($row = $result->fetch_array(MYSQLI_ASSOC)){
> > $pid = $this->db->prepare($row['pid']);
> > $message = stripslashes($this->db->prepare($row['message']));
> > $token = $this->db->prepare($row['devicetoken']);
> > if(!$fp){
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed to connect to APNS: {$error}
> > {$errorString}.");
> > }
> > else if(!$this->_checkMessage($pid, $message, $token,
> > $development)) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Invalid message for device pid: ".
> > $pid.".");
> > }
> > else {
> > $this->_pushMessage($fp, $pid, $message, $token, $development);
> > }
> > }
> > fclose($fp);
> > $this->_checkFeedback($development);
> > }
> > }
> > }
> > private function _pushMessage($fp, $pid, $message, $token,
> > $development){
> > $msg = chr(0).pack("n",32).pack('H*',
> > $token).pack("n",strlen($message)).$message;
> > $fwrite = fwrite($fp, $msg);
> > if(!$fwrite) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed writing to stream.", E_USER_ERROR);
> > }
> > else {
> > $this->_pushSuccess($pid);
> > }
> > }
> > ////////////// END REPLACE EXISTING ////////////////
> > Hope you can use this for your own projects!
> > Regards Michael
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
mlunoe <michael.lu... @gmail.com>
Date: Mon, 7 May 2012 02:30:54 -0700 (PDT)
Local: Mon, May 7 2012 5:30 am
Subject: Re: Batching multiple notifications
Yes, I used it to build a campions league app to send out 10,000
messages each minute and it takes about ten seconds for it to finish.
I don't know Apples limit for batching, so to avoid your server
getting banned from using apn, I would search the web for a limit. And
please post what you find here, so we can all learn! :)
Yes, it should be possible to just replace with my code and add the
"new addition" for it to work. No, errors with it have been reported
so far, but please keep me updated!
br. Michael
On Mar 15, 11:32 am, yossi cohen <yossi.c... @gmail.com> wrote:
> Hi Michael,
> Thank you for the mail
> I have APNS package on my server for few month now , but I never tested a
> real broadcast
> is I have 70,000 users and I don't want it to take hours to sending
> I want to use your suggestion for modification for my first try for
> broadcast
> - did you use it already ?, if yes do you have idea how much it will take
> to send 70,000 messages ?
> - it is just to replace the current code with those you sent in your mail ?
> Thanks!,
> Spring
> 2012/3/2 mlunoe <michael.lu... @gmail.com>
> > I am very excited about this library. Thank you so much for all the
> > work you put into this!
> > At first it seemed very capable of handling multiple notifications as
> > it can handle many applications. However, on further inspection I
> > found that it does not batch notifications as Apple encourages you to
> > do on their apns guide (https://developer.apple.com/library/mac/
> > #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/
> > CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it
> > opens a stream, sends a notification and closes the stream, which can
> > be optimised. Here are the code that opens a stream, sends all the
> > queued messages (in a batch) and closes the stream:
> > ////////////// BEGIN NEW ADDITION ////////////////
> > /**
> > * True if running in sandbox
> > *
> > * @var bool
> > * @access private
> > */
> > private $isSandbox = true;
> > /**
> > * The limit of how many messages to send
> > * @var int
> > * @access private
> > */
> > private $limit = 100;
> > private function _checkMessage($pid, $message, $token, $development) {
> > return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0
> > &&
> > strlen($development)!=0;
> > }
> > ////////////// END NEW ADDITION ////////////////
> > ////////////// BEGIN REPLACE EXISTING ////////////////
> > private function _fetchMessages(){
> > // only send one message per user... oldest message first
> > $sql = "SELECT
> > `apns_messages`.`pid`,
> > `apns_messages`.`message`,
> > `apns_devices`.`devicetoken`
> > FROM `apns_messages`
> > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> > `apns_messages`.`clientid`)
> > WHERE `apns_messages`.`status`='queued'
> > AND `apns_messages`.`delivery` <= NOW()
> > AND `apns_devices`.`status`='active'
> > AND
> > `apns_devices`.`development`=".($this->isSandbox ?
> > "'sandbox'":"'production'").
> > " GROUP BY `apns_messages`.`fk_device`
> > ORDER BY `apns_messages`.`created` ASC
> > LIMIT ".$this->limit.";";
> > $development = $this->isSandbox ? 'sandbox': 'production';
> > if($result = $this->db->query($sql)){
> > if($result->num_rows){
> > $ctx = stream_context_create();
> > stream_context_set_option($ctx, 'ssl',
> > 'local_cert', $this-
> > >apnsData[$development]['certificate']);
> > $fp =
> > stream_socket_client($this->apnsData[$development]['ssl'],
> > $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> > STREAM_CLIENT_PERSISTENT), $ctx);
> > while($row = $result->fetch_array(MYSQLI_ASSOC)){
> > $pid = $this->db->prepare($row['pid']);
> > $message =
> > stripslashes($this->db->prepare($row['message']));
> > $token =
> > $this->db->prepare($row['devicetoken']);
> > if(!$fp){
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed to
> > connect to APNS: {$error}
> > {$errorString}.");
> > }
> > else if(!$this->_checkMessage($pid,
> > $message, $token,
> > $development)) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Invalid
> > message for device pid: ".
> > $pid.".");
> > }
> > else {
> > $this->_pushMessage($fp, $pid,
> > $message, $token, $development);
> > }
> > }
> > fclose($fp);
> > $this->_checkFeedback($development);
> > }
> > }
> > }
> > private function _flushMessages(){
> > // send all the messages for each device
> > $sql = "SELECT
> > `apns_messages`.`pid`,
> > `apns_messages`.`message`,
> > `apns_devices`.`devicetoken`
> > FROM `apns_messages`
> > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` =
> > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` =
> > `apns_messages`.`clientid`)
> > WHERE `apns_messages`.`status`='queued'
> > AND `apns_messages`.`delivery` <= NOW()
> > AND `apns_devices`.`status`='active'
> > AND
> > `apns_devices`.`development`=".($this->isSandbox ?
> > "'sandbox'":"'production'").
> > " ORDER BY `apns_messages`.`created` ASC
> > LIMIT ".$this->limit.";";
> > $development = $this->isSandbox ? 'sandbox': 'production';
> > if($result = $this->db->query($sql)){
> > //var_dump ($result);
> > if($result->num_rows){
> > $ctx = stream_context_create();
> > stream_context_set_option($ctx, 'ssl',
> > 'local_cert', $this-
> > >apnsData[$development]['certificate']);
> > $fp =
> > stream_socket_client($this->apnsData[$development]['ssl'],
> > $error, $errorString, 100, (STREAM_CLIENT_CONNECT|
> > STREAM_CLIENT_PERSISTENT), $ctx);
> > while($row = $result->fetch_array(MYSQLI_ASSOC)){
> > $pid = $this->db->prepare($row['pid']);
> > $message =
> > stripslashes($this->db->prepare($row['message']));
> > $token =
> > $this->db->prepare($row['devicetoken']);
> > if(!$fp){
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed to
> > connect to APNS: {$error}
> > {$errorString}.");
> > }
> > else if(!$this->_checkMessage($pid,
> > $message, $token,
> > $development)) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Invalid
> > message for device pid: ".
> > $pid.".");
> > }
> > else {
> > $this->_pushMessage($fp, $pid,
> > $message, $token, $development);
> > }
> > }
> > fclose($fp);
> > $this->_checkFeedback($development);
> > }
> > }
> > }
> > private function _pushMessage($fp, $pid, $message, $token,
> > $development){
> > $msg = chr(0).pack("n",32).pack('H*',
> > $token).pack("n",strlen($message)).$message;
> > $fwrite = fwrite($fp, $msg);
> > if(!$fwrite) {
> > $this->_pushFailed($pid);
> > $this->_triggerError("Failed writing to stream.",
> > E_USER_ERROR);
> > }
> > else {
> > $this->_pushSuccess($pid);
> > }
> > }
> > ////////////// END REPLACE EXISTING ////////////////
> > Hope you can use this for your own projects!
> > Regards
...
read more »
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Caizer Kim <cai... @gmail.com>
Date: Thu, 9 Aug 2012 03:35:31 -0700 (PDT)
Local: Thurs, Aug 9 2012 6:35 am
Subject: Re: Batching multiple notifications
Hi, have you used your code with most recent version?
I've got to send over 200,000 notification a day, and I found out that it takes so long time. It seems like the current version of easy apns delivers 1 notification per second.
If it is possible to be used with most recent version.. I would like to apply it.
Thanks very much.
I am very excited about this library. Thank you so much for all the
> work you put into this!
> At first it seemed very capable of handling multiple notifications as > it can handle many applications. However, on further inspection I > found that it does not batch notifications as Apple encourages you to > do on their apns guide (https://developer.apple.com/library/mac/ > #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ > CommunicatingWIthAPS/CommunicatingWIthAPS.html<https://developer.apple.com/library/mac/#documentation/NetworkingInte... >). > For each message it > opens a stream, sends a notification and closes the stream, which can > be optimised. Here are the code that opens a stream, sends all the > queued messages (in a batch) and closes the stream:
> ////////////// BEGIN NEW ADDITION ////////////////
> /** > * True if running in sandbox > * > * @var bool > * @access private > */ > private $isSandbox = true;
> /** > * The limit of how many messages to send > * @var int > * @access private > */ > private $limit = 100;
> private function _checkMessage($pid, $message, $token, $development) { > return strlen($pid)!=0 && strlen($message)!=0 && strlen($token)!=0 > && > strlen($development)!=0; > }
> ////////////// END NEW ADDITION ////////////////
> ////////////// BEGIN REPLACE EXISTING ////////////////
> private function _fetchMessages(){ > // only send one message per user... oldest message first > $sql = "SELECT > `apns_messages`.`pid`, > `apns_messages`.`message`, > `apns_devices`.`devicetoken` > FROM `apns_messages` > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > `apns_messages`.`clientid`) > WHERE `apns_messages`.`status`='queued' > AND `apns_messages`.`delivery` <= NOW() > AND `apns_devices`.`status`='active' > AND > `apns_devices`.`development`=".($this->isSandbox ? > "'sandbox'":"'production'"). > " GROUP BY `apns_messages`.`fk_device` > ORDER BY `apns_messages`.`created` ASC > LIMIT ".$this->limit.";"; > $development = $this->isSandbox ? 'sandbox': 'production'; > if($result = $this->db->query($sql)){ > if($result->num_rows){ > $ctx = stream_context_create(); > stream_context_set_option($ctx, 'ssl', > 'local_cert', $this- > >apnsData[$development]['certificate']); > $fp = > stream_socket_client($this->apnsData[$development]['ssl'], > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > STREAM_CLIENT_PERSISTENT), $ctx);
> while($row = $result->fetch_array(MYSQLI_ASSOC)){ > $pid = $this->db->prepare($row['pid']); > $message = > stripslashes($this->db->prepare($row['message'])); > $token = > $this->db->prepare($row['devicetoken']);
> if(!$fp){ > $this->_pushFailed($pid); > $this->_triggerError("Failed to > connect to APNS: {$error} > {$errorString}."); > } > else if(!$this->_checkMessage($pid, > $message, $token, > $development)) { > $this->_pushFailed($pid); > $this->_triggerError("Invalid > message for device pid: ". > $pid."."); > } > else { > $this->_pushMessage($fp, $pid, > $message, $token, $development);
> } > } > fclose($fp);
> $this->_checkFeedback($development); > } > } > }
> private function _flushMessages(){ > // send all the messages for each device > $sql = "SELECT > `apns_messages`.`pid`, > `apns_messages`.`message`, > `apns_devices`.`devicetoken` > FROM `apns_messages` > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > `apns_messages`.`clientid`) > WHERE `apns_messages`.`status`='queued' > AND `apns_messages`.`delivery` <= NOW() > AND `apns_devices`.`status`='active' > AND > `apns_devices`.`development`=".($this->isSandbox ? > "'sandbox'":"'production'"). > " ORDER BY `apns_messages`.`created` ASC > LIMIT ".$this->limit.";"; > $development = $this->isSandbox ? 'sandbox': 'production'; > if($result = $this->db->query($sql)){ > //var_dump ($result); > if($result->num_rows){ > $ctx = stream_context_create(); > stream_context_set_option($ctx, 'ssl', > 'local_cert', $this- > >apnsData[$development]['certificate']); > $fp = > stream_socket_client($this->apnsData[$development]['ssl'], > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > STREAM_CLIENT_PERSISTENT), $ctx); > while($row = $result->fetch_array(MYSQLI_ASSOC)){ > $pid = $this->db->prepare($row['pid']); > $message = > stripslashes($this->db->prepare($row['message'])); > $token = > $this->db->prepare($row['devicetoken']);
> if(!$fp){ > $this->_pushFailed($pid); > $this->_triggerError("Failed to > connect to APNS: {$error} > {$errorString}."); > } > else if(!$this->_checkMessage($pid, > $message, $token, > $development)) { > $this->_pushFailed($pid); > $this->_triggerError("Invalid > message for device pid: ". > $pid."."); > } > else { > $this->_pushMessage($fp, $pid, > $message, $token, $development);
> } > } > fclose($fp);
> $this->_checkFeedback($development); > } > } > }
> private function _pushMessage($fp, $pid, $message, $token, > $development){ > $msg = chr(0).pack("n",32).pack('H*', > $token).pack("n",strlen($message)).$message; > $fwrite = fwrite($fp, $msg); > if(!$fwrite) { > $this->_pushFailed($pid); > $this->_triggerError("Failed writing to stream.", > E_USER_ERROR); > } > else { > $this->_pushSuccess($pid); > } > }
> ////////////// END REPLACE EXISTING ////////////////
> Hope you can use this for your own projects!
> Regards Michael
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Piersoft <pierso... @gmail.com>
Date: Wed, 19 Sep 2012 06:31:47 -0700 (PDT)
Local: Wed, Sep 19 2012 9:31 am
Subject: Re: Batching multiple notifications
can you post the code that you use?
Il giorno lunedì 7 maggio 2012 11:08:37 UTC+2, mlunoe ha scritto:
> No, there is actually no difference. In the php source of easy apns > they have both _fetchMessages() and _flushMessages(), where the first > takes 100 messages at a time and the latter takes $this->limit, so it > is adjustable. I ended up deleting one of them to use only the > adjustable as they where the same.
> On Mar 14, 3:43 pm, Guillaume <guilla... @gmail.com> wrote: > > _flushMessages() and _fetchMessages() are same functions?
> > With theses modifications it seems it's possible to send push quickly. > > But if I have 90,000 tokens, and so I put the $limit = 100000; the > > $msg to send will be too large, no ?
> > On 2 mar, 12:51, mlunoe <michael.lu... @gmail.com> wrote:
> > > I am very excited about this library. Thank you so much for all the > > > work you put into this!
> > > At first it seemed very capable of handling multiple notifications as > > > it can handle many applications. However, on further inspection I > > > found that it does not batch notifications as Apple encourages you to > > > do on their apns guide (https://developer.apple.com/library/mac/ > > > #documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ > > > CommunicatingWIthAPS/CommunicatingWIthAPS.html). For each message it > > > opens a stream, sends a notification and closes the stream, which can > > > be optimised. Here are the code that opens a stream, sends all the > > > queued messages (in a batch) and closes the stream:
> > > ////////////// BEGIN NEW ADDITION ////////////////
> > > /** > > > * True if running in sandbox > > > * > > > * @var bool > > > * @access private > > > */ > > > private $isSandbox = true;
> > > /** > > > * The limit of how many messages to send > > > * @var int > > > * @access private > > > */ > > > private $limit = 100;
> > > private function _checkMessage($pid, $message, $token, $development) { > > > return strlen($pid)!=0 && strlen($message)!=0 && > strlen($token)!=0 && > > > strlen($development)!=0;
> > > }
> > > ////////////// END NEW ADDITION ////////////////
> > > ////////////// BEGIN REPLACE EXISTING ////////////////
> > > private function _fetchMessages(){ > > > // only send one message per user... oldest message first > > > $sql = "SELECT > > > `apns_messages`.`pid`, > > > `apns_messages`.`message`, > > > `apns_devices`.`devicetoken` > > > FROM `apns_messages` > > > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > > > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > > > `apns_messages`.`clientid`) > > > WHERE `apns_messages`.`status`='queued' > > > AND `apns_messages`.`delivery` <= NOW() > > > AND `apns_devices`.`status`='active' > > > AND > `apns_devices`.`development`=".($this->isSandbox ? > > > "'sandbox'":"'production'"). > > > " GROUP BY `apns_messages`.`fk_device` > > > ORDER BY `apns_messages`.`created` ASC > > > LIMIT ".$this->limit.";"; > > > $development = $this->isSandbox ? 'sandbox': 'production'; > > > if($result = $this->db->query($sql)){ > > > if($result->num_rows){ > > > $ctx = stream_context_create(); > > > stream_context_set_option($ctx, 'ssl', > 'local_cert', $this->apnsData[$development]['certificate']);
> > > $fp = > stream_socket_client($this->apnsData[$development]['ssl'], > > > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > > > STREAM_CLIENT_PERSISTENT), $ctx);
> > > while($row = > $result->fetch_array(MYSQLI_ASSOC)){ > > > $pid = > $this->db->prepare($row['pid']); > > > $message = > stripslashes($this->db->prepare($row['message'])); > > > $token = > $this->db->prepare($row['devicetoken']);
> > > if(!$fp){ > > > $this->_pushFailed($pid); > > > $this->_triggerError("Failed > to connect to APNS: {$error} > > > {$errorString}."); > > > } > > > else if(!$this->_checkMessage($pid, > $message, $token, > > > $development)) { > > > $this->_pushFailed($pid); > > > $this->_triggerError("Invalid > message for device pid: ". > > > $pid."."); > > > } > > > else { > > > $this->_pushMessage($fp, $pid, > $message, $token, $development);
> > > } > > > } > > > fclose($fp);
> > > $this->_checkFeedback($development); > > > } > > > }
> > > }
> > > private function _flushMessages(){ > > > // send all the messages for each device > > > $sql = "SELECT > > > `apns_messages`.`pid`, > > > `apns_messages`.`message`, > > > `apns_devices`.`devicetoken` > > > FROM `apns_messages` > > > LEFT JOIN `apns_devices` ON (`apns_devices`.`pid` = > > > `apns_messages`.`fk_device` AND `apns_devices`.`clientid` = > > > `apns_messages`.`clientid`) > > > WHERE `apns_messages`.`status`='queued' > > > AND `apns_messages`.`delivery` <= NOW() > > > AND `apns_devices`.`status`='active' > > > AND > `apns_devices`.`development`=".($this->isSandbox ? > > > "'sandbox'":"'production'"). > > > " ORDER BY `apns_messages`.`created` ASC > > > LIMIT ".$this->limit.";"; > > > $development = $this->isSandbox ? 'sandbox': 'production'; > > > if($result = $this->db->query($sql)){ > > > //var_dump ($result); > > > if($result->num_rows){ > > > $ctx = stream_context_create(); > > > stream_context_set_option($ctx, 'ssl', > 'local_cert', $this->apnsData[$development]['certificate']);
> > > $fp = > stream_socket_client($this->apnsData[$development]['ssl'], > > > $error, $errorString, 100, (STREAM_CLIENT_CONNECT| > > > STREAM_CLIENT_PERSISTENT), $ctx); > > > while($row = > $result->fetch_array(MYSQLI_ASSOC)){ > > > $pid = > $this->db->prepare($row['pid']); > > > $message = > stripslashes($this->db->prepare($row['message'])); > > > $token = > $this->db->prepare($row['devicetoken']);
> > > if(!$fp){ > > > $this->_pushFailed($pid); > > > $this->_triggerError("Failed > to connect to APNS: {$error} > > > {$errorString}."); > > > } > > > else if(!$this->_checkMessage($pid, > $message, $token, > > > $development)) { > > > $this->_pushFailed($pid); > > > $this->_triggerError("Invalid > message for device pid: ". > > > $pid."."); > > > } > > > else { > > > $this->_pushMessage($fp, $pid, > $message, $token, $development);
> > > } > > > } > > > fclose($fp);
> > > $this->_checkFeedback($development); > > > } > > > }
> > > }
> > > private function _pushMessage($fp, $pid, $message, $token, > > > $development){ > > > $msg = chr(0).pack("n",32).pack('H*', > > > $token).pack("n",strlen($message)).$message; > > > $fwrite = fwrite($fp, $msg); > > > if(!$fwrite) { > > > $this->_pushFailed($pid); > > > $this->_triggerError("Failed writing to stream.", > E_USER_ERROR); > > > } > > > else { > > > $this->_pushSuccess($pid); > > > }
> > > }
> > > ////////////// END REPLACE EXISTING ////////////////
> > > Hope you can use this for your own projects!
> > > Regards Michael
You must
Sign in before you can post messages.
You do not have the permission required to post.