Skip to content

Commit

Permalink
Optimize key handling
Browse files Browse the repository at this point in the history
Don't fetch key `dateAdded` or `lastUsed` when not needed and remaining
cache key info in memcached. This greatly brings down DB load on
`master`.
  • Loading branch information
dstillman committed Feb 18, 2022
1 parent 8790ee5 commit 3bb16ec
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 41 deletions.
37 changes: 18 additions & 19 deletions controllers/KeysController.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,27 @@ public function keys() {

$this->allowMethods(['GET', 'POST', 'PUT', 'DELETE']);

$isSuper = $this->permissions->isSuper();

if ($key) {
$keyObj = Zotero_Keys::getByKey($key);
if (!$keyObj) {
$this->e404("Key '$key' not found");
}
$isWebsite = $this->permissions->isSuper()
$isWebsite = $isSuper
|| ($this->apiVersion >= 3 && $this->cookieAuth && $keyObj->userID == $this->userID);
}
else {
$keyObj = null;
$isWebsite = $this->permissions->isSuper()
$isWebsite = $isSuper
|| ($this->apiVersion >= 3 && $this->cookieAuth && $userID == $this->userID);
}

$options = [
'website' => $isWebsite,
'super' => $isSuper
];

if ($this->method == 'GET') {
// Single key
if ($key) {
Expand All @@ -75,14 +82,10 @@ public function keys() {
}

if ($this->apiVersion >= 3) {
$json = $keyObj->toJSON();
$json = $keyObj->toJSON($options);

// If not super-user or website user, don't include name or recent IP addresses
if (!$isWebsite) {
unset($json['dateAdded']);
unset($json['lastUsed']);
unset($json['name']);
unset($json['recentIPs']);
}

header('application/json');
Expand All @@ -93,14 +96,10 @@ public function keys() {
}
}
else {
$this->responseXML = $keyObj->toXML();
$this->responseXML = $keyObj->toXML($options);

// If not super-user, don't include name or recent IP addresses
if (!$this->permissions->isSuper()) {
unset($this->responseXML['dateAdded']);
unset($this->responseXML['lastUsed']);
if (!$isSuper) {
unset($this->responseXML->name);
unset($this->responseXML->recentIPs);
}
}
}
Expand All @@ -116,15 +115,15 @@ public function keys() {
if ($this->apiVersion >= 3) {
$json = [];
foreach ($keyObjs as $keyObj) {
$json[] = $keyObj->toJSON();
$json[] = $keyObj->toJSON($options);
}
echo Zotero_Utilities::formatJSON($json);
}
else {
$xml = new SimpleXMLElement('<keys/>');
$domXML = dom_import_simplexml($xml);
foreach ($keyObjs as $keyObj) {
$keyXML = $keyObj->toXML();
$keyXML = $keyObj->toXML($options);
$domKeyXML = dom_import_simplexml($keyXML);
$node = $domXML->ownerDocument->importNode($domKeyXML, true);
$domXML->appendChild($node);
Expand Down Expand Up @@ -225,10 +224,10 @@ public function keys() {

if ($this->apiVersion >= 3) {
header('application/json');
echo Zotero_Utilities::formatJSON($keyObj->toJSON());
echo Zotero_Utilities::formatJSON($keyObj->toJSON($options));
}
else {
$this->responseXML = $keyObj->toXML();
$this->responseXML = $keyObj->toXML($options);
}

Zotero_DB::commit();
Expand Down Expand Up @@ -307,10 +306,10 @@ public function keys() {
}

if ($this->apiVersion >= 3) {
echo Zotero_Utilities::formatJSON($keyObj->toJSON());
echo Zotero_Utilities::formatJSON($keyObj->toJSON($options));
}
else {
$this->responseXML = $keyObj->toXML();
$this->responseXML = $keyObj->toXML($options);
}

Zotero_DB::commit();
Expand Down
83 changes: 61 additions & 22 deletions model/Key.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public function __get($field) {
case 'key':
case 'userID':
case 'name':
case 'dateAdded':
break;

default:
Expand Down Expand Up @@ -244,6 +243,10 @@ public function save() {
$this->id = $insertID;
}

// Name might have changed -- keep in sync with self::load()
Z_Core::$MC->delete("keyInfoByID_" . $this->id);
Z_Core::$MC->delete("keyInfoByKey_" . $this->key);

if (!$insertID) {
$sql = "SELECT * FROM keyPermissions WHERE keyID=?";
$oldRows = Zotero_DB::query($sql, $this->id);
Expand Down Expand Up @@ -376,6 +379,8 @@ public function erase() {

Zotero_DB::commit();

Z_Core::$MC->delete("keyInfoByID_" . $this->id);
Z_Core::$MC->delete("keyInfoByKey_" . $this->key);
// Keep in sync with Zotero_Keys::getByKey()
Z_Core::$MC->delete("keyIDByKey_" . $this->key);
// Keep in sync with load() and save()
Expand All @@ -390,7 +395,9 @@ public function erase() {
*
* @return SimpleXMLElement Key data as SimpleXML element
*/
public function toXML() {
public function toXML($options = []) {
$isSuper = !empty($options['super']);

if (($this->id || $this->key) && !$this->loaded) {
$this->load();
}
Expand All @@ -399,10 +406,6 @@ public function toXML() {
$xml = new SimpleXMLElement($xml);

$xml['key'] = $this->key;
$xml['dateAdded'] = $this->dateAdded;
if ($this->lastUsed != '0000-00-00 00:00:00') {
$xml['lastUsed'] = $this->lastUsed;
}
$xml->name = $this->name;

if ($this->permissions) {
Expand Down Expand Up @@ -436,16 +439,26 @@ public function toXML() {
}
}

$ips = $this->getRecentIPs();
if ($ips) {
$xml->recentIPs = implode(' ', $ips);
if ($isSuper) {
$row = $this->getDates();
$xml['dateAdded'] = $row['dateAdded'];
if ($row['lastUsed'] != '0000-00-00 00:00:00') {
$xml['lastUsed'] = $row['lastUsed'];
}

$ips = $this->getRecentIPs();
if ($ips) {
$xml->recentIPs = implode(' ', $ips);
}
}

return $xml;
}


public function toJSON() {
public function toJSON($options = []) {
$isWebsite = !empty($options['website']);

if (($this->id || $this->key) && !$this->loaded) {
$this->load();
}
Expand Down Expand Up @@ -502,14 +515,17 @@ public function toJSON() {
}
}

$json['dateAdded'] = Zotero_Date::sqlToISO8601($this->dateAdded);
if ($this->lastUsed != '0000-00-00 00:00:00') {
$json['lastUsed'] = Zotero_Date::sqlToISO8601($this->lastUsed);
}

$ips = $this->getRecentIPs();
if ($ips) {
$json['recentIPs'] = $ips;
if ($isWebsite) {
$row = $this->getDates();
$json['dateAdded'] = Zotero_Date::sqlToISO8601($row['dateAdded']);
if ($row['lastUsed'] != '0000-00-00 00:00:00') {
$json['lastUsed'] = Zotero_Date::sqlToISO8601($row['lastUsed']);
}

$ips = $this->getRecentIPs();
if ($ips) {
$json['recentIPs'] = $ips;
}
}

return $json;
Expand Down Expand Up @@ -566,12 +582,26 @@ public function logAccess() {

private function load() {
if ($this->id) {
$sql = "SELECT * FROM `keys` WHERE keyID=?";
$row = Zotero_DB::rowQuery($sql, $this->id);
$cacheKey = "keyInfoByID_" . $this->id;
$row = Z_Core::$MC->get($cacheKey);
if (!$row) {
$sql = "SELECT `key`, userID, name FROM `keys` WHERE keyID=?";
$row = Zotero_DB::rowQuery($sql, $this->id);
if ($row) {
Z_Core::$MC->set($cacheKey, $row, 60);
}
}
}
else if ($this->key) {
$sql = "SELECT * FROM `keys` WHERE `key`=?";
$row = Zotero_DB::rowQuery($sql, $this->key);
$cacheKey = "keyInfoByKey_" . $this->key;
$row = Z_Core::$MC->get($cacheKey);
if (!$row) {
$sql = "SELECT keyID, userID, name FROM `keys` WHERE `key`=?";
$row = Zotero_DB::rowQuery($sql, $this->key);
if ($row) {
Z_Core::$MC->set($cacheKey, $row, 60);
}
}
}
if (!$row) {
return false;
Expand Down Expand Up @@ -605,6 +635,15 @@ private function load() {
}


private function getDates() {
$row = Zotero_DB::rowQuery("SELECT dateAdded, lastUsed FROM `keys` WHERE keyID=?", $this->id);
return [
'dateAdded' => $row['dateAdded'],
'lastUsed' => $row['lastUsed']
];
}


private function getRecentIPs() {
$sql = "SELECT INET_NTOA(ipAddress) FROM keyAccessLog WHERE keyID=?
ORDER BY timestamp DESC LIMIT 5";
Expand Down

0 comments on commit 3bb16ec

Please sign in to comment.