Commit 37d64e23 authored by catch's avatar catch
Browse files

Issue #3327118 by Defcon0, acbramley, iSampo, poker10, Nitin shrivastava,...

Issue #3327118 by Defcon0, acbramley, iSampo, poker10, Nitin shrivastava, catch, fgm, longwave: Chunk multiple cache sets into groups of 100 to avoid OOM/max_allowed_packet issues

(cherry picked from commit a04bdb08)
parent ce444178
Loading
Loading
Loading
Loading
Loading
+61 −50
Original line number Diff line number Diff line
@@ -32,6 +32,11 @@ class DatabaseBackend implements CacheBackendInterface {
   */
  const MAXIMUM_NONE = -1;

  /**
   * The chunk size for inserting cache entities.
   */
  const MAX_ITEMS_PER_CACHE_SET = 100;

  /**
   * The maximum number of rows that this cache bin table is allowed to store.
   *
@@ -215,9 +220,14 @@ public function setMultiple(array $items) {
   * @see \Drupal\Core\Cache\CacheBackendInterface::setMultiple()
   */
  protected function doSetMultiple(array $items) {
    // Chunk the items as the database might not be able to receive thousands
    // of items in a single query.
    $chunks = array_chunk($items, self::MAX_ITEMS_PER_CACHE_SET, TRUE);

    foreach ($chunks as $chunk_items) {
      $values = [];

    foreach ($items as $cid => $item) {
      foreach ($chunk_items as $cid => $item) {
        $item += [
          'expire' => CacheBackendInterface::CACHE_PERMANENT,
          'tags' => [],
@@ -253,7 +263,7 @@ protected function doSetMultiple(array $items) {
      }

      // If all $items were useless writes, we may end up with zero writes.
    if (empty($values)) {
      if (count($values) === 0) {
        return;
      }

@@ -272,6 +282,7 @@ protected function doSetMultiple(array $items) {

      $query->execute();
    }
  }

  /**
   * {@inheritdoc}
+9 −0
Original line number Diff line number Diff line
@@ -53,6 +53,15 @@ public function testSetGet() {
    $cached_value_short = $this->randomMachineName();
    $backend->set($cid_short, $cached_value_short);
    $this->assertSame($cached_value_short, $backend->get($cid_short)->data, "Backend contains the correct value for short, non-ASCII cache id.");

    // Set multiple items to test exceeding the chunk size.
    $backend->deleteAll();
    $items = [];
    for ($i = 0; $i <= DatabaseBackend::MAX_ITEMS_PER_CACHE_SET; $i++) {
      $items["test$i"]['data'] = $i;
    }
    $backend->setMultiple($items);
    $this->assertSame(DatabaseBackend::MAX_ITEMS_PER_CACHE_SET + 1, $this->getNumRows());
  }

  /**