Merge branch 'preloader' of github.com:appwrite/appwrite into swoole
This commit is contained in:
commit
a9b823c720
|
@ -153,6 +153,12 @@ bash ./build.sh 1.0.0
|
|||
|
||||
Before running the command, make sure you have proper write permissions to the Appwrite docker hub team.
|
||||
|
||||
**Build for multicore**
|
||||
|
||||
```bash
|
||||
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t appwrite/multicore:0.0.0 --push
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
To run tests manually, run phpunit from your command line:
|
||||
|
@ -161,6 +167,27 @@ To run tests manually, run phpunit from your command line:
|
|||
docker exec appwrite test
|
||||
```
|
||||
|
||||
## Benchmarking
|
||||
|
||||
You can use WRK Docker image to benchmark the server performance. Benchmarking is extremely useful when you want to compare how the server behaves before and after a change has been applied. Replace [APPWRITE_HOSTNAME_OR_IP] with your Appwrite server hostname or IP. Note that localhost is not accessible from inside the WRK container.
|
||||
|
||||
```
|
||||
Options:
|
||||
-c, --connections <N> Connections to keep open
|
||||
-d, --duration <T> Duration of test
|
||||
-t, --threads <N> Number of threads to use
|
||||
|
||||
-s, --script <S> Load Lua script file
|
||||
-H, --header <H> Add header to request
|
||||
--latency Print latency statistics
|
||||
--timeout <T> Socket/request timeout
|
||||
-v, --version Print version details
|
||||
```
|
||||
|
||||
```bash
|
||||
docker run --rm skandyla/wrk -t5 -c10 -d30 https://[APPWRITE_HOSTNAME_OR_IP]
|
||||
```
|
||||
|
||||
## Code Maintenance
|
||||
|
||||
We use some automation tools to help us keep a healthy code base.
|
||||
|
|
|
@ -130,4 +130,4 @@ RUN echo extension=redis.so >> /usr/local/etc/php/conf.d/redis.ini
|
|||
|
||||
EXPOSE 80
|
||||
|
||||
CMD [ "php" , "app/server.php" ]
|
||||
CMD [ "php" , "app/server.php" ]
|
||||
|
|
|
@ -8,7 +8,7 @@ return [
|
|||
APP_PLATFORM_CLIENT => [
|
||||
'key' => APP_PLATFORM_CLIENT,
|
||||
'name' => 'Client',
|
||||
'description' => 'Client libraries for integrating with '.APP_NAME.' to build client-based applications and websites. Read the [getting started for web](/docs/getting-started-for-web) or [getting started for Flutter](/docs/getting-started-for-flutter) tutorials to start building your first application.',
|
||||
'description' => 'Client libraries for integrating with Appwrite to build client-based applications and websites. Read the [getting started for web](/docs/getting-started-for-web) or [getting started for Flutter](/docs/getting-started-for-flutter) tutorials to start building your first application.',
|
||||
'enabled' => true,
|
||||
'beta' => false,
|
||||
'languages' => [ // TODO change key to 'sdks'
|
||||
|
@ -121,7 +121,7 @@ return [
|
|||
APP_PLATFORM_SERVER => [
|
||||
'key' => APP_PLATFORM_SERVER,
|
||||
'name' => 'Server',
|
||||
'description' => 'Libraries for integrating with '.APP_NAME.' to build server side integrations. Read the [getting started for server](/docs/getting-started-for-server) tutorial to start building your first server integration.',
|
||||
'description' => 'Libraries for integrating with Appwrite to build server side integrations. Read the [getting started for server](/docs/getting-started-for-server) tutorial to start building your first server integration.',
|
||||
'enabled' => true,
|
||||
'beta' => false,
|
||||
'languages' => [ // TODO change key to 'sdks'
|
||||
|
|
|
@ -156,7 +156,6 @@ App::get('/v1/locale/continents')
|
|||
$response->json($list);
|
||||
}, ['response', 'locale']);
|
||||
|
||||
|
||||
App::get('/v1/locale/currencies')
|
||||
->desc('List Currencies')
|
||||
->groups(['api', 'locale'])
|
||||
|
|
|
@ -12,7 +12,7 @@ App::init(function ($utopia, $request, $response, $layout) {
|
|||
if (!empty($request->getQuery('version', ''))) {
|
||||
$layout->setPath(__DIR__.'/../../views/layouts/empty.phtml');
|
||||
}
|
||||
|
||||
|
||||
$layout
|
||||
->setParam('title', APP_NAME)
|
||||
->setParam('protocol', $request->getProtocol())
|
||||
|
|
34
app/preload.php
Normal file
34
app/preload.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Init
|
||||
*
|
||||
* Inializes both Appwrite API entry point, queue workers, and CLI tasks.
|
||||
* Set configuration, framework resources, app constants
|
||||
*
|
||||
*/
|
||||
|
||||
// ini_set('display_errors', 1);
|
||||
// ini_set('display_startup_errors', 1);
|
||||
// error_reporting(E_ALL);
|
||||
|
||||
if (file_exists(__DIR__.'/../vendor/autoload.php')) {
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
}
|
||||
|
||||
use Appwrite\Preloader\Preloader;
|
||||
|
||||
include 'init.php';
|
||||
include 'app.php';
|
||||
|
||||
(new Preloader())
|
||||
->paths(realpath(__DIR__ . '/../app/config'))
|
||||
->paths(realpath(__DIR__ . '/../app/controllers'))
|
||||
->paths(realpath(__DIR__ . '/../src'))
|
||||
->ignore(realpath(__DIR__ . '/../vendor/twig/twig'))
|
||||
->ignore(realpath(__DIR__ . '/../vendor/guzzlehttp/guzzle'))
|
||||
->ignore(realpath(__DIR__ . '/../vendor/geoip2'))
|
||||
->ignore(realpath(__DIR__ . '/../vendor/maxmind'))
|
||||
->ignore(realpath(__DIR__ . '/../vendor/maxmind-db'))
|
||||
->ignore(realpath(__DIR__ . '/../vendor/piwik'))
|
||||
->load();
|
|
@ -2,7 +2,7 @@ version: '3'
|
|||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.1.4
|
||||
image: traefik:2.2
|
||||
container_name: appwrite_traefik
|
||||
command:
|
||||
- --log.level=DEBUG
|
||||
|
|
139
src/Appwrite/Preloader/Preloader.php
Normal file
139
src/Appwrite/Preloader/Preloader.php
Normal file
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Preloader;
|
||||
|
||||
class Preloader
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $ignores = [];
|
||||
|
||||
private static $count = 0;
|
||||
|
||||
private $paths;
|
||||
|
||||
public function __construct(string ...$paths)
|
||||
{
|
||||
$this->paths = $paths;
|
||||
|
||||
// We'll use composer's classmap
|
||||
// to easily find which classes to autoload,
|
||||
// based on their filename
|
||||
$classMap = require __DIR__ . '/../../../vendor/composer/autoload_classmap.php';
|
||||
|
||||
$this->paths = array_merge(
|
||||
$this->paths,
|
||||
array_values($classMap)
|
||||
);
|
||||
}
|
||||
|
||||
public function paths(string ...$paths): Preloader
|
||||
{
|
||||
$this->paths = array_merge(
|
||||
$this->paths,
|
||||
$paths
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function ignore(string ...$names): Preloader
|
||||
{
|
||||
$this->ignores = array_merge(
|
||||
$this->ignores,
|
||||
$names
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function load(): void
|
||||
{
|
||||
// We'll loop over all registered paths
|
||||
// and load them one by one
|
||||
foreach ($this->paths as $path) {
|
||||
$this->loadPath(rtrim($path, '/'));
|
||||
}
|
||||
|
||||
$count = self::$count;
|
||||
|
||||
echo "[Preloader] Preloaded {$count} classes" . PHP_EOL;
|
||||
}
|
||||
|
||||
private function loadPath(string $path): void
|
||||
{
|
||||
// If the current path is a directory,
|
||||
// we'll load all files in it
|
||||
if (is_dir($path)) {
|
||||
$this->loadDir($path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we'll just load this one file
|
||||
$this->loadFile($path);
|
||||
}
|
||||
|
||||
private function loadDir(string $path): void
|
||||
{
|
||||
$handle = opendir($path);
|
||||
|
||||
// We'll loop over all files and directories
|
||||
// in the current path,
|
||||
// and load them one by one
|
||||
while ($file = readdir($handle)) {
|
||||
if (in_array($file, ['.', '..'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->loadPath("{$path}/{$file}");
|
||||
}
|
||||
|
||||
closedir($handle);
|
||||
}
|
||||
|
||||
private function loadFile(string $path): void
|
||||
{
|
||||
// And use it to make sure the class shouldn't be ignored
|
||||
if ($this->shouldIgnore($path)) {
|
||||
return;
|
||||
}
|
||||
echo "[Preloader] Preloaded `{$path}`" . PHP_EOL;
|
||||
// Finally we require the path,
|
||||
// causing all its dependencies to be loaded as well
|
||||
try {
|
||||
ob_start(); //Start of build
|
||||
|
||||
require_once $path;
|
||||
|
||||
$output = mb_strlen(ob_get_contents());
|
||||
|
||||
ob_end_clean(); //End of build
|
||||
} catch (\Throwable $th) {
|
||||
echo "[Preloader] Failed to load `{$path}`" . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
self::$count++;
|
||||
}
|
||||
|
||||
private function shouldIgnore(?string $path): bool
|
||||
{
|
||||
if($path === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!in_array(pathinfo($path, PATHINFO_EXTENSION), ['php'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($this->ignores as $ignore) {
|
||||
if (strpos($path, $ignore) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ class S3 extends Device
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
public function getName():string
|
||||
{
|
||||
return 'S3 Storage';
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ class S3 extends Device
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription():string
|
||||
{
|
||||
return 'S3 Bucket Storage drive for AWS or on premise solution';
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class S3 extends Device
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRoot()
|
||||
public function getRoot():string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
@ -35,14 +35,162 @@ class S3 extends Device
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPath($filename)
|
||||
public function getPath($filename):string
|
||||
{
|
||||
$path = '';
|
||||
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
$path = ($i < \strlen($filename)) ? $path.DIRECTORY_SEPARATOR.$filename[$i] : $path.DIRECTORY_SEPARATOR.'x';
|
||||
}
|
||||
|
||||
return $this->getRoot().$path.DIRECTORY_SEPARATOR.$filename;
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Upload.
|
||||
*
|
||||
* Upload a file to desired destination in the selected disk.
|
||||
*
|
||||
* @param string $target
|
||||
* @param string $filename
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return string|bool saved destination on success or false on failures
|
||||
*/
|
||||
public function upload($source, $path):bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read file by given path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read(string $path):string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Write file by given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write(string $path, string $data):bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move file from given source to given path, Return true on success and false on failure.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.filesize.php
|
||||
*
|
||||
* @param string $source
|
||||
* @param string $target
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function move(string $source, string $target):bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file in given path, Return true on success and false on failure.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.filesize.php
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(string $path, bool $recursive = false):bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns given file path its size.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.filesize.php
|
||||
*
|
||||
* @param $path
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFileSize(string $path):int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns given file path its mime type.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.mime-content-type.php
|
||||
*
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileMimeType(string $path):string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns given file path its MD5 hash value.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.md5-file.php
|
||||
*
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileHash(string $path):string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get directory size in bytes.
|
||||
*
|
||||
* Return -1 on error
|
||||
*
|
||||
* Based on http://www.jonasjohn.de/snippets/php/dir-size.htm
|
||||
*
|
||||
* @param $path
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDirectorySize(string $path):int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Partition Free Space.
|
||||
*
|
||||
* disk_free_space — Returns available space on filesystem or disk partition
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getPartitionFreeSpace():float
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Partition Total Space.
|
||||
*
|
||||
* disk_total_space — Returns the total size of a filesystem or disk partition
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getPartitionTotalSpace():float
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue