diff --git a/README-CN.md b/README-CN.md new file mode 100644 index 000000000..cdc5d90bf --- /dev/null +++ b/README-CN.md @@ -0,0 +1,176 @@ +
+ 🌍 其他语言 +
+
+
+
+
+ 适用于[Flutter/Vue/Angular/React/iOS/Android/* 等等平台 *]的完整后端服务
+
+
+
+ 🌍 Translations +
@@ -170,3 +173,7 @@ Join our growing community around the world! See our official [Blog](https://med
## License
This repository is available under the [BSD 3-Clause License](./LICENSE).
+
+## Translations
+- [English](README.md)
+- [简体中文](README-CN.md)
diff --git a/app/config/auth.php b/app/config/auth.php
index 086ba9a7b..aab6833b6 100644
--- a/app/config/auth.php
+++ b/app/config/auth.php
@@ -7,35 +7,35 @@ return [
'name' => 'Email/Password',
'key' => 'emailPassword',
'icon' => '/images/users/email.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateSession',
+ 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateSession',
'enabled' => true,
],
'magic-url' => [
'name' => 'Magic URL',
'key' => 'usersAuthMagicURL',
'icon' => '/images/users/magic-url.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateMagicURLSession',
+ 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateMagicURLSession',
'enabled' => true,
],
'anonymous' => [
'name' => 'Anonymous',
'key' => 'anonymous',
'icon' => '/images/users/anonymous.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateAnonymousSession',
+ 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateAnonymousSession',
'enabled' => true,
],
'invites' => [
'name' => 'Invites',
'key' => 'invites',
'icon' => '/images/users/invites.png',
- 'docs' => 'https://appwrite.io/docs/client/teams?sdk=web#teamsCreateMembership',
+ 'docs' => 'https://appwrite.io/docs/client/teams?sdk=web-default#teamsCreateMembership',
'enabled' => true,
],
'jwt' => [
'name' => 'JWT',
'key' => 'JWT',
'icon' => '/images/users/jwt.png',
- 'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateJWT',
+ 'docs' => 'https://appwrite.io/docs/client/account?sdk=web-default#accountCreateJWT',
'enabled' => true,
],
'phone' => [
diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php
index a64c47597..8488b341f 100644
--- a/app/controllers/api/functions.php
+++ b/app/controllers/api/functions.php
@@ -46,7 +46,7 @@ App::post('/v1/functions')
->param('vars', [], new Assoc(), 'Key-value JSON object that will be passed to the function as environment variables.', true)
->param('events', [], new ArrayList(new WhiteList(array_keys(Config::getParam('events')), true)), 'Events list.', true)
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
- ->param('timeout', 15, new Range(1, 900), 'Function maximum execution time in seconds.', true)
+ ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.', true)
->inject('response')
->inject('dbForProject')
->action(function ($functionId, $name, $execute, $runtime, $vars, $events, $schedule, $timeout, $response, $dbForProject) {
@@ -294,7 +294,7 @@ App::put('/v1/functions/:functionId')
->param('vars', [], new Assoc(), 'Key-value JSON object that will be passed to the function as environment variables.', true)
->param('events', [], new ArrayList(new WhiteList(array_keys(Config::getParam('events')), true)), 'Events list.', true)
->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true)
- ->param('timeout', 15, new Range(1, 900), 'Maximum execution time in seconds.', true)
+ ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Maximum execution time in seconds.', true)
->inject('response')
->inject('dbForProject')
->inject('project')
diff --git a/app/init.php b/app/init.php
index 439e7cc3b..d591d1ddb 100644
--- a/app/init.php
+++ b/app/init.php
@@ -86,6 +86,9 @@ const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244';
const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite';
const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1';
+// Database Reconnect
+const DATABASE_RECONNECT_SLEEP = 2;
+const DATABASE_RECONNECT_MAX_ATTEMPTS = 10;
// Database Worker Types
const DATABASE_TYPE_CREATE_ATTRIBUTE = 'createAttribute';
const DATABASE_TYPE_CREATE_INDEX = 'createIndex';
diff --git a/app/realtime.php b/app/realtime.php
index 9acb37570..b2ddf6763 100644
--- a/app/realtime.php
+++ b/app/realtime.php
@@ -91,13 +91,32 @@ $server->error($logError);
function getDatabase(Registry &$register, string $namespace)
{
- $db = $register->get('dbPool')->get();
- $redis = $register->get('redisPool')->get();
+ $attempts = 0;
- $cache = new Cache(new RedisCache($redis));
- $database = new Database(new MariaDB($db), $cache);
- $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
- $database->setNamespace($namespace);
+ do {
+ try {
+ $attempts++;
+
+ $db = $register->get('dbPool')->get();
+ $redis = $register->get('redisPool')->get();
+
+ $cache = new Cache(new RedisCache($redis));
+ $database = new Database(new MariaDB($db), $cache);
+ $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
+ $database->setNamespace($namespace);
+
+ if (!$database->exists($database->getDefaultDatabase(), 'realtime')) {
+ throw new Exception('Collection not ready');
+ }
+ break; // leave loop if successful
+ } catch(\Exception $e) {
+ Console::warning("Database not ready. Retrying connection ({$attempts})...");
+ if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) {
+ throw new \Exception('Failed to connect to database: '. $e->getMessage());
+ }
+ sleep(DATABASE_RECONNECT_SLEEP);
+ }
+ } while ($attempts < DATABASE_RECONNECT_MAX_ATTEMPTS);
return [
$database,
@@ -106,6 +125,7 @@ function getDatabase(Registry &$register, string $namespace)
$register->get('redisPool')->put($redis);
}
];
+
};
$server->onStart(function () use ($stats, $register, $containerId, &$statsDocument, $logError) {
diff --git a/composer.json b/composer.json
index d6c0a7ff2..e7bd6646a 100644
--- a/composer.json
+++ b/composer.json
@@ -46,7 +46,7 @@
"utopia-php/cache": "0.4.*",
"utopia-php/cli": "0.11.*",
"utopia-php/config": "0.2.*",
- "utopia-php/database": "0.13.*",
+ "utopia-php/database": "0.14.*",
"utopia-php/locale": "0.4.*",
"utopia-php/orchestration": "0.2.*",
"utopia-php/registry": "0.5.*",
diff --git a/composer.lock b/composer.lock
index 62a9f81bd..91440e4a7 100644
--- a/composer.lock
+++ b/composer.lock
@@ -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": "f022f43cc2d6023c3dad3805b7c4455a",
+ "content-hash": "ab493f0a7f01a1105f8bc5caaf9b928b",
"packages": [
{
"name": "adhocore/jwt",
@@ -355,16 +355,16 @@
},
{
"name": "composer/package-versions-deprecated",
- "version": "1.11.99.4",
+ "version": "1.11.99.5",
"source": {
"type": "git",
"url": "https://github.com/composer/package-versions-deprecated.git",
- "reference": "b174585d1fe49ceed21928a945138948cb394600"
+ "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b174585d1fe49ceed21928a945138948cb394600",
- "reference": "b174585d1fe49ceed21928a945138948cb394600",
+ "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d",
+ "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d",
"shasum": ""
},
"require": {
@@ -408,7 +408,7 @@
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"support": {
"issues": "https://github.com/composer/package-versions-deprecated/issues",
- "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.4"
+ "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5"
},
"funding": [
{
@@ -424,7 +424,7 @@
"type": "tidelift"
}
],
- "time": "2021-09-13T08:41:34+00:00"
+ "time": "2022-01-17T14:14:24+00:00"
},
{
"name": "dragonmantank/cron-expression",
@@ -2141,16 +2141,16 @@
},
{
"name": "utopia-php/database",
- "version": "0.13.2",
+ "version": "0.14.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
- "reference": "bf92279b707b3a10ee5ec5df5c065023b2221357"
+ "reference": "2f2527bb080cf578fba327ea2ec637064561d403"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/utopia-php/database/zipball/bf92279b707b3a10ee5ec5df5c065023b2221357",
- "reference": "bf92279b707b3a10ee5ec5df5c065023b2221357",
+ "url": "https://api.github.com/repos/utopia-php/database/zipball/2f2527bb080cf578fba327ea2ec637064561d403",
+ "reference": "2f2527bb080cf578fba327ea2ec637064561d403",
"shasum": ""
},
"require": {
@@ -2198,9 +2198,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
- "source": "https://github.com/utopia-php/database/tree/0.13.2"
+ "source": "https://github.com/utopia-php/database/tree/0.14.0"
},
- "time": "2022-01-04T10:51:22+00:00"
+ "time": "2022-01-21T16:34:34+00:00"
},
{
"name": "utopia-php/domains",
@@ -3703,9 +3703,6 @@
"require": {
"php": "^7.1 || ^8.0"
},
- "replace": {
- "myclabs/deep-copy": "self.version"
- },
"require-dev": {
"doctrine/collections": "^1.0",
"doctrine/common": "^2.6",
@@ -6669,5 +6666,5 @@
"platform-overrides": {
"php": "8.0"
},
- "plugin-api-version": "2.1.0"
+ "plugin-api-version": "2.2.0"
}
diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php
index 1444c9066..b9ed5af27 100644
--- a/src/Appwrite/Resque/Worker.php
+++ b/src/Appwrite/Resque/Worker.php
@@ -70,9 +70,6 @@ abstract class Worker
throw new Exception("Please implement getName method in worker");
}
- const MAX_ATTEMPTS = 10;
- const SLEEP_TIME = 2;
-
const DATABASE_PROJECT = 'project';
const DATABASE_CONSOLE = 'console';
@@ -174,7 +171,7 @@ abstract class Worker
global $register;
$namespace = '';
- $sleep = self::SLEEP_TIME; // overwritten when necessary
+ $sleep = DATABASE_RECONNECT_SLEEP; // overwritten when necessary
switch ($type) {
case self::DATABASE_PROJECT:
@@ -201,18 +198,24 @@ abstract class Worker
$database = new Database(new MariaDB($register->get('db')), $cache);
$database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$database->setNamespace($namespace); // Main DB
+
if (!empty($projectId) && !$database->getDocument('projects', $projectId)->isEmpty()) {
throw new \Exception("Project does not exist: {$projectId}");
}
+
+ if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), 'realtime')) {
+ throw new \Exception('Console project not ready');
+ }
+
break; // leave loop if successful
} catch(\Exception $e) {
Console::warning("Database not ready. Retrying connection ({$attempts})...");
- if ($attempts >= self::MAX_ATTEMPTS) {
+ if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) {
throw new \Exception('Failed to connect to database: '. $e->getMessage());
}
sleep($sleep);
}
- } while ($attempts < self::MAX_ATTEMPTS);
+ } while ($attempts < DATABASE_RECONNECT_MAX_ATTEMPTS);
return $database;
}