You are here

public static function BrightcoveUtil::runWithSemaphore in Brightcove Video Connect 3.x

Same name and namespace in other branches
  1. 8.2 src/BrightcoveUtil.php \Drupal\brightcove\BrightcoveUtil::runWithSemaphore()
  2. 8 src/BrightcoveUtil.php \Drupal\brightcove\BrightcoveUtil::runWithSemaphore()

Run a piece of code with semaphore check.

Parameters

callable $function: Function that needs to be run in sync.

\Drupal\Core\Lock\LockBackendInterface|null $lock: Lock backend.

Return value

bool|mixed FALSE if the execution was failed, otherwise it will return what the callable function returned.

2 calls to BrightcoveUtil::runWithSemaphore()
BrightcoveSubscriptionController::notificationCallback in src/Controller/BrightcoveSubscriptionController.php
Menu callback to handle the Brightcove notification callback.
BrightcoveVideoController::ingestionCallback in src/Controller/BrightcoveVideoController.php
Ingestion callback for Brightcove.

File

src/BrightcoveUtil.php, line 493

Class

BrightcoveUtil
Utility class for Brightcove.

Namespace

Drupal\brightcove

Code

public static function runWithSemaphore(callable $function, LockBackendInterface $lock = NULL) {
  $lock_name = 'brightcove_semaphore';
  try {

    // Make sure that the lock service is available.
    if ($lock === NULL) {
      $lock = \Drupal::lock();
    }

    // Basic semaphore to prevent race conditions, this is needed because
    // Brightcove may call callbacks again before the previous one would
    // finish.
    //
    // To make sure that the waiting doesn't run indefinitely limit the
    // maximum iterations to 600 cycles, which in worst case scenario would
    // mean 5 minutes maximum wait time.
    $limit = 600;
    for ($i = 0; $i < $limit; $i++) {

      // Try to acquire lock.
      for (; $i < $limit && !$lock
        ->lockMayBeAvailable($lock_name); $i++) {

        // Wait random time between 100 and 500 milliseconds on each try.
        // The lock backend's wait() method is not used here as it can wait
        // only seconds that may take too long.
        usleep(mt_rand(100000, 500000));
      }

      // Make sure that other processes have not acquired the lock while we
      // waited then try to acquire lock as soon as we can.
      if ($lock
        ->lockMayBeAvailable($lock_name) && $lock
        ->acquire($lock_name)) {
        break;
      }
    }

    // If we couldn't acquire the lock in the given time, release the lock
    // (finally block will take care of it) and return with FALSE.
    if (600 <= $i) {
      return FALSE;
    }

    // Run function.
    return $function();
  } catch (\Exception $e) {

    // Log error, and return with FALSE.
    watchdog_exception('brightcove', $e, $e
      ->getMessage());
    return FALSE;
  } finally {

    // Release semaphore.
    // This will always run regardless what happened.
    $lock
      ->release($lock_name);
  }
}