mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-08 22:01:03 +01:00
Provide read and overwrite for Lisk counters
Summary: Ref T6881. This is part 1 of my 35-step plan to support subscriptions that bill monthly. Expanding the capabilities of counters will let me use them to create a logical clock on time-based event updates, build a daemon on top of that, and eventually get time-based triggers. Test Plan: Added and executed unit tests. Reviewers: btrahan Reviewed By: btrahan Subscribers: chad, epriestley Maniphest Tasks: T6881 Differential Revision: https://secure.phabricator.com/D11395
This commit is contained in:
parent
2297a43d44
commit
7ab5d108a4
3 changed files with 72 additions and 14 deletions
|
@ -2231,7 +2231,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php',
|
||||
'PhabricatorProjectViewController' => 'applications/project/controller/PhabricatorProjectViewController.php',
|
||||
'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php',
|
||||
'PhabricatorProjectWikiExplainController' => 'applications/project/controller/PhabricatorProjectWikiExplainController.php',
|
||||
'PhabricatorProjectsPolicyRule' => 'applications/policy/rule/PhabricatorProjectsPolicyRule.php',
|
||||
'PhabricatorPygmentSetupCheck' => 'applications/config/check/PhabricatorPygmentSetupCheck.php',
|
||||
'PhabricatorQuery' => 'infrastructure/query/PhabricatorQuery.php',
|
||||
|
@ -5459,7 +5458,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectViewController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectWatchController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectWikiExplainController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule',
|
||||
'PhabricatorPygmentSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
|
|
|
@ -1173,7 +1173,7 @@ abstract class LiskDAO {
|
|||
$id_key = $this->getIDKeyForUse();
|
||||
if (empty($data[$id_key])) {
|
||||
$counter_name = $this->getTableName();
|
||||
$id = self::loadNextCounterID($conn, $counter_name);
|
||||
$id = self::loadNextCounterValue($conn, $counter_name);
|
||||
$this->setID($id);
|
||||
$data[$id_key] = $id;
|
||||
}
|
||||
|
@ -1688,6 +1688,7 @@ abstract class LiskDAO {
|
|||
$this->$name = $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increments a named counter and returns the next value.
|
||||
*
|
||||
|
@ -1697,7 +1698,7 @@ abstract class LiskDAO {
|
|||
*
|
||||
* @task util
|
||||
*/
|
||||
public static function loadNextCounterID(
|
||||
public static function loadNextCounterValue(
|
||||
AphrontDatabaseConnection $conn_w,
|
||||
$counter_name) {
|
||||
|
||||
|
@ -1721,6 +1722,58 @@ abstract class LiskDAO {
|
|||
return $conn_w->getInsertID();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current value of a named counter.
|
||||
*
|
||||
* @param AphrontDatabaseConnection Database where the counter resides.
|
||||
* @param string Counter name to read.
|
||||
* @return int|null Current value, or `null` if the counter does not exist.
|
||||
*
|
||||
* @task util
|
||||
*/
|
||||
public static function loadCurrentCounterValue(
|
||||
AphrontDatabaseConnection $conn_r,
|
||||
$counter_name) {
|
||||
|
||||
$row = queryfx_one(
|
||||
$conn_r,
|
||||
'SELECT counterValue FROM %T WHERE counterName = %s',
|
||||
self::COUNTER_TABLE_NAME,
|
||||
$counter_name);
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int)$row['counterValue'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overwrite a named counter, forcing it to a specific value.
|
||||
*
|
||||
* If the counter does not exist, it is created.
|
||||
*
|
||||
* @param AphrontDatabaseConnection Database where the counter resides.
|
||||
* @param string Counter name to create or overwrite.
|
||||
* @return void
|
||||
*
|
||||
* @task util
|
||||
*/
|
||||
public static function overwriteCounterValue(
|
||||
AphrontDatabaseConnection $conn_w,
|
||||
$counter_name,
|
||||
$counter_value) {
|
||||
|
||||
queryfx(
|
||||
$conn_w,
|
||||
'INSERT INTO %T (counterName, counterValue) VALUES (%s, %d)
|
||||
ON DUPLICATE KEY UPDATE counterValue = VALUES(counterValue)',
|
||||
self::COUNTER_TABLE_NAME,
|
||||
$counter_name,
|
||||
$counter_value);
|
||||
}
|
||||
|
||||
private function getBinaryColumns() {
|
||||
return $this->getConfigOption(self::CONFIG_BINARY);
|
||||
}
|
||||
|
|
|
@ -99,14 +99,21 @@ final class LiskFixtureTestCase extends PhabricatorTestCase {
|
|||
$conn_w = $obj->establishConnection('w');
|
||||
|
||||
// Test that the counter bascially behaves as expected.
|
||||
$this->assertEqual(1, LiskDAO::loadNextCounterID($conn_w, 'a'));
|
||||
$this->assertEqual(2, LiskDAO::loadNextCounterID($conn_w, 'a'));
|
||||
$this->assertEqual(3, LiskDAO::loadNextCounterID($conn_w, 'a'));
|
||||
$this->assertEqual(1, LiskDAO::loadNextCounterValue($conn_w, 'a'));
|
||||
$this->assertEqual(2, LiskDAO::loadNextCounterValue($conn_w, 'a'));
|
||||
$this->assertEqual(3, LiskDAO::loadNextCounterValue($conn_w, 'a'));
|
||||
|
||||
// This first insert is primarily a test that the previous LAST_INSERT_ID()
|
||||
// value does not bleed into the creation of a new counter.
|
||||
$this->assertEqual(1, LiskDAO::loadNextCounterID($conn_w, 'b'));
|
||||
$this->assertEqual(2, LiskDAO::loadNextCounterID($conn_w, 'b'));
|
||||
$this->assertEqual(1, LiskDAO::loadNextCounterValue($conn_w, 'b'));
|
||||
$this->assertEqual(2, LiskDAO::loadNextCounterValue($conn_w, 'b'));
|
||||
|
||||
// Test alternate access/overwrite methods.
|
||||
$this->assertEqual(3, LiskDAO::loadCurrentCounterValue($conn_w, 'a'));
|
||||
|
||||
LiskDAO::overwriteCounterValue($conn_w, 'a', 42);
|
||||
$this->assertEqual(42, LiskDAO::loadCurrentCounterValue($conn_w, 'a'));
|
||||
$this->assertEqual(43, LiskDAO::loadNextCounterValue($conn_w, 'a'));
|
||||
|
||||
// These inserts alternate database connections. Since unit tests are
|
||||
// transactional by default, we need to break out of them or we'll deadlock
|
||||
|
@ -117,11 +124,11 @@ final class LiskFixtureTestCase extends PhabricatorTestCase {
|
|||
$conn_1 = $obj->establishConnection('w', $force_new = true);
|
||||
$conn_2 = $obj->establishConnection('w', $force_new = true);
|
||||
|
||||
$this->assertEqual(1, LiskDAO::loadNextCounterID($conn_1, 'z'));
|
||||
$this->assertEqual(2, LiskDAO::loadNextCounterID($conn_2, 'z'));
|
||||
$this->assertEqual(3, LiskDAO::loadNextCounterID($conn_1, 'z'));
|
||||
$this->assertEqual(4, LiskDAO::loadNextCounterID($conn_2, 'z'));
|
||||
$this->assertEqual(5, LiskDAO::loadNextCounterID($conn_1, 'z'));
|
||||
$this->assertEqual(1, LiskDAO::loadNextCounterValue($conn_1, 'z'));
|
||||
$this->assertEqual(2, LiskDAO::loadNextCounterValue($conn_2, 'z'));
|
||||
$this->assertEqual(3, LiskDAO::loadNextCounterValue($conn_1, 'z'));
|
||||
$this->assertEqual(4, LiskDAO::loadNextCounterValue($conn_2, 'z'));
|
||||
$this->assertEqual(5, LiskDAO::loadNextCounterValue($conn_1, 'z'));
|
||||
|
||||
LiskDAO::beginIsolateAllLiskEffectsToTransactions();
|
||||
} catch (Exception $ex) {
|
||||
|
|
Loading…
Reference in a new issue