addDefaults(array( 'max_lock_wait_time' => 10, 'min_lock_retry_microtime' => 10000, 'max_lock_retry_microtime' => 50000, )); parent::__construct($client, $config); } /** * {@inheritdoc} * Retries the request until the lock can be acquired */ public function doRead($id) { $item = array(); $rightNow = time(); $timeout = $rightNow + $this->config->get('max_lock_wait_time'); // Create an UpdateItem command so that a lock can be set and the item // returned (via ReturnValues) in a single, atomic operation $updateItem = $this->client->getCommand('UpdateItem', array( 'TableName' => $this->config->get('table_name'), 'Key' => $this->formatKey($id), 'Expected' => array( 'lock' => array( 'Exists' => false ) ), 'AttributeUpdates' => array( 'lock' => array( 'Value' => array( 'N' => '1' ) ) ), 'ReturnValues' => 'ALL_NEW', Ua::OPTION => Ua::SESSION )); // Acquire the lock and fetch the item data do { try { $result = $updateItem->execute(); } catch (ConditionalCheckFailedException $e) { // If lock fails, sleep and try again later usleep(rand( $this->config->get('min_lock_retry_microtime'), $this->config->get('max_lock_retry_microtime') )); $result = array(); $rightNow = time(); } catch (DynamoDbException $e) { return $item; } } while (!$result && $rightNow < $timeout); // Get the item attributes if (isset($result['Attributes'])) { foreach ($result['Attributes'] as $key => $value) { $item[$key] = current($value); } } return $item; } /** * {@inheritdoc} */ protected function getExtraAttributes() { // @codeCoverageIgnoreStart return array('lock' => array('Action' => 'DELETE')); // @codeCoverageIgnoreEnd } }