Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Database/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,11 @@ public function clearTimeout(string $event): void
{
// Clear existing callback
$this->before($event, 'timeout');

// Adapters that apply the timeout from this property on every statement
// (e.g. Postgres SET statement_timeout) would otherwise keep enforcing a
// cleared timeout on all subsequent queries.
$this->timeout = 0;
}

/**
Expand Down
30 changes: 20 additions & 10 deletions src/Database/Adapter/Mongo.php
Original file line number Diff line number Diff line change
Expand Up @@ -2712,15 +2712,6 @@ public function count(Document $collection, array $queries = [], ?int $max = nul
$this->escapeQueryAttributes($collection, $queries);

$filters = [];
$options = [];

if (!\is_null($max) && $max > 0) {
$options['limit'] = $max;
}

if ($this->timeout) {
$options['maxTimeMS'] = $this->timeout;
}

// Build filters from queries
$filters = $this->buildFilters($queries);
Expand All @@ -2745,6 +2736,11 @@ public function count(Document $collection, array $queries = [], ?int $max = nul
**/

$options = $this->getTransactionOptions();

if ($this->timeout) {
$options['maxTimeMS'] = $this->timeout;
}
Comment thread
abnegate marked this conversation as resolved.

$pipeline = [];

// Add match stage if filters are provided
Expand Down Expand Up @@ -2790,6 +2786,11 @@ public function count(Document $collection, array $queries = [], ?int $max = nul

return 0;
} catch (MongoException $e) {
$processed = $this->processException($e);
if ($processed instanceof TimeoutException) {
throw $processed;
}

return 0;
}
}
Expand Down Expand Up @@ -2848,7 +2849,16 @@ public function sum(Document $collection, string $attribute, array $queries = []
];

$options = $this->getTransactionOptions();
return $this->client->aggregate($name, $pipeline, $options)->cursor->firstBatch[0]->total ?? 0;

if ($this->timeout) {
$options['maxTimeMS'] = $this->timeout;
}

try {
return $this->client->aggregate($name, $pipeline, $options)->cursor->firstBatch[0]->total ?? 0;
} catch (MongoException $e) {
throw $this->processException($e);
}
}

/**
Expand Down
54 changes: 54 additions & 0 deletions tests/e2e/Adapter/Scopes/GeneralTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,61 @@ public function testQueryTimeout(): void
}
}

public function testCountTimeout(): void
{
if (!$this->getDatabase()->getAdapter()->getSupportForTimeouts()) {
$this->expectNotToPerformAssertions();
return;
}

/** @var Database $database */
$database = $this->getDatabase();

$database->createCollection('count-timeouts');

$this->assertEquals(
true,
$database->createAttribute(
collection: 'count-timeouts',
id: 'longtext',
type: Database::VAR_STRING,
size: 100000000,
required: true
)
);

$longtext = file_get_contents(__DIR__ . '/../../../resources/longtext.txt');
for ($i = 0; $i < 20; $i++) {
$database->createDocument('count-timeouts', new Document([
'longtext' => $longtext,
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any())
]
]));
}

try {
$database->setTimeout(1);

$thrown = null;
try {
// A substring scan forces the engine to walk every huge value; a
// cheap filter (e.g. notEqual) lets COUNT finish inside the timeout.
$database->count('count-timeouts', [
Query::contains('longtext', ['needle-that-does-not-exist']),
]);
} catch (\Exception $e) {
$thrown = $e;
}

$this->assertInstanceOf(TimeoutException::class, $thrown, 'count() must throw a timeout exception');
} finally {
$database->clearTimeout();
$database->deleteCollection('count-timeouts');
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.
}

public function testPreserveDatesUpdate(): void
{
Expand Down
Loading