/** * @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; }
/** * @return bool */ public function lock() { $result = true; // Start a session $session = $this->session->create('{"LockDelay":0, "TTL": "' . $this->ttl . 's"}')->json(); $this->sessionId = $session['ID']; $lockedResources = []; foreach ($this->resources as $resource) { // Lock a key / value with the current session $lockAcquired = $this->kv->put($this->lockPath . $resource, '', ['acquire' => $this->sessionId])->json(); if (false === $lockAcquired) { $result = false; break; } else { $lockedResources[] = $resource; } } if (!$result) { $this->releaseResources($lockedResources); } return $result; }