Failures related to the WordPress APC Object Cache plugin

On a site for a newer X-Team client, APC was previously chosen as the object cache plugin. This has caused some headaches due to APC not being available while in CLI mode, rendering WP-CLI mostly broken: any commands which change parts of the database which get object-cached won’t appear until the cache gets invalidated, which may not happen anytime soon. For example, plugin (de)activation is broken in WP-CLI with APC Object Cache, as the manifest of activated plugins is cached.

Today I encountered a more serious problem with APC Object Cache.

I was making some widget changes, and I saw that my changes weren’t being reflected on the frontend. Upon reloading the widgets admin page, I also noticed that my changes didn’t seem to get saved. But if I ran wp option get widget_text, I could see my changes had been written to the database (as, of course, WP-CLI here was bypassing the APC object cache). So for some reason, APC was refusing to invalidate widget caches. Doing some more digging, I was shocked to see that the the Text widgets used in the sidebar, had multi-widget instance numbers surpassing 560,000,000. That’s right, 560 million.  The output of wp option get widget_text included:

array (
  /*...*/
  526001242 =>
  array (
    'title' => 'Lorem Ipsum',
    'text' => 'Hello World',
    'filter' => false,
  ),
  '_multiwidget' => 1,
)

Some plugin must have at some time bumped that widget instance number up, because there’s no way there have been millions of Text widgets used on the site. Only a couple dozen Text widget instances are currently present.

In any case, this incredibly-sparse PHP array seemed like a good candidate for what was causing APC cache to fail. I swapped out APC for Memcached Object Cache, and the problem went away. While the Memcached plugin stores arrays as serialized strings, just as they get stored in the options table, the APC plugin is apc_store’ing the array wrapped in an ArrayObject instance:

if ( is_array( $data ) )
    $store_data = new ArrayObject( $data );

While I couldn’t reproduce this problem on VVV or on the site’s staging environment, for some reason on production this array object failed to get stored by APC.

I’ve never had any issues with Memcached Object Cache, so I’m glad I made the switch. Not only did it fix this strange widgets issue, but it’s great to be able to once again rely on WP-CLI!

Leave a Reply