/**
* @return bool|mixed
*/
public function acquire()
{
if ($this->sessionId) {
throw new \Exception('Resources are acquired.');
}
$result = true;
// Start a session
$session = $this->session->create('{"Name": "semaphor", "LockDelay":0, "TTL": "' . $this->ttl . 's"}')->json();
$this->sessionId = $session['ID'];
$lockedResources = [];
foreach ($this->resources as $resource) {
if (false === $this->kv->put($this->getResourceKey($resource, $this->sessionId), '', ['acquire' => $this->sessionId])->json()) {
$result = false;
} else {
$lockedResources[] = $resource;
$semaphoreMetaDataValue = ['limit' => $resource->limit, 'sessions' => []];
// get actuall metadata
$semaphorDataItems = $this->kv->get($this->getResourceKeyPrefix($resource), ['recurse' => true])->json();
foreach ($semaphorDataItems as $key => $item) {
if ($item['Key'] == $this->getResourceKey($resource, $this->metaDataKey)) {
$semaphoreMetaDataActual = $item;
$semaphoreMetaDataActual['Value'] = json_decode(base64_decode($semaphoreMetaDataActual['Value']), true);
unset($semaphorDataItems[$key]);
break;
}
}
// build new metadata
if (isset($semaphoreMetaDataActual)) {
foreach ($semaphorDataItems as $item) {
if (isset($item['Session'])) {
if (isset($semaphoreMetaDataActual['Value']['sessions'][$item['Session']])) {
$semaphoreMetaDataValue['sessions'][$item['Session']] = $semaphoreMetaDataActual['Value']['sessions'][$item['Session']];
}
} else {
$this->kv->delete($item['Key']);
}
}
}
$resource->acquired = min($resource->acquire, $semaphoreMetaDataValue['limit'] - array_sum($semaphoreMetaDataValue['sessions']));
// add new elemet to metadata and save it
if ($resource->acquired) {
$semaphoreMetaDataValue['sessions'][$this->sessionId] = $resource->acquired;
$result = $this->kv->put($this->getResourceKey($resource, $this->metaDataKey), json_encode($semaphoreMetaDataValue), ['cas' => isset($semaphoreMetaDataActual) ? $semaphoreMetaDataActual['ModifyIndex'] : 0])->json();
} else {
$result = false;
}
}
if (!$result) {
break;
}
}
if (!$result) {
$this->release();
}
return $result;
}