Skip to content
This repository has been archived by the owner on Jan 24, 2023. It is now read-only.

Commit

Permalink
Updating the pgdata system to include the following: (#79)
Browse files Browse the repository at this point in the history
Lock and memcache retry to max 100 and 1 second, whichever comes first
Adding an error log when lock takes more than 1 try
Adding an exception when trying to lock on an empty row
Adding function docs
  • Loading branch information
Mehul24 authored Jan 30, 2020
1 parent 6ce07a0 commit 29d4d05
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
15 changes: 15 additions & 0 deletions src/Zynga/Framework/Cache/V2/Driver/Memcache.hh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class Memcache extends DriverBase implements MemcacheDriverInterface {
// Operations like set and delete will retry their operation
const int OPERATION_ATTEMPTS_MAX = 100; // 100 * 10000 = 1s max wait time.
const int OPERATION_TIMEOUT_AMOUNT_MICRO_SECONDS = 10000;

// Max lock timeout is 1 seconds
const int MAX_TIMEOUT_AMOUNT_SECONDS = 1;

public function __construct(DriverConfigInterface $config) {
$this->_config = $config;
Expand Down Expand Up @@ -98,12 +101,18 @@ class Memcache extends DriverBase implements MemcacheDriverInterface {

$this->connect();

$startTime = microtime(true);
for ($retryCount = 0; $retryCount < self::OPERATION_ATTEMPTS_MAX; $retryCount++) {
$success = $this->_memcache->set($key, $value, $flags, $ttl);
if ($success == true) {
return true;
}

// We crossed max timeout, break early.
if( (microtime(true) - $startTime) > self::MAX_TIMEOUT_AMOUNT_SECONDS) {
return false;
}

usleep(self::OPERATION_TIMEOUT_AMOUNT_MICRO_SECONDS);
}

Expand Down Expand Up @@ -133,12 +142,18 @@ class Memcache extends DriverBase implements MemcacheDriverInterface {

$this->connect();

$startTime = microtime(true);
for ($retryCount = 0; $retryCount < self::OPERATION_ATTEMPTS_MAX; $retryCount++) {
$success = $this->_memcache->delete($key);
if ($success == true) {
return true;
}

// We crossed max timeout, break early.
if( (microtime(true) - $startTime) > self::MAX_TIMEOUT_AMOUNT_SECONDS) {
return false;
}

usleep(self::OPERATION_TIMEOUT_AMOUNT_MICRO_SECONDS);
}

Expand Down
14 changes: 12 additions & 2 deletions src/Zynga/Framework/Lockable/Cache/V1/Driver/Caching.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ class Caching extends FactoryDriverBase implements DriverInterface {
private DriverConfigInterface $_config;
private Map<string, LockPayloadInterface> $_locks;

// Lock operation would try a max of 200 times and sleep for 10000 in between
const int LOCK_ATTEMPTS_MAX = 200; // 200 * 10000 = 2s max wait time.
// Lock operation would try a max of 100 times and sleep for 10000 in between
const int LOCK_ATTEMPTS_MAX = 100;
const int LOCK_TIMEOUT_AMOUNT_MICRO_SECONDS = 10000;
// Max lock timeout is 1 seconds
const int MAX_TIMEOUT_AMOUNT_SECONDS = 1;

public function __construct(DriverConfigInterface $config) {
$this->_config = $config;
Expand Down Expand Up @@ -130,6 +132,14 @@ class Caching extends FactoryDriverBase implements DriverInterface {
}

$lockRetryCount++;

// We crossed max timeout, break early.
if( (microtime(true) - $startTime) > self::MAX_TIMEOUT_AMOUNT_SECONDS) {
return false;
}

// Don't care about the first lock try. Only log an error for subsequent ones.
error_log('JEO pgData::lock storable=' . get_class($obj) . ' key=' . $lockKey . ' lockRetryCount=' . $lockRetryCount . ' obj=' . $obj->export()->asJSON());
// if failed to get a lock, sleep and try again
usleep(self::LOCK_TIMEOUT_AMOUNT_MICRO_SECONDS);
}
Expand Down
18 changes: 17 additions & 1 deletion src/Zynga/Framework/PgData/V1/PgModel/Cache.hh
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ class Cache implements CacheInterface {
public function lockRowCache(PgRowInterface $row): bool {

try {
if($row->getPrimaryKeyTyped()->isDefaultValue()[0] === true) {
throw new Exception("Trying to lock a pg row without primary key! Row=" . $row->export()->asJSON());
}

$cache = $this->getDataCache();

return $cache->lock($row);

} catch (Exception $e) {
Expand All @@ -77,6 +81,10 @@ class Cache implements CacheInterface {

}

/**
* API to force clear the result set cache so it can refetched.
* Used by external systems to manage result set caches
*/
public function clearResultSetCache<TModelClass as PgRowInterface>(
classname<TModelClass> $model,
PgWhereClauseInterface $where,
Expand Down Expand Up @@ -137,6 +145,10 @@ class Cache implements CacheInterface {
return false;
}

/**
* Used internally by the system to lock result set cache before populating data.
* Should not be used by external systems.
*/
public function lockResultSetCache<TModelClass as PgRowInterface>(
classname<TModelClass> $model,
PgWhereClauseInterface $where,
Expand All @@ -156,6 +168,10 @@ class Cache implements CacheInterface {
}
}

/**
* Used internally by the system to unlock result set cache after populating data.
* Should not be used by external systems.
*/
public function unlockResultSetCache<TModelClass as PgRowInterface>(
classname<TModelClass> $model,
PgWhereClauseInterface $where,
Expand Down

0 comments on commit 29d4d05

Please sign in to comment.