diff --git a/README.md b/README.md index 7057e2c..3a301a7 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ Laravel SingleStore Backup is a package that makes it easy to make backups of yo - [Setting Timeout Parameter](#setting-timeout-parameter) - [Init Backup](#init-backup-non-local-only) - [Differential Backup](#differential-backup-non-local-only) -- [Setting multipart_chunk_size_mb Parameter](#setting-multipart_chunk_size_mb-parameter-s3-only) -- [Setting s3_force_path_style Parameter](#setting-s3_force_path_style-parameter-s3-compatible-only) +- [Advanced Usage](#advanced-usage) +- [Publishing Config File](#publishing-config-file) - [License](#license) ## Installation @@ -44,6 +44,8 @@ SINGLESTORE_BACKUP_PATH= # S3 storage SINGLESTORE_BACKUP_REGION= +SINGLESTORE_BACKUP_MULTIPART_CHUNK_SIZE= +SINGLESTORE_BACKUP_FORCE_PATH_STYLE= # External storages SINGLESTORE_BACKUP_ENDPOINT= @@ -68,7 +70,7 @@ You can set the timeout parameter, a value specified in milliseconds, to determi php artisan singlestore:backup --timeout=30000 ``` -## Init Backup (Non-local Only) +## Init Backup If you're making an incremental backup and want to create the `INIT` backup, you can do that by using the `--init` parameter. @@ -76,7 +78,7 @@ If you're making an incremental backup and want to create the `INIT` backup, you php artisan singlestore:backup --init ``` -## Differential Backup (Non-local Only) +## Differential Backup If you're making an incremental backup and want to do a `DIFFERENTIAL` backup, you can do that by using the `--differential` parameter. @@ -84,21 +86,10 @@ If you're making an incremental backup and want to do a `DIFFERENTIAL` backup, y php artisan singlestore:backup --differential ``` -## Setting multipart_chunk_size_mb Parameter (S3 Only) +## Advanced Usage -The `multipart_chunk_size_mb` must be in the range of [5..500]. By default, the chunk size is 5 MB. A larger chunk size allows users to upload large files without going over Amazon’s limitation on maximum number of parts per upload. Although, a larger chunk size increases the chance of a network error during the upload to S3. If a chunk fails to upload, SingleStoreDB retries uploading it until the limit set on the number of retries by AWS is reached. Each partition will use "multipart_chunk_size_mb" MB(s) of additional memory. -```sh -php artisan singlestore:backup --multipart_chunk_size_mb=10 -``` - -## Setting s3_force_path_style Parameter (S3 Compatible Only) - -`s3_force_path_style` is an optional boolean JSON config option that defaults to true. It specifies whether to use path style (the default: region.amazonaws.com/bucket) or virtual address style (bucket.region.amazonaws.com) syntax when specifying the location of the bucket. - -```sh -php artisan singlestore:backup --s3_force_path_style -``` +## Publishing Config File ## License diff --git a/config/singlestore-backup.php b/config/singlestore-backup.php index bea13ce..cb360f4 100644 --- a/config/singlestore-backup.php +++ b/config/singlestore-backup.php @@ -23,16 +23,6 @@ */ 'path' => env('SINGLESTORE_BACKUP_PATH'), - /* - |-------------------------------------------------------------------------- - | SingleStore Backup Region - |-------------------------------------------------------------------------- - | - | The AWS S3 region where the backups will be stored (Only used by "s3" driver). - | - */ - 'region' => env('SINGLESTORE_BACKUP_REGION'), - /* |-------------------------------------------------------------------------- | SingleStore Backup Endpoint @@ -72,4 +62,18 @@ | */ 'secret_key' => env('SINGLESTORE_BACKUP_SECRET_KEY'), + + /* + |-------------------------------------------------------------------------- + | SingleStore Backup S3 Parameters + |-------------------------------------------------------------------------- + | + | AWS S3 extra parameters (Only used by "s3" driver). + | + */ + 'region' => env('SINGLESTORE_BACKUP_REGION'), + + 'multipart_chunk_size' => (int) env('SINGLESTORE_BACKUP_MULTIPART_CHUNK_SIZE'), + + 'force_path_style' => (bool) env('SINGLESTORE_BACKUP_FORCE_PATH_STYLE'), ]; diff --git a/src/Console/SinglestoreBackupCommand.php b/src/Console/SinglestoreBackupCommand.php index aafec39..3670bcc 100644 --- a/src/Console/SinglestoreBackupCommand.php +++ b/src/Console/SinglestoreBackupCommand.php @@ -14,7 +14,7 @@ class SinglestoreBackupCommand extends Command * * @var string */ - protected $signature = 'singlestore:backup {--timeout=} {--init} {--differential} {--s3_force_path_style} {--multipart_chunk_size_mb=}'; + protected $signature = 'singlestore:backup {--timeout=} {--init} {--differential}'; /** * The console command description. @@ -40,11 +40,19 @@ public function handle() $this->warn('Starting backup... This might take a while.'); $singlestoreBackup = new SinglestoreBackup( - $this->option('timeout'), - $this->option('init'), - $this->option('differential'), - $this->option('multipart_chunk_size_mb'), - $this->option('s3_force_path_style') + driver: config('singlestore-backup.driver'), + database: config('database.connections.singlestore.database'), + path: config('singlestore-backup.path'), + endpoint: config('singlestore-backup.endpoint'), + timeout: $this->option('timeout'), + publicKey: config('singlestore-backup.public_key'), + secretKey: config('singlestore-backup.secret_key'), + bucket: config('singlestore-backup.bucket'), + init: $this->option('init'), + differential: $this->option('differential'), + region: config('singlestore-backup.region'), + multipartChunkSizeMb: config('singlestore-backup.multipart_chunk_size'), + s3ForcePathStyle: config('singlestore-backup.force_path_style') ); try { diff --git a/src/SinglestoreBackup.php b/src/SinglestoreBackup.php index 9fe7330..da9fc40 100644 --- a/src/SinglestoreBackup.php +++ b/src/SinglestoreBackup.php @@ -6,21 +6,25 @@ class SinglestoreBackup { - protected string $driver; - public function __construct( + protected string $driver, + protected string $database, + protected ?string $path = null, + protected ?string $endpoint = null, protected ?int $timeout = null, + protected ?string $publicKey = null, + protected ?string $secretKey = null, + protected ?string $bucket = null, protected bool $init = false, protected bool $differential = false, + protected ?string $region = null, protected ?int $multipartChunkSizeMb = null, - protected ?bool $s3ForcePathStyle = null + protected ?bool $s3ForcePathStyle = null, ) { if ($init && $differential) { throw new \InvalidArgumentException('You can\'t use "$init" and "$differential" attributes at the same time.'); } - $this->driver = config('singlestore-backup.driver'); - if ($this->driver !== 's3' && $this->multipartChunkSizeMb) { throw new \InvalidArgumentException('You can\'t use "$multipartChunkSizeMb" attribute with "' . $this->driver . '" driver.'); } @@ -50,21 +54,16 @@ protected function executeLocalStorageQuery(): array $timeoutStatement = "TIMEOUT {$this->timeout}"; } - $database = (string) config('database.connections.singlestore.database'); - $path = (string) config('singlestore-backup.path'); - // Mount query - $rawQuery = "BACKUP DATABASE {$database} TO ? {$timeoutStatement}"; + $rawQuery = "BACKUP DATABASE {$this->database} TO ? {$timeoutStatement}"; $rawQuery = preg_replace('/\s+/', ' ', $rawQuery); - return DB::select($rawQuery, [$path]); + return DB::select($rawQuery, [$this->path]); } protected function executeExternalStorageQuery(): array { - [$to, $bucket, $config, $credentials] = static::getExternalStorageParameters(); - - $database = (string) config('database.connections.singlestore.database'); + [$to, $config, $credentials] = static::getExternalStorageParameters(); // Mount statements $with = ''; @@ -81,33 +80,30 @@ protected function executeExternalStorageQuery(): array } // Mount query - $rawQuery = "BACKUP DATABASE {$database} {$with} TO {$to} ? {$timeoutStatement} CONFIG ? CREDENTIALS ?"; + $rawQuery = "BACKUP DATABASE {$this->database} {$with} TO {$to} ? {$timeoutStatement} CONFIG ? CREDENTIALS ?"; $rawQuery = preg_replace('/\s+/', ' ', $rawQuery); - return DB::select($rawQuery, [$bucket, $config, $credentials]); + return DB::select($rawQuery, [$this->bucket, $config, $credentials]); } protected function getExternalStorageParameters(): array { $config = [ - 'endpoint_url' => (string) config('singlestore-backup.endpoint'), + 'endpoint_url' => $this->endpoint, ]; - - $publicKey = (string) config('singlestore-backup.public_key'); - $secretKey = (string) config('singlestore-backup.secret_key'); $credentials = match($this->driver) { 's3' => [ - 'aws_access_key_id' => $publicKey, - 'aws_secret_access_key' => $secretKey, + 'aws_access_key_id' => $this->publicKey, + 'aws_secret_access_key' => $this->secretKey, ], 'gcs' => [ - 'access_id' => $publicKey, - 'secret_key' => $secretKey, + 'access_id' => $this->publicKey, + 'secret_key' => $this->secretKey, ], 'azure' => [ - 'account_name' => $publicKey, - 'account_key' => $secretKey, + 'account_name' => $this->publicKey, + 'account_key' => $this->secretKey, ], }; @@ -119,11 +115,13 @@ protected function getExternalStorageParameters(): array $config[]['s3_force_path_style'] = $this->s3ForcePathStyle; } + if ($this->driver === 's3' && $this->region) { + $config['region'] = $this->region; + } + return [ strtoupper($this->driver), - (string) config('singlestore-backup.bucket'), - json_encode($config), json_encode($credentials),