mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
Merge pull request #8546 from appwrite/fix-seconds-precision-exception
Feat: Add seconds precision to scheduledAt
This commit is contained in:
commit
b115b6fb67
10 changed files with 82 additions and 44 deletions
|
|
@ -1643,7 +1643,7 @@ App::post('/v1/functions/:functionId/executions')
|
|||
->param('path', '/', new Text(2048), 'HTTP path of execution. Path can include query params. Default value is /', true)
|
||||
->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true), 'HTTP method of execution. Default value is GET.', true)
|
||||
->param('headers', [], new AnyOf([new Assoc(), new Text(65535)], AnyOf::TYPE_MIXED), 'HTTP headers of execution. Defaults to empty.', true)
|
||||
->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), 'Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future.', true)
|
||||
->param('scheduledAt', null, new DatetimeValidator(true, DateTimeValidator::PRECISION_MINUTES, 60), 'Scheduled execution time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.', true)
|
||||
->inject('response')
|
||||
->inject('request')
|
||||
->inject('project')
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Projects;
|
|||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Cache\Cache;
|
||||
|
|
@ -209,7 +209,7 @@ App::post('/v1/projects')
|
|||
$audit = new Audit($dbForProject);
|
||||
$audit->setup();
|
||||
|
||||
$abuse = new TimeLimit('', 0, 1, $dbForProject);
|
||||
$abuse = new AbuseDatabase('', 0, 1, $dbForProject);
|
||||
$abuse->setup();
|
||||
|
||||
/** @var array $collections */
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use Appwrite\Messaging\Adapter\Realtime;
|
|||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Abuse\Abuse;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
|
||||
use Utopia\App;
|
||||
use Utopia\Cache\Adapter\Filesystem;
|
||||
use Utopia\Cache\Cache;
|
||||
|
|
@ -380,7 +380,7 @@ App::init()
|
|||
foreach ($abuseKeyLabel as $abuseKey) {
|
||||
$start = $request->getContentRangeStart();
|
||||
$end = $request->getContentRangeEnd();
|
||||
$timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
|
||||
$timeLimit = new AbuseDatabase($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject);
|
||||
$timeLimit
|
||||
->setParam('{projectId}', $project->getId())
|
||||
->setParam('{userId}', $user->getId())
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use Swoole\Http\Request as SwooleRequest;
|
|||
use Swoole\Http\Response as SwooleResponse;
|
||||
use Swoole\Http\Server;
|
||||
use Swoole\Process;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\CLI\Console;
|
||||
|
|
@ -101,8 +101,8 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
|
|||
$audit->setup();
|
||||
}
|
||||
|
||||
if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
|
||||
$adapter = new TimeLimit("", 0, 1, $dbForConsole);
|
||||
if ($dbForConsole->getCollection(AbuseDatabase::COLLECTION)->isEmpty()) {
|
||||
$adapter = new AbuseDatabase("", 0, 1, $dbForConsole);
|
||||
$adapter->setup();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use Swoole\Runtime;
|
|||
use Swoole\Table;
|
||||
use Swoole\Timer;
|
||||
use Utopia\Abuse\Abuse;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
|
||||
use Utopia\App;
|
||||
use Utopia\Cache\Adapter\Sharding;
|
||||
use Utopia\Cache\Cache;
|
||||
|
|
@ -463,7 +463,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server,
|
|||
*
|
||||
* Abuse limits are connecting 128 times per minute and ip address.
|
||||
*/
|
||||
$timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject);
|
||||
$timeLimit = new AbuseDatabase('url:{url},ip:{ip}', 128, 60, $dbForProject);
|
||||
$timeLimit
|
||||
->setParam('{ip}', $request->getIP())
|
||||
->setParam('{url}', $request->getURI());
|
||||
|
|
@ -563,7 +563,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re
|
|||
*
|
||||
* Abuse limits are sending 32 times per minute and connection.
|
||||
*/
|
||||
$timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database);
|
||||
$timeLimit = new AbuseDatabase('url:{url},connection:{connection}', 32, 60, $database);
|
||||
|
||||
$timeLimit
|
||||
->setParam('{connection}', $connection)
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@
|
|||
"ext-sockets": "*",
|
||||
"appwrite/php-runtimes": "0.14.*",
|
||||
"appwrite/php-clamav": "2.0.*",
|
||||
"utopia-php/abuse": "0.38.*",
|
||||
"utopia-php/abuse": "0.40.*",
|
||||
"utopia-php/analytics": "0.10.*",
|
||||
"utopia-php/audit": "0.40.*",
|
||||
"utopia-php/audit": "0.41.*",
|
||||
"utopia-php/cache": "0.10.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.50.*",
|
||||
"utopia-php/database": "0.51.*",
|
||||
"utopia-php/domains": "0.5.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
|
|
|
|||
44
composer.lock
generated
44
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "340aae0879435fc71eac688d47033eb4",
|
||||
"content-hash": "cd0323e7303780f34b2f775a526de516",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
|
@ -1429,26 +1429,28 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/abuse",
|
||||
"version": "0.38.0",
|
||||
"version": "0.40.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/abuse.git",
|
||||
"reference": "b7be9086c9d9b4561d810cbd42fdda798742f56c"
|
||||
"reference": "69748a6741a9e44f0c9e430f3c2bd2b8a677c048"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/b7be9086c9d9b4561d810cbd42fdda798742f56c",
|
||||
"reference": "b7be9086c9d9b4561d810cbd42fdda798742f56c",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/69748a6741a9e44f0c9e430f3c2bd2b8a677c048",
|
||||
"reference": "69748a6741a9e44f0c9e430f3c2bd2b8a677c048",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-pdo": "*",
|
||||
"ext-redis": "*",
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "0.50.*"
|
||||
"utopia-php/database": "0.51.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.5.*",
|
||||
"phpbench/phpbench": "^1.2",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpunit": "^9.4"
|
||||
},
|
||||
|
|
@ -1472,9 +1474,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/abuse/issues",
|
||||
"source": "https://github.com/utopia-php/abuse/tree/0.38.0"
|
||||
"source": "https://github.com/utopia-php/abuse/tree/0.40.0"
|
||||
},
|
||||
"time": "2024-06-24T00:52:02+00:00"
|
||||
"time": "2024-08-16T06:08:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/analytics",
|
||||
|
|
@ -1524,21 +1526,21 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/audit",
|
||||
"version": "0.40.0",
|
||||
"version": "0.41.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/audit.git",
|
||||
"reference": "735ae211ce5fee5b52b736731571b4030b1d7cdc"
|
||||
"reference": "77f1d0a95ea791e38a38a8bc1b7728ffcedcd2d1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/735ae211ce5fee5b52b736731571b4030b1d7cdc",
|
||||
"reference": "735ae211ce5fee5b52b736731571b4030b1d7cdc",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/77f1d0a95ea791e38a38a8bc1b7728ffcedcd2d1",
|
||||
"reference": "77f1d0a95ea791e38a38a8bc1b7728ffcedcd2d1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "0.50.*"
|
||||
"utopia-php/database": "0.51.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.5.*",
|
||||
|
|
@ -1565,9 +1567,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/audit/issues",
|
||||
"source": "https://github.com/utopia-php/audit/tree/0.40.0"
|
||||
"source": "https://github.com/utopia-php/audit/tree/0.41.0"
|
||||
},
|
||||
"time": "2024-06-24T00:52:17+00:00"
|
||||
"time": "2024-08-16T06:08:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cache",
|
||||
|
|
@ -1721,16 +1723,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.50.4",
|
||||
"version": "0.51.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "fd3b856be77bd643bc8a9e3572ee11e4185b9230"
|
||||
"reference": "845783a54cced784e00db084a29486fdb96d3d58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/fd3b856be77bd643bc8a9e3572ee11e4185b9230",
|
||||
"reference": "fd3b856be77bd643bc8a9e3572ee11e4185b9230",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/845783a54cced784e00db084a29486fdb96d3d58",
|
||||
"reference": "845783a54cced784e00db084a29486fdb96d3d58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1771,9 +1773,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.50.4"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.51.1"
|
||||
},
|
||||
"time": "2024-08-13T03:18:26+00:00"
|
||||
"time": "2024-08-16T10:54:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Appwrite\Extend\Exception;
|
|||
use Executor\Executor;
|
||||
use Throwable;
|
||||
use Utopia\Abuse\Abuse;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
use Utopia\Abuse\Adapters\Database as AbuseDatabase;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Cache\Adapter\Filesystem;
|
||||
use Utopia\Cache\Cache;
|
||||
|
|
@ -493,7 +493,7 @@ class Deletes extends Action
|
|||
$projectCollectionIds = [
|
||||
...\array_keys(Config::getParam('collections', [])['projects']),
|
||||
Audit::COLLECTION,
|
||||
TimeLimit::COLLECTION,
|
||||
AbuseDatabase::COLLECTION,
|
||||
];
|
||||
|
||||
$limit = \count($projectCollectionIds) + 25;
|
||||
|
|
@ -686,7 +686,7 @@ class Deletes extends Action
|
|||
{
|
||||
$projectId = $project->getId();
|
||||
$dbForProject = $getProjectDB($project);
|
||||
$timeLimit = new TimeLimit("", 0, 1, $dbForProject);
|
||||
$timeLimit = new AbuseDatabase("", 0, 1, $dbForProject);
|
||||
$abuse = new Abuse($timeLimit);
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -219,7 +219,8 @@ class FunctionsCustomClientTest extends Scope
|
|||
|
||||
// Schedule execution for the future
|
||||
\date_default_timezone_set('UTC');
|
||||
$futureTime = (new \DateTime())->add(new \DateInterval('PT10S'));
|
||||
$futureTime = (new \DateTime())->add(new \DateInterval('PT2M'));
|
||||
$futureTime->setTime($futureTime->format('H'), $futureTime->format('i'), 0, 0);
|
||||
|
||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
|
@ -236,7 +237,7 @@ class FunctionsCustomClientTest extends Scope
|
|||
|
||||
$executionId = $execution['body']['$id'];
|
||||
|
||||
sleep(10);
|
||||
sleep(60 + 60 + 15); // up to 1 minute round up, 1 minute schedule postpone, 15s cold start safety
|
||||
|
||||
$start = \microtime(true);
|
||||
while (true) {
|
||||
|
|
@ -251,7 +252,7 @@ class FunctionsCustomClientTest extends Scope
|
|||
}
|
||||
|
||||
if (\microtime(true) - $start > 10) {
|
||||
$this->fail('Execution did not complete within 10 seconds of schedule in status ' . $execution['body']['status'] . ': ' . \json_encode($execution));
|
||||
$this->fail('Scheduled execution did not complete with status ' . $execution['body']['status'] . ': ' . \json_encode($execution));
|
||||
}
|
||||
|
||||
usleep(500000); // 0.5 seconds
|
||||
|
|
@ -267,7 +268,6 @@ class FunctionsCustomClientTest extends Scope
|
|||
/* Test for FAILURE */
|
||||
|
||||
// Schedule synchronous execution
|
||||
|
||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
|
|
@ -278,6 +278,41 @@ class FunctionsCustomClientTest extends Scope
|
|||
|
||||
$this->assertEquals(400, $execution['headers']['status-code']);
|
||||
|
||||
// Execution with seconds precision
|
||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'async' => true,
|
||||
'scheduledAt' => (new \DateTime("2100-12-08 16:12:02"))->format(\DateTime::ATOM)
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $execution['headers']['status-code']);
|
||||
|
||||
// Execution with milliseconds precision
|
||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'async' => true,
|
||||
'scheduledAt' => (new \DateTime("2100-12-08 16:12:02.255"))->format(\DateTime::ATOM)
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $execution['headers']['status-code']);
|
||||
|
||||
// Execution too soon
|
||||
$futureTime = (new \DateTime())->add(new \DateInterval('PT1M'));
|
||||
$futureTime->setTime($futureTime->format('H'), $futureTime->format('i'), 0, 0);
|
||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'async' => true,
|
||||
'scheduledAt' => $futureTime->format(\DateTime::ATOM),
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $execution['headers']['status-code']);
|
||||
|
||||
// Cleanup : Delete function
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/functions/' . $function['body']['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
|
|
|
|||
|
|
@ -1286,14 +1286,15 @@ class FunctionsCustomServerTest extends Scope
|
|||
*/
|
||||
public function testDeleteScheduledExecution($data): array
|
||||
{
|
||||
$futureTime = (new \DateTime())->add(new \DateInterval('PT10H'))->format('Y-m-d H:i:s');
|
||||
$futureTime = (new \DateTime())->add(new \DateInterval('PT10H'));
|
||||
$futureTime->setTime($futureTime->format('H'), $futureTime->format('i'), 0, 0);
|
||||
|
||||
$execution = $this->client->call(Client::METHOD_POST, '/functions/' . $data['functionId'] . '/executions', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'async' => true,
|
||||
'scheduledAt' => $futureTime,
|
||||
'scheduledAt' => $futureTime->format('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
$executionId = $execution['body']['$id'] ?? '';
|
||||
|
|
|
|||
Loading…
Reference in a new issue