You are here

class BulkDocs in Replication 8

Same name and namespace in other branches
  1. 8.2 src/BulkDocs/BulkDocs.php \Drupal\replication\BulkDocs\BulkDocs

Hierarchy

Expanded class hierarchy of BulkDocs

1 file declares its use of BulkDocs
BulkDocsFactory.php in src/BulkDocsFactory.php

File

src/BulkDocs/BulkDocs.php, line 17

Namespace

Drupal\replication\BulkDocs
View source
class BulkDocs implements BulkDocsInterface {
  use DependencySerializationTrait;

  /**
   * @var \Drupal\multiversion\Workspace\WorkspaceManagerInterface
   */
  protected $workspaceManager;

  /**
   * @var \Drupal\multiversion\Entity\WorkspaceInterface
   */
  protected $workspace;

  /**
   * @var \Drupal\multiversion\Entity\Index\UuidIndexInterface
   */
  protected $uuidIndex;

  /**
   * @var \Drupal\multiversion\Entity\Index\RevisionIndexInterface
   */
  protected $revIndex;

  /**
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * @var \Drupal\Core\Lock\LockBackendInterface
   */
  protected $lock;

  /**
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected $logger;

  /**
   * @var \Drupal\Core\Entity\ContentEntityInterface[]
   */
  protected $entities = [];

  /**
   * @var bool
   */
  protected $newEdits = TRUE;

  /**
   * @var array
   */
  protected $result = [];

  /**
   * The state service.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

  /**
   * The replication settings config.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $config;

  /**
   * Constructor.
   *
   * @param \Drupal\multiversion\Workspace\WorkspaceManagerInterface $workspace_manager
   * @param \Drupal\multiversion\Entity\WorkspaceInterface $workspace
   * @param \Drupal\multiversion\Entity\Index\UuidIndexInterface $uuid_index
   * @param \Drupal\multiversion\Entity\Index\RevisionIndexInterface $rev_index
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   * @param \Drupal\Core\Lock\LockBackendInterface $lock
   * @param \Drupal\Core\Logger\LoggerChannelInterface $logger
   * @param \Drupal\Core\State\StateInterface $state
   * @param \Drupal\Core\Config\ImmutableConfig $config
   */
  public function __construct(WorkspaceManagerInterface $workspace_manager, WorkspaceInterface $workspace, UuidIndexInterface $uuid_index, RevisionIndexInterface $rev_index, EntityTypeManagerInterface $entity_type_manager, LockBackendInterface $lock, LoggerChannelInterface $logger, StateInterface $state, ImmutableConfig $config) {
    $this->workspaceManager = $workspace_manager;
    $this->workspace = $workspace;
    $this->uuidIndex = $uuid_index;
    $this->revIndex = $rev_index;
    $this->entityTypeManager = $entity_type_manager;
    $this->lock = $lock;
    $this->logger = $logger;
    $this->state = $state;
    $this->config = $config;
  }

  /**
   * {@inheritdoc}
   */
  public function newEdits($new_edits) {
    $this->newEdits = (bool) $new_edits;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setEntities($entities) {
    $this->entities = $entities;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getEntities() {
    return $this->entities;
  }

  /**
   * {@inheritdoc}
   */
  public function save() {

    // Writing a bulk of documents can potentially take a lot of time, so we
    // aquire a lock to ensure the integrity of the operation.
    do {

      // Check if the operation may be available.
      if ($this->lock
        ->lockMayBeAvailable('bulk_docs')) {

        // The operation may be available, so break the wait and continue if we
        // successfully can acquire a lock.
        if ($this->lock
          ->acquire('bulk_docs')) {
          break;
        }
      }
      $this->logger
        ->critical('Lock exists on bulk operation. Waiting.');
    } while ($this->lock
      ->wait('bulk_docs', 3000));
    $inital_workspace = $this->workspaceManager
      ->getActiveWorkspace();
    $this->workspaceManager
      ->setActiveWorkspace($this->workspace);

    // Temporarily disable the maintenance of the {comment_entity_statistics} table.
    $this->state
      ->set('comment.maintain_entity_statistics', FALSE);
    foreach ($this->entities as $entity) {
      $uuid = $entity
        ->uuid();
      $rev = $entity->_rev->value;
      try {

        // Check if the revision being posted already exists.
        $record = $this->revIndex
          ->useWorkspace($this->workspace
          ->id())
          ->get("{$uuid}:{$rev}");
        if ($record) {
          if (!$this->newEdits && !$record['is_stub']) {
            $this->result[] = [
              'error' => 'Conflict',
              'reason' => 'Document update conflict.',
              'id' => $uuid,
              'rev' => $rev,
            ];
            continue;
          }
        }

        // In cases where a stub was created earlier in the same bulk operation
        // it may already exists. This means we need to ensure the local ID
        // mapping is correct.
        $entity_type = $this->entityTypeManager
          ->getDefinition($entity
          ->getEntityTypeId());
        $id_key = $entity_type
          ->getKey('id');
        if ($record = $this->uuidIndex
          ->useWorkspace($this->workspace
          ->id())
          ->get($entity
          ->uuid())) {
          $entity->{$id_key}->value = $record['entity_id'];
          $entity
            ->enforceIsNew(FALSE);
        }
        else {
          $entity
            ->enforceIsNew(TRUE);
          $entity->{$id_key}->value = NULL;
        }
        $entity->workspace->target_id = $this->workspace
          ->id();
        $entity->_rev->new_edit = $this->newEdits;
        $this->entityTypeManager
          ->getStorage($entity
          ->getEntityTypeId())
          ->useWorkspace($this->workspace
          ->id());
        if ($entity
          ->save()) {
          $this->result[] = [
            'id' => $uuid,
            'ok' => TRUE,
            'rev' => $entity->_rev->value,
          ];
          if ($this->config
            ->get('verbose_logging')) {
            $this->logger
              ->info($entity_type
              ->getLabel() . ' ' . $entity
              ->label() . ' saved in workspace ' . $this->workspace
              ->label());
          }
        }
      } catch (\Throwable $e) {
        $message = $e
          ->getMessage();
        $this->result[] = [
          'error' => $message,
          'reason' => 'Exception',
          'id' => $uuid,
          'rev' => $entity->_rev->value,
        ];
        $arguments = Error::decodeException($e) + [
          '%uuid' => $uuid,
        ];
        $this->logger
          ->error('%type: @message in %function (line %line of %file). The error occurred while saving the entity with the UUID: %uuid.', $arguments);
      }
    }

    // Enable the the maintenance of entity statistics for comments.
    $this->state
      ->set('comment.maintain_entity_statistics', TRUE);

    // Switch back to the initial workspace.
    $this->workspaceManager
      ->setActiveWorkspace($inital_workspace);
    $this->lock
      ->release('bulk_docs');
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getResult() {
    return $this->result;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
BulkDocs::$config protected property The replication settings config.
BulkDocs::$entities protected property
BulkDocs::$entityTypeManager protected property
BulkDocs::$lock protected property
BulkDocs::$logger protected property
BulkDocs::$newEdits protected property
BulkDocs::$result protected property
BulkDocs::$revIndex protected property
BulkDocs::$state protected property The state service.
BulkDocs::$uuidIndex protected property
BulkDocs::$workspace protected property
BulkDocs::$workspaceManager protected property
BulkDocs::getEntities public function Overrides BulkDocsInterface::getEntities
BulkDocs::getResult public function Overrides BulkDocsInterface::getResult
BulkDocs::newEdits public function Overrides BulkDocsInterface::newEdits
BulkDocs::save public function Overrides BulkDocsInterface::save
BulkDocs::setEntities public function Overrides BulkDocsInterface::setEntities
BulkDocs::__construct public function Constructor.
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2