Every so often, the Facebook API will go off into the weeds for whatever reason, and throw something like this:

Facebook API exception fb_call_method failed calling admin.getAppProperties. .
#0 /var/www/html/mysite/sites/all/modules/fb/fb.module(261): fb_call_method(Object(Facebook), 'admin.getAppPro...', Array)
#1 [internal function]: fb_init()
#2 /var/www/html/mysite/includes/module.inc(483): call_user_func_array('fb_init', Array)
#3 /var/www/html/mysite/includes/common.inc(2677): module_invoke_all('init')
#4 /var/www/html/mysite/includes/bootstrap.inc(1203): _drupal_bootstrap_full()
#5 /var/www/html/mysite/includes/bootstrap.inc(1110): _drupal_bootstrap(8)
#6 /var/www/html/mysite/index.php(16): drupal_bootstrap(8)
#7 {main}
$_REQUEST:
Array
(
    [q] => people/mysite/foo
)


REQUEST_URI:
/people/mysite/foo

Not much to be done, I guess, but set up a default exception handler and get ready to catch FacebookAPIException. I'm skating on the edge of my competence here; my current plan is to add something like this to template.php:

function vr_exception_handler($exception) {
    switch (get_class($exception)) {
        case "FacebookApiException":
            drupal_goto('facebook-is-down');
        default:
	     // Else use default exception class
	     echo $exception->getMessage();
    }
}

set_exception_handler('vr_exception_handler');

where /facebook-is-down is a failwhale-type page that reports the problem in some reasonable way to the user.

Does this make sense? Is there a better way to handle what I'm trying to do here? Thanks much!

Comments

jim_at_miramontes’s picture

Sorry, I guess -- this morning's coffee is kicking in a little late. I found a way to test this, and, no, putting the code into template.php didn't work.

What does seem to work, however, is to put the vr_exception_handler function and set_exception_handler call in a module's hook_init function -- this will get it installed after fb.module et al are loaded, so the exception type exists, and all the throwing and catching seems to work.

Better suggestions, of course, are welcome...

jim_at_miramontes’s picture

Bump. No, the approach noted above doesn't really work; my site is still crashing when Facebook is in the weeds. To me, the problem looks like a matter that the error is happening inside fb_init, and my module's hook_init handler hasn't run yet. Thus the exception handler hasn't been set up yet, so it can't do anything.

Is there any way to deal with this? Could I force my module containing this hook to load at the very beginning of the module-loading process (somehow -- I think there's a way to do this), so that the exception handler is defined when/if the API exception happens? Thanks!

jim_at_miramontes’s picture

I've got something that works here that is either wonderfully principled or a terrible hack: When Facebook is down, the first bit of code that seems to discover this fact is in fb_init() -- the call to fb_call_method:
$props = fb_call_method($_fb, 'admin.getAppProperties', array('properties' => 'base_domains'));
fails. (See the original backtrace at the top of this post.) So I've currently put a try/catch block around this statement that watches for exceptions of class FacebookApiException. If it gets such a thing, it does a drupal_goto to /facebook-is-down.php, a static page that is meant to (at least) throw up some sort of failwhale notification to the user. If some other kind of exception happens, I log it via fb_log_exception and let things continue.

Like I said, I hope that there's something rational about what I'm doing here. I haven't exercised this much in real-world situations, but I'll report back if anything bad seems to happen. Meanwhile, if anyone sees anything wrong with this scheme, please speak up. Thanks!

szantog’s picture

Title: Sanity check re handling FacebookAPIException » Using rest api in fb_init often causes FacebookAPIException
Version: 6.x-3.1 » 7.x-3.x-dev
Component: Facebook Connect » Code
Category: support » bug

The key of this problem I think, should change to old rest api based method to Graph Api. Now, I haven't any idea how to solve this. To get base domains of an application needs Application Page Access Tokens. I didn't find function in fb module, to create this, I think, because the fb module doesn't store any data from users who has manage application facebook role.

So

  1. We can get the user id of admins of application.
  2. Need to create own page access tokens.
  3. Then fetch base_domains via graph api.
szantog’s picture

Priority: Normal » Major
Issue tags: +Performance

Hmm.. I've hacked this, applied manually my site's base_domains in fb_init, and the page generation time decreased at least 50%! It means, that api call in fb_init is very expensive. I will thinking about, how to solve this.

webfaqtory’s picture

I highly suggest hardcoding your base_domains in the fb.module. I'm as much against hacking modules as the next man but the performance boost is dramatic. Our page loads are now < 1 second as opposed to 3-5 seconds. To give an example for our belocal.com site:

$props['base_domains'][0] = 'belocal.com';
$props['base_domains'][1] = 'www.belocal.com';

In fb.module, line 260 (6.x-3.1)

jim_at_miramontes’s picture

Huh. I've tried this, and am also seeing a dramatic increase in page load times. Some of this is because fb_init gets called a lot (perhaps too often in my site -- long story), but that call to getAppProperties is definitely expensive.

However, I'm also finding that hardcoding the domains is, somehow, messing up my logout process. I haven't completely figured this out yet, but will report back if/when I do. In the meantime, I suppose that none of you other hardcoders have seen any logout problems? I WAS having a definite problem with this (really!), but it seems to have "gone away". The Facebook API seemed to be a little flaky this morning when I was working on this, but I'm honestly now sure what is or was up. I'll keep an eye on this, but for now I'm going to pretend it never happened....

Meanwhile, as for the hard-coding: It would be easy enough to add some settings code that would let one specify their site domains without hacking the module, but the real question (for Dave or someone else who really understands the internals) is whether the site_domains need to be gotten dynamically through this call, or whether specifying them one way or another is good enough. I'm going to use the hard-codings and see if anything bad happens, but information based on knowledge of the code rather than dumb luck would certainly be a better alternative.

ALSO meanwhile, I guess my original question still stands -- what's a good way to handle those cases where the Facebook API goes into the weeds and throws some sort of exception? We might make the site_domains call go away with the hard-coding approach, but the general problem is still out there. Thoughts are welcome.

Dave Cohen’s picture

Status: Active » Fixed

Is this still an issue?

All that code should be wrapped in try{...} catch {...} now.

Automatically closed -- issue fixed for 2 weeks with no activity.