Версия 0.3.0 #3
@ -0,0 +1,50 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Files;
|
||||||
|
|
||||||
|
use App\Services\Commands\DeleteOldFilesService;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
final class DeleteOldFilesFromStorage extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'files:delete-old-files-from-storage';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Remove temporary files or files that have been deleted from the storage table';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle(DeleteOldFilesService $deleteOldFilesService): void
|
||||||
|
{
|
||||||
|
$temporaryBeforeDate = Carbon::now()->subDays(3);
|
||||||
|
$deletedBeforeDate = Carbon::now()->subDays(7);
|
||||||
|
|
||||||
|
$result = $deleteOldFilesService->fromStorage($temporaryBeforeDate, $deletedBeforeDate);
|
||||||
|
if ($result->isError()) {
|
||||||
|
$this->error($result->getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->info($result->getMessage());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Services\Commands;
|
||||||
|
|
||||||
|
use App\Models\Storage as StorageModel;
|
||||||
|
use App\ServiceResults\ServiceResultError;
|
||||||
|
use App\ServiceResults\ServiceResultSuccess;
|
||||||
|
use App\Services\Service;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Storage as StorageSupport;
|
||||||
|
|
||||||
|
final class DeleteOldFilesService extends Service
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* $temporaryBeforeDate = date of deletion of temporary files
|
||||||
|
* $deletedBeforeDate = date of deletion files that were marked as deleted
|
||||||
|
*
|
||||||
|
* @param Carbon $temporaryBeforeDate
|
||||||
|
* @param Carbon $deletedBeforeDate
|
||||||
|
* @return ServiceResultError|ServiceResultSuccess
|
||||||
|
*/
|
||||||
|
public function fromStorage(Carbon $temporaryBeforeDate, Carbon $deletedBeforeDate): ServiceResultError|ServiceResultSuccess
|
||||||
|
{
|
||||||
|
$disk = config('storage.disk');
|
||||||
|
|
||||||
|
StorageModel::withTrashed()
|
||||||
|
->where(function (Builder $query) use($temporaryBeforeDate) {
|
||||||
|
$query->whereNull('morph_id')->where('updated_at', '<', $temporaryBeforeDate);
|
||||||
|
})->orWhere(function (Builder $query) use($deletedBeforeDate) {
|
||||||
|
$query->whereNotNull('deleted_at')->where('deleted_at', '<', $deletedBeforeDate);
|
||||||
|
})->chunkById(100, function ($items) use($disk) {
|
||||||
|
$deleteIds = [];
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$deleteIds[] = $item->id;
|
||||||
|
|
||||||
|
if (StorageSupport::disk($disk)->exists($item->file)) {
|
||||||
|
StorageSupport::disk($disk)->delete($item->file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StorageModel::withTrashed()->whereIn('id', $deleteIds)->forceDelete();
|
||||||
|
});
|
||||||
|
|
||||||
|
return $this->ok(__('Old Files deleted.'));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('storage', function (Blueprint $table) {
|
||||||
|
$table->dropIndex(['morph_id']);
|
||||||
|
$table->index(['morph_id', 'updated_at']);
|
||||||
|
$table->index(['deleted_at']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('storage', function (Blueprint $table) {
|
||||||
|
$table->dropIndex(['morph_id', 'updated_at']);
|
||||||
|
$table->dropIndex(['deleted_at']);
|
||||||
|
$table->index(['morph_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@ -267,5 +267,6 @@
|
|||||||
"Documentation successfully removed": "Documentation successfully removed",
|
"Documentation successfully removed": "Documentation successfully removed",
|
||||||
"Category successfully created": "Category successfully created",
|
"Category successfully created": "Category successfully created",
|
||||||
"Category updated successfully": "Category updated successfully",
|
"Category updated successfully": "Category updated successfully",
|
||||||
"Category successfully deleted": "Category successfully deleted"
|
"Category successfully deleted": "Category successfully deleted",
|
||||||
|
"Old Files deleted": "Old Files deleted"
|
||||||
}
|
}
|
||||||
|
@ -267,5 +267,6 @@
|
|||||||
"Documentation successfully removed": "Документация успешно удалена",
|
"Documentation successfully removed": "Документация успешно удалена",
|
||||||
"Category successfully created": "Категория успешно создана",
|
"Category successfully created": "Категория успешно создана",
|
||||||
"Category updated successfully": "Категория успешно обновлена",
|
"Category updated successfully": "Категория успешно обновлена",
|
||||||
"Category successfully deleted": "Категория успешно удалена"
|
"Category successfully deleted": "Категория успешно удалена",
|
||||||
|
"Old Files deleted": "Старые файлы удалены"
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use Illuminate\Support\Facades\Schedule;
|
||||||
|
|
||||||
|
$timezone = config('app.user_timezone');
|
||||||
|
|
||||||
|
Schedule::command(\App\Console\Commands\Files\DeleteOldFilesFromStorage::class)->timezone($timezone)->dailyAt('3:30');
|
||||||
|
@ -64,10 +64,12 @@ FROM BUILD AS PRODUCTION
|
|||||||
|
|
||||||
COPY --from=APP_BUILD_FOR_PRODUCTION /home/app /var/www/html
|
COPY --from=APP_BUILD_FOR_PRODUCTION /home/app /var/www/html
|
||||||
COPY docker/docker-entrypoint_prod.sh /home/unit/docker-entrypoint.sh
|
COPY docker/docker-entrypoint_prod.sh /home/unit/docker-entrypoint.sh
|
||||||
|
COPY docker/start.sh /usr/local/bin/start
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
RUN chmod 755 /home/unit/docker-entrypoint.sh
|
RUN chmod 755 /home/unit/docker-entrypoint.sh \
|
||||||
|
&& chmod 755 /usr/local/bin/start
|
||||||
|
|
||||||
STOPSIGNAL SIGTERM
|
STOPSIGNAL SIGTERM
|
||||||
|
|
||||||
@ -81,17 +83,19 @@ FROM BUILD AS DEVELOP
|
|||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
COPY docker/docker-entrypoint_dev.sh /home/unit/docker-entrypoint.sh
|
COPY docker/docker-entrypoint_dev.sh /home/unit/docker-entrypoint.sh
|
||||||
|
COPY docker/start.sh /usr/local/bin/start
|
||||||
|
|
||||||
STOPSIGNAL SIGTERM
|
STOPSIGNAL SIGTERM
|
||||||
|
|
||||||
RUN chmod 755 /home/unit/docker-entrypoint.sh \
|
RUN chmod 755 /home/unit/docker-entrypoint.sh \
|
||||||
|
&& chmod 755 /usr/local/bin/start \
|
||||||
&& apk --no-cache add git nodejs npm \
|
&& apk --no-cache add git nodejs npm \
|
||||||
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||||
|
|
||||||
ENTRYPOINT ["/home/unit/docker-entrypoint.sh"]
|
ENTRYPOINT ["/home/unit/docker-entrypoint.sh"]
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock", "--user", "unit", "--group", "unit"]
|
CMD ["/usr/local/bin/start"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
21
app/docker/start.sh
Executable file
21
app/docker/start.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
set -e
|
||||||
|
role=${CONTAINER_ROLE:-app}
|
||||||
|
if [ "$role" = "app" ]; then
|
||||||
|
exec unitd --no-daemon --control unix:/var/run/control.unit.sock --user unit --group unit
|
||||||
|
elif [ "$role" = "queue" ]; then
|
||||||
|
echo "Running the queue..."
|
||||||
|
while [ true ]
|
||||||
|
do
|
||||||
|
php /var/www/html/artisan queue:work --verbose --sleep=5 --tries=100 --backoff=10 --max-time=3600 --queue=high,normal,low,default
|
||||||
|
done
|
||||||
|
elif [ "$role" = "scheduler" ]; then
|
||||||
|
while [ true ]
|
||||||
|
do
|
||||||
|
php /var/www/html/artisan schedule:run --verbose --no-interaction &
|
||||||
|
sleep 60
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Could not match the container role \"$role\""
|
||||||
|
exit 1
|
||||||
|
fi
|
@ -17,6 +17,35 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
CONTAINER_ROLE: app
|
CONTAINER_ROLE: app
|
||||||
UNIT_SOURCE: '"172.16.0.0/12"'
|
UNIT_SOURCE: '"172.16.0.0/12"'
|
||||||
|
|
||||||
|
queue:
|
||||||
|
build:
|
||||||
|
context: app
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
target: PRODUCTION
|
||||||
|
# restart: always
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- app-redis
|
||||||
|
environment:
|
||||||
|
CONTAINER_ROLE: queue
|
||||||
|
volumes:
|
||||||
|
- ./app/application:/var/www/html
|
||||||
|
|
||||||
|
scheduler:
|
||||||
|
build:
|
||||||
|
context: app
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
target: PRODUCTION
|
||||||
|
# restart: always
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- app-redis
|
||||||
|
environment:
|
||||||
|
CONTAINER_ROLE: scheduler
|
||||||
|
volumes:
|
||||||
|
- ./app/application:/var/www/html
|
||||||
|
|
||||||
app-redis:
|
app-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
# restart: always
|
# restart: always
|
||||||
|
@ -13,13 +13,40 @@ services:
|
|||||||
- ${DOCKER_APP_PORT}:9000
|
- ${DOCKER_APP_PORT}:9000
|
||||||
volumes:
|
volumes:
|
||||||
- ./app/application:/var/www/html
|
- ./app/application:/var/www/html
|
||||||
|
|
||||||
|
queue:
|
||||||
|
build:
|
||||||
|
context: app
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
target: DEVELOP
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- app-redis
|
||||||
|
environment:
|
||||||
|
CONTAINER_ROLE: queue
|
||||||
|
volumes:
|
||||||
|
- ./app/application:/var/www/html
|
||||||
|
|
||||||
|
scheduler:
|
||||||
|
build:
|
||||||
|
context: app
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
target: DEVELOP
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- app-redis
|
||||||
|
environment:
|
||||||
|
CONTAINER_ROLE: scheduler
|
||||||
|
volumes:
|
||||||
|
- ./app/application:/var/www/html
|
||||||
|
|
||||||
app-redis:
|
app-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
volumes:
|
volumes:
|
||||||
- ./redis/data:/data
|
- ./redis/data:/data
|
||||||
|
|
||||||
captcha-app:
|
captcha-app:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
cap_drop:
|
cap_drop:
|
||||||
- ALL
|
- ALL
|
||||||
cap_add:
|
cap_add:
|
||||||
@ -31,10 +58,13 @@ services:
|
|||||||
- db
|
- db
|
||||||
- captcha-redis
|
- captcha-redis
|
||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
|
volumes:
|
||||||
|
- ./captcha-app/app/storage/app:/var/www/html/storage/app
|
||||||
|
- ./captcha-app/app/storage/logs:/var/www/html/storage/logs
|
||||||
ports:
|
ports:
|
||||||
- ${DOCKER_CAPTCHA_PORT}:9000
|
- ${DOCKER_CAPTCHA_PORT}:9000
|
||||||
captcha-queue:
|
captcha-queue:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@ -42,8 +72,11 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
CONTAINER_ROLE: queue
|
CONTAINER_ROLE: queue
|
||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
|
volumes:
|
||||||
|
- ./captcha-app/app/storage/app:/var/www/html/storage/app
|
||||||
|
- ./captcha-app/app/storage/logs:/var/www/html/storage/logs
|
||||||
captcha-reverb:
|
captcha-reverb:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@ -51,10 +84,13 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
CONTAINER_ROLE: websockets
|
CONTAINER_ROLE: websockets
|
||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
|
volumes:
|
||||||
|
- ./captcha-app/app/storage/app:/var/www/html/storage/app
|
||||||
|
- ./captcha-app/app/storage/logs:/var/www/html/storage/logs
|
||||||
ports:
|
ports:
|
||||||
- ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000
|
- ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000
|
||||||
captcha-scheduler:
|
captcha-scheduler:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@ -62,6 +98,9 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
CONTAINER_ROLE: scheduler
|
CONTAINER_ROLE: scheduler
|
||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
|
volumes:
|
||||||
|
- ./captcha-app/app/storage/app:/var/www/html/storage/app
|
||||||
|
- ./captcha-app/app/storage/logs:/var/www/html/storage/logs
|
||||||
captcha-redis:
|
captcha-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
volumes:
|
volumes:
|
||||||
|
Loading…
Reference in New Issue
Block a user