Quantcast
Channel: PHP vs .Net » PHP
Viewing all articles
Browse latest Browse all 10

Facebook Notifications –"An unknown error occurred (out of memory)"

$
0
0

Over the last few months, I've worked with the Facebook Notification system many times, and there has always been a moderate-to-high level of frustration with it. It is difficult to test on a development application, because you simply don't have the same number of users as a live application, and the application settings on a dev app are different, which affects your allocation of allowed notifications.

One of the prevalent errors I was getting for a long time was that a notification sent to a large number of users (application-to-user notification) would invariably fail with an Exception thrown from the Facebook PHP client library. My notification controller code in a particular application was set up to catch Exceptions and display the error into the administration control panel. However, "An unknown error occurred (out of memory)" is about as helpful as you might imagine. Yay Facebook. The only thing going for this particular error is that it's an iota more helpful than Facebook's documentation, which you quickly learn to distrust as out-of-date or just plain wrong.

The logic

My notification function logic was fairly simple: Accept an array of Facebook user ids, run an FQL query against Facebook to make sure the users all had the application installed, remove any ids that didn't, then use the Notifications.send() method (via the PHP client library's $facebook->api_client->notifications_send() method) to fire off the message.

No problems on development. On production, it was a giant party of "An unknown error occurred (out of memory)" errors.

At first I thought that Notifications.send() couldn't handle a lot of user ids (I was giving it at least 5000), so I put a loop in to break it up into several small "chunk sends". I went all the way down to 500 users per request, and nothing seemed to change, other than I was probably wasting my allocated notifications. The only silver lining to doing this testing on a production server was that the failed notifications didn't seem to go out to anyone, although that's impossible to tell for sure.

It's not the size of the notification, it's how you verify it.

I struggled with this for a long while until I realized that there was only one other possible location for Facebook to throw this error, and that was with the FQL query. I moved my "chunking" loop to work with the FQL as well, and I finally had relief from the "unknown" error. My conclusion therefore is that FQL queries might not be able to handle a large result set.

Since the documentation and forums couldn't give me any help, I thought I'd post my working code and explanation here, in the hopes that someone might find it useful.

Note that the Facebook object has been previously set as a property of the Controller that is executing this function, so it is accessed via $this->facebook here. You can see how the original array is broken into separate requests of approximately 500 users each, with each chunk of users being verified in turn. I have no idea what a safe number of users would be, however 500 seems to be working for me (for now).

/**
 * Sends a Facebook Notification message to all given users of an application.
 *
 * @param array $facebookIds Array of Facebook IDs to send the notification to.
 * @param string $msg Notification message to send.
 * @return int Count of how many users were sent the message.
 * @link http://wiki.developers.facebook.com/index.php/Notifications.send
 */
public function notifyMultipleUsers($facebookIds, $msg)
{
	if (! is_array($facebookIds) || count($facebookIds) == 0) {
		throw new Exception('No user ids given to notifyMultipleUsers().');
	}
	$reqSize = 500;
	$numUsers = 0;
	while(count($facebookIds) > 0) {
		$tmpIds = array_splice($facebookIds,0,$reqSize);
		//Check against Facebook database to verify which users have the app installed.
		$fql = 'SELECT uid FROM user '.
		       'WHERE is_app_user=1 AND uid IN ('.implode(',',$tmpIds).')';
		$fqlRes = $this->facebook->api_client->fql_query($fql);
		$appUsers = array();
		foreach($fqlRes as $a) {
			$appUsers[] = $a['uid'];
		}
		$c = count($appUsers);
		if ($c > 0) {
			$this->facebook->api_client->notifications_send(
				implode(',',$appUsers),$msg,'app_to_user'
			);
			$numUsers += $c;
		}
	}
	return $numUsers;
}

Viewing all articles
Browse latest Browse all 10

Trending Articles