Page MenuHomePhabricator

D15781.id38048.diff
No OneTemporary

D15781.id38048.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -34,6 +34,7 @@
'AphrontObjectMissingQueryException' => 'aphront/storage/exception/AphrontObjectMissingQueryException.php',
'AphrontParameterQueryException' => 'aphront/storage/exception/AphrontParameterQueryException.php',
'AphrontQueryException' => 'aphront/storage/exception/AphrontQueryException.php',
+ 'AphrontQueryTimeoutQueryException' => 'aphront/storage/exception/AphrontQueryTimeoutQueryException.php',
'AphrontRecoverableQueryException' => 'aphront/storage/exception/AphrontRecoverableQueryException.php',
'AphrontRequestStream' => 'aphront/requeststream/AphrontRequestStream.php',
'AphrontSchemaQueryException' => 'aphront/storage/exception/AphrontSchemaQueryException.php',
@@ -564,6 +565,7 @@
'AphrontObjectMissingQueryException' => 'AphrontQueryException',
'AphrontParameterQueryException' => 'AphrontQueryException',
'AphrontQueryException' => 'Exception',
+ 'AphrontQueryTimeoutQueryException' => 'AphrontRecoverableQueryException',
'AphrontRecoverableQueryException' => 'AphrontQueryException',
'AphrontRequestStream' => 'Phobject',
'AphrontSchemaQueryException' => 'AphrontQueryException',
diff --git a/src/aphront/storage/connection/AphrontDatabaseConnection.php b/src/aphront/storage/connection/AphrontDatabaseConnection.php
--- a/src/aphront/storage/connection/AphrontDatabaseConnection.php
+++ b/src/aphront/storage/connection/AphrontDatabaseConnection.php
@@ -9,6 +9,7 @@
private $transactionState;
private $readOnly;
+ private $queryTimeout;
abstract public function getInsertID();
abstract public function getAffectedRows();
@@ -48,6 +49,15 @@
return $this->readOnly;
}
+ public function setQueryTimeout($query_timeout) {
+ $this->queryTimeout = $query_timeout;
+ return $this;
+ }
+
+ public function getQueryTimeout() {
+ return $this->queryTimeout;
+ }
+
public function asyncQuery($raw_query) {
throw new Exception(pht('Async queries are not supported.'));
}
diff --git a/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php b/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php
--- a/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php
+++ b/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php
@@ -81,7 +81,37 @@
}
protected function rawQuery($raw_query) {
- return @$this->requireConnection()->query($raw_query);
+ $conn = $this->requireConnection();
+ $time_limit = $this->getQueryTimeout();
+
+ // If we have a query time limit, run this query synchronously but use
+ // the async API. This allows us to kill queries which take too long
+ // without requiring any configuration on the server side.
+ if ($time_limit && $this->supportsAsyncQueries()) {
+ $conn->query($raw_query, MYSQLI_ASYNC);
+
+ $read = array($conn);
+ $error = array($conn);
+ $reject = array($conn);
+
+ $result = mysqli::poll($read, $error, $reject, $time_limit);
+
+ if ($result === false) {
+ $this->closeConnection();
+ throw new Exception(
+ pht('Failed to poll mysqli connection!'));
+ } else if ($result === 0) {
+ $this->closeConnection();
+ throw new AphrontQueryTimeoutQueryException(
+ pht(
+ 'Query timed out after %s second(s)!',
+ new PhutilNumber($time_limit)));
+ }
+
+ return @$conn->reap_async_query();
+ }
+
+ return @$conn->query($raw_query);
}
protected function rawQueries(array $raw_queries) {
diff --git a/src/aphront/storage/exception/AphrontQueryTimeoutQueryException.php b/src/aphront/storage/exception/AphrontQueryTimeoutQueryException.php
new file mode 100644
--- /dev/null
+++ b/src/aphront/storage/exception/AphrontQueryTimeoutQueryException.php
@@ -0,0 +1,4 @@
+<?php
+
+final class AphrontQueryTimeoutQueryException
+ extends AphrontRecoverableQueryException {}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 3, 12:00 AM (2 d, 4 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6732159
Default Alt Text
D15781.id38048.diff (4 KB)

Event Timeline