I have some entities with large amounts longtext data attached. The view is using fields and VBO. For some reason VBO each one of my nodes data in the cache_from table. For every entity shown, all of that entities data per pageload is saved to the DB. For me this has ended up being 18mb of data.

Is this normal behaviour or has something gone wrong with my view?

Comments

BTMash’s picture

Version: 7.x-3.1 » 7.x-3.x-dev

My solution to this is completely screwed up (it is doing stuff that you really *shouldn't* be doing but did work around completely blowing up the cache_form table without messing up every other form on the site(s).

/**
 * Implements hook_views_pre_build().
 */
function my_custom_module_views_pre_build(&$view) {
  $fields = (isset($view->field)) ? array_keys($view->field) : array();
  if (in_array('views_bulk_operations', $fields) && !user_is_anonymous()) {
    global $conf;
    // Add the fake cache class for usage.
    require_once DRUPAL_ROOT . '/includes/cache-install.inc';
    // Disable forms from being cached.
    $conf['cache_class_cache_form'] = 'DrupalFakeCache';
  }
}
Sam152’s picture

I think what I ended up doing was storing the blob in a different entity and referencing it. It ended up having some other positive side effects so I wasn't too upset with that.

charlie-s’s picture

@btmash do you need to unset the fake cache afterwards, since you're setting a global conf value? Also, in using the DrupalFakeCache class, does the VBO still actually work? I would think the $form_state / validate / submit functions wouldn't work.

BTMash’s picture

@csdco ... well, I found out this morning what you said is exactly what happened. Argh :( Back to the drawing board. @PerthSam152, would you be able to share what you had (understandable if not but can't hurt to ask)?

charlie-s’s picture

@btmash you can build custom bulk operations forms pretty easily, which may let you build the forms without pre-loading the entities and thus could save you a lot of room in the db side and in general performance. Just a thought.

BTMash’s picture

@csdco, I know that is always possible (and have done so in the past w/ d6 before I found out about vbo) and ultimately may not have a choice (I'm partially sidestepping the problem right now by clearing out cache_form of any entries that are older than 1 hour as I (and the client) don't expect a person to be on a particular form for longer than that period). But I do enjoy the flexibility vbo offers in putting the data I want together hence hoping for a solution from within vbo as opposed to reinventing so to speak (or the tl;dr version: I'm being lazy :().

charlie-s’s picture

No that's not lazy, I completely understand not wanting to open up a pandora's box of "unknown quantity of work". The cache clear is a good idea. You may also be able to target your specific form via an ID and clear it even more frequently. Good luck!

bojanz’s picture

Unfortunately this is expected behavior since it's working around a Views bug (Views Forms need to be cached so that the results don't change when you go to the next screen, such as the confirmation). I don't think it's fixable in D7 without a big Views Form refactoring.

Sam152’s picture

If this is a bug that wont be fixed, my solution in #2 is probably going to work for a portion of the people having this issue.

Anonymous’s picture

I've just experienced this on a site I've recently put live - downloaded a copy of the database and noticed it was 1.2GB, with 626Mb being the cache_form table.

Not sure if I've done this right but I just changed my_custom_module to a proper module name, added a .info file and enabled it. Everything seems to be working OK so I'll keep an eye on the table size.

Can I safely truncate the current 626Mb cache_form table or is it now just stuck there?

Thanks!

Sam152’s picture

Yeah, you can safely remove all content from any of the cache_* tables.

Kristen Pol’s picture

Issue summary: View changes

Steve/Sam - Actually, you should only remove data from cache_form that is expired, e.g.

DELETE FROM cache_form where 'expire' < UNIX_TIMESTAMP();

If you delete all data from cache_form, users who are currently interacting with forms on the site will have errors and have to reload their forms. So, cache_form isn't used like a proper cache table where you can delete it all without issues (beyond slower load times).

skh’s picture

I was experiencing this as well. The VBO in question was the result of a rather intricate view and the entries in the cache table were enormous. Below is what I came up with.

If all you're looking for is the cache not to be created on the first load, setting $form_state['cache'] = FALSE only should be sufficient. The rest of the code is really to deal with the case when the user progresses past the first step but doesn't finish the form.

This is kind of a strange thing to do, but it's working in my case. VBO seems a bit different in that you likely won't (can't?) return to a previous form state, making the usage of the cache only relevant while progressing through steps. When a user views a VBO form, the code below will clear any past cache entries per-user-per-form.

One note is that if they bail and don't finish the form after the first step, it won't get cleared until the next form view. You could run this code elsewhere but for me this was enough.

Note this won't clear entries that were already in the DB before, and assumes that it's not an anonymous user using VBO.


/**
 * Implements hook_views_bulk_operations_form_alter().
 */
function MODULE_views_bulk_operations_form_alter(&$form, &$form_state, $vbo) {

  // Current user uid.
  $uid = $GLOBALS['user']->uid;

  // Current form id.
  $form_id = $form['#form_id'];

  // Get any previously cached VBO forms.
  $user_vbo_cache = variable_get('user_vbo_cache', array());

  // Prevent caching on the initial form.
  $form_state['cache'] = FALSE;

  // No input, will be a new form submission.
  if (empty($form_state['input'])) {

    // User has previous cached forms.
    if (!empty($user_vbo_cache[$uid][$form_id])) {

      // Remove them from the db.
      cache_clear_all(array_keys($user_vbo_cache[$uid][$form_id]), 'cache_form');

      // This user's VBO cache for this form is empty now.
      unset($user_vbo_cache[$uid][$form_id]);

      // Are all forms empty for this user's VBO cache now.
      if (empty($user_vbo_cache[$uid])) {

        // Remove from saved.
        unset($user_vbo_cache[$uid]);
      }
    }
  }

  // Not first step.
  else {

    // Current build id.
    $form_build_id = $form['#build_id'];

    // Add form cid.
    $user_vbo_cache[$uid][$form_id]['form_' . $form_build_id] = 1;

    // Add form state cid.
    $user_vbo_cache[$uid][$form_id]['form_state_' . $form_build_id] = 1;
  }

  // There's still cached VBO forms.
  if (!empty($user_vbo_cache)) {

    // Save the variable.
    variable_set('user_vbo_cache', $user_vbo_cache);
  }

  // There's no cached VBO forms.
  else {

    // Remove the setting.
    variable_del('user_vbo_cache');
  }
}

iamEAP’s picture

I was able to mitigate the effects of this issue by setting a reasonable limit on the number of rows rendered at any given time and using a pager. This at least reduces the size of the cached object on initial form render.