Compare commits

...

13 Commits

Author SHA1 Message Date
Brock H Caldwell
445224d368 fix: error twig template 2025-11-05 11:23:57 -06:00
Brock H Caldwell
9a660279be fix: sentry 2025-11-05 00:12:32 -06:00
Brock H Caldwell
c1adedf74d feat: sentry integration 2025-11-04 23:53:31 -06:00
Brock H Caldwell
9a0e7fce26 fix(Scheduler): copy from app image 2025-11-04 20:08:43 -06:00
Brock H Caldwell
d90b4d7863 fix(Worker): pulls /app from app image again 2025-11-04 20:03:27 -06:00
Brock H Caldwell
2860d2e949 fix(Worker): installs more php mods 2025-11-04 19:27:50 -06:00
Brock H Caldwell
ad2bbfd48c fix: install php-dom 2025-11-04 14:48:39 -06:00
Brock H Caldwell
5e306c6740 fix: adds php84-xml 2025-11-04 14:24:42 -06:00
Brock H Caldwell
56129de3f9 fix: uses correct command 2025-11-04 13:50:27 -06:00
Brock H Caldwell
22b2b46da5 fix: disable multiplatform builds 2025-11-04 13:23:35 -06:00
Brock H Caldwell
7cc48ffc73 chore: docker cleanup/refactoring 2025-11-04 12:55:19 -06:00
Brock H Caldwell
adb79db8f5 feat: allows configuring the worker service and processes via command options and env vars 2025-11-04 12:19:37 -06:00
Brock H Caldwell
9ca87af938 wip: generates supervisord config at runtime 2025-11-04 09:54:41 -06:00
24 changed files with 982 additions and 128 deletions

View File

@@ -12,3 +12,4 @@ phpstan.dist.neon
phpunit.dist.xml
nomad.deploy.hcl
deployment.properties
var/download/*

4
.env
View File

@@ -58,3 +58,7 @@ OIDC_BYPASS_FORM_LOGIN=false
NOTIFICATION_TRANSPORT=
NTFY_DSN=
###> sentry/sentry-symfony ###
SENTRY_DSN=
###< sentry/sentry-symfony ###

View File

@@ -1,14 +1,22 @@
# torsearch-app is built from this base
export APP_FRANKENPHP_TAG=php8.4
docker buildx build --platform=linux/amd64 -f docker/Dockerfile.base.app -t code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base:latest --build-arg "FRANKENPHP_TAG=${APP_FRANKENPHP_TAG}" .
#docker buildx build --platform=linux/amd64,linux/arm64 -f docker/Dockerfile.base.app -t code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base:latest --build-arg "FRANKENPHP_TAG=${APP_FRANKENPHP_TAG}" .
docker build -f docker/Dockerfile.base.app -t code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base:latest --build-arg "FRANKENPHP_TAG=${APP_FRANKENPHP_TAG}" .
docker push code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG}
docker push code.caldwell.digital/home/torsearch-base:latest
# torsearch-worker & torsearch-scheduler are built from this base
export WORKER_FRANKENPHP_TAG=php8.4-alpine
docker buildx build --platform=linux/amd64 -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base-worker:latest --build-arg "FRANKENPHP_TAG=${WORKER_FRANKENPHP_TAG}" .
#docker buildx build --platform=linux/amd64,linux/arm64 -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base-worker:latest --build-arg "FRANKENPHP_TAG=${WORKER_FRANKENPHP_TAG}" .
docker build -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base-worker:latest --build-arg "FRANKENPHP_TAG=${WORKER_FRANKENPHP_TAG}" .
docker push code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG}
docker push code.caldwell.digital/home/torsearch-base-worker:latest
# torsearch-worker-supervisord
export ALPINE_VERSION=3.22
#docker buildx build --platform=linux/amd64,linux/arm64 -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker-supervisord:latest --build-arg "ALPINE_VERSION=${ALPINE_VERSION}" .
docker build -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker-supervisord:latest --build-arg "ALPINE_VERSION=${ALPINE_VERSION}" .
docker push code.caldwell.digital/home/torsearch-base-worker-supervisord:latest

View File

@@ -33,12 +33,9 @@ services:
worker:
# build:
# dockerfile: docker/Dockerfile.base.worker
# context: .
# args:
# FRANKENPHP_TAG: php8.4-alpine
image: torsearch-alpine
build:
dockerfile: docker/Dockerfile.worker
context: .
restart: unless-stopped
volumes:
- $PWD:/app
@@ -46,22 +43,19 @@ services:
tty: true
environment:
TZ: America/Chicago
# command: php /app/bin/console messenger:consume async --time-limit=3600 -vv
scheduler:
build:
dockerfile: docker/Dockerfile.base.worker
dockerfile: docker/Dockerfile.scheduler
context: .
args:
FRANKENPHP_TAG: php8.4-alpine
restart: unless-stopped
volumes:
- $PWD:/app
- $PWD/var/download:/var/download
tty: true
environment:
TZ: America/Chicago
command: php /app/bin/console messenger:consume scheduler_monitor -vv
tty: true
WORKER_MONITOR: 2
redis:

View File

@@ -29,6 +29,7 @@
"phpstan/phpdoc-parser": "^2.1",
"predis/predis": "^2.4",
"runtime/frankenphp-symfony": "^0.2.0",
"sentry/sentry-symfony": "^5.6",
"spatie/icalendar-generator": "^3.0",
"spomky-labs/pwa-bundle": "^1.2",
"stof/doctrine-extensions-bundle": "^1.14",
@@ -46,6 +47,7 @@
"symfony/mailer": "7.3.*",
"symfony/mercure-bundle": "^0.3.9",
"symfony/messenger": "7.3.*",
"symfony/monolog-bundle": "^3.10",
"symfony/notifier": "7.3.*",
"symfony/ntfy-notifier": "7.3.*",
"symfony/object-mapper": "7.3.*",

605
composer.lock generated
View File

@@ -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": "c133ccd27ac6a41256bdc69129c16546",
"content-hash": "952def2c32d975032ac0061e5aa37319",
"packages": [
{
"name": "1tomany/rich-bundle",
@@ -2552,6 +2552,66 @@
],
"time": "2025-03-27T12:30:47+00:00"
},
{
"name": "jean85/pretty-package-versions",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
"shasum": ""
},
"require": {
"composer-runtime-api": "^2.1.0",
"php": "^7.4|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.2",
"jean85/composer-provided-replaced-stub-package": "^1.0",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^7.5|^8.5|^9.6",
"rector/rector": "^2.0",
"vimeo/psalm": "^4.3 || ^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Jean85\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alessandro Lai",
"email": "alessandro.lai85@gmail.com"
}
],
"description": "A library to get pretty versions strings of installed dependencies",
"keywords": [
"composer",
"package",
"release",
"versions"
],
"support": {
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
},
"time": "2025-03-19T14:43:43+00:00"
},
{
"name": "lcobucci/jwt",
"version": "5.5.0",
@@ -2681,6 +2741,109 @@
},
"time": "2025-02-06T08:48:15+00:00"
},
{
"name": "monolog/monolog",
"version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6",
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6",
"shasum": ""
},
"require": {
"php": ">=8.1",
"psr/log": "^2.0 || ^3.0"
},
"provide": {
"psr/log-implementation": "3.0.0"
},
"require-dev": {
"aws/aws-sdk-php": "^3.0",
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
"ext-json": "*",
"graylog2/gelf-php": "^1.4.2 || ^2.0",
"guzzlehttp/guzzle": "^7.4.5",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8",
"php-amqplib/php-amqplib": "~2.4 || ^3",
"php-console/php-console": "^3.1.8",
"phpstan/phpstan": "^2",
"phpstan/phpstan-deprecation-rules": "^2",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "^10.5.17 || ^11.0.7",
"predis/predis": "^1.1 || ^2",
"rollbar/rollbar": "^4.0",
"ruflin/elastica": "^7 || ^8",
"symfony/mailer": "^5.4 || ^6",
"symfony/mime": "^5.4 || ^6"
},
"suggest": {
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
"ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
"ext-mbstring": "Allow to work properly with unicode symbols",
"ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
"ext-openssl": "Required to send log messages using SSL",
"ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Monolog\\": "src/Monolog"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "https://seld.be"
}
],
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
"homepage": "https://github.com/Seldaek/monolog",
"keywords": [
"log",
"logging",
"psr-3"
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/3.9.0"
},
"funding": [
{
"url": "https://github.com/Seldaek",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
"type": "tidelift"
}
],
"time": "2025-03-24T10:02:05+00:00"
},
{
"name": "nesbot/carbon",
"version": "3.10.0",
@@ -4757,6 +4920,196 @@
],
"time": "2023-12-12T12:06:11+00:00"
},
{
"name": "sentry/sentry",
"version": "4.17.1",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
"reference": "5c696b8de57e841a2bf3b6f6eecfd99acfdda80c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/5c696b8de57e841a2bf3b6f6eecfd99acfdda80c",
"reference": "5c696b8de57e841a2bf3b6f6eecfd99acfdda80c",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
"jean85/pretty-package-versions": "^1.5|^2.0.4",
"php": "^7.2|^8.0",
"psr/log": "^1.0|^2.0|^3.0",
"symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0"
},
"conflict": {
"raven/raven": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.4",
"guzzlehttp/promises": "^2.0.3",
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
"monolog/monolog": "^1.6|^2.0|^3.0",
"phpbench/phpbench": "^1.0",
"phpstan/phpstan": "^1.3",
"phpunit/phpunit": "^8.5|^9.6",
"vimeo/psalm": "^4.17"
},
"suggest": {
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
},
"type": "library",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Sentry\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sentry",
"email": "accounts@sentry.io"
}
],
"description": "PHP SDK for Sentry (http://sentry.io)",
"homepage": "http://sentry.io",
"keywords": [
"crash-reporting",
"crash-reports",
"error-handler",
"error-monitoring",
"log",
"logging",
"profiling",
"sentry",
"tracing"
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
"source": "https://github.com/getsentry/sentry-php/tree/4.17.1"
},
"funding": [
{
"url": "https://sentry.io/",
"type": "custom"
},
{
"url": "https://sentry.io/pricing/",
"type": "custom"
}
],
"time": "2025-10-23T15:19:24+00:00"
},
{
"name": "sentry/sentry-symfony",
"version": "5.6.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-symfony.git",
"reference": "9867751f5091b55d7e3a223f48d88e228132e073"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-symfony/zipball/9867751f5091b55d7e3a223f48d88e228132e073",
"reference": "9867751f5091b55d7e3a223f48d88e228132e073",
"shasum": ""
},
"require": {
"guzzlehttp/psr7": "^2.1.1",
"jean85/pretty-package-versions": "^1.5||^2.0",
"php": "^7.2||^8.0",
"sentry/sentry": "^4.16.0",
"symfony/cache-contracts": "^1.1||^2.4||^3.0",
"symfony/config": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/console": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/dependency-injection": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/event-dispatcher": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/http-kernel": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/polyfill-php80": "^1.22",
"symfony/psr-http-message-bridge": "^1.2||^2.0||^6.4||^7.0"
},
"require-dev": {
"doctrine/dbal": "^2.13||^3.3||^4.0",
"doctrine/doctrine-bundle": "^2.6",
"friendsofphp/php-cs-fixer": "^2.19||^3.40",
"masterminds/html5": "^2.8",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "1.12.5",
"phpstan/phpstan-phpunit": "1.4.0",
"phpstan/phpstan-symfony": "1.4.10",
"phpunit/phpunit": "^8.5.40||^9.6.21",
"symfony/browser-kit": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/cache": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/dom-crawler": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/framework-bundle": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/http-client": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/messenger": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/monolog-bundle": "^3.4",
"symfony/phpunit-bridge": "^5.2.6||^6.0||^7.0",
"symfony/process": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/security-core": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/security-http": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/twig-bundle": "^4.4.20||^5.0.11||^6.0||^7.0",
"symfony/yaml": "^4.4.20||^5.0.11||^6.0||^7.0",
"vimeo/psalm": "^4.3||^5.16.0"
},
"suggest": {
"doctrine/doctrine-bundle": "Allow distributed tracing of database queries using Sentry.",
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler.",
"symfony/cache": "Allow distributed tracing of cache pools using Sentry.",
"symfony/twig-bundle": "Allow distributed tracing of Twig template rendering using Sentry."
},
"type": "symfony-bundle",
"autoload": {
"files": [
"src/aliases.php"
],
"psr-4": {
"Sentry\\SentryBundle\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sentry",
"email": "accounts@sentry.io"
}
],
"description": "Symfony integration for Sentry (http://getsentry.com)",
"homepage": "http://getsentry.com",
"keywords": [
"errors",
"logging",
"sentry",
"symfony"
],
"support": {
"issues": "https://github.com/getsentry/sentry-symfony/issues",
"source": "https://github.com/getsentry/sentry-symfony/tree/5.6.0"
},
"funding": [
{
"url": "https://sentry.io/",
"type": "custom"
},
{
"url": "https://sentry.io/pricing/",
"type": "custom"
}
],
"time": "2025-09-24T13:41:01+00:00"
},
{
"name": "spatie/icalendar-generator",
"version": "3.0.0",
@@ -7637,6 +7990,169 @@
],
"time": "2025-02-19T08:51:26+00:00"
},
{
"name": "symfony/monolog-bridge",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/monolog-bridge.git",
"reference": "c66a65049c75f3ddf03d73c8c9ed61405779ce47"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/c66a65049c75f3ddf03d73c8c9ed61405779ce47",
"reference": "c66a65049c75f3ddf03d73c8c9ed61405779ce47",
"shasum": ""
},
"require": {
"monolog/monolog": "^3",
"php": ">=8.2",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
"symfony/console": "<6.4",
"symfony/http-foundation": "<6.4",
"symfony/security-core": "<6.4"
},
"require-dev": {
"symfony/console": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/mailer": "^6.4|^7.0",
"symfony/messenger": "^6.4|^7.0",
"symfony/mime": "^6.4|^7.0",
"symfony/security-core": "^6.4|^7.0",
"symfony/var-dumper": "^6.4|^7.0"
},
"type": "symfony-bridge",
"autoload": {
"psr-4": {
"Symfony\\Bridge\\Monolog\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides integration for Monolog with various Symfony components",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/monolog-bridge/tree/v7.3.5"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-10-14T19:16:15+00:00"
},
{
"name": "symfony/monolog-bundle",
"version": "v3.10.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/monolog-bundle.git",
"reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
"reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
"shasum": ""
},
"require": {
"monolog/monolog": "^1.25.1 || ^2.0 || ^3.0",
"php": ">=7.2.5",
"symfony/config": "^5.4 || ^6.0 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
"symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0"
},
"require-dev": {
"symfony/console": "^5.4 || ^6.0 || ^7.0",
"symfony/phpunit-bridge": "^6.3 || ^7.0",
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Bundle\\MonologBundle\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony MonologBundle",
"homepage": "https://symfony.com",
"keywords": [
"log",
"logging"
],
"support": {
"issues": "https://github.com/symfony/monolog-bundle/issues",
"source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-11-06T17:08:13+00:00"
},
{
"name": "symfony/notifier",
"version": "v7.3.0",
@@ -8777,6 +9293,89 @@
],
"time": "2025-04-04T13:12:05+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
"version": "v7.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/psr-http-message-bridge.git",
"reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f",
"reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/http-message": "^1.0|^2.0",
"symfony/http-foundation": "^6.4|^7.0"
},
"conflict": {
"php-http/discovery": "<1.15",
"symfony/http-kernel": "<6.4"
},
"require-dev": {
"nyholm/psr7": "^1.1",
"php-http/discovery": "^1.15",
"psr/log": "^1.1.4|^2|^3",
"symfony/browser-kit": "^6.4|^7.0",
"symfony/config": "^6.4|^7.0",
"symfony/event-dispatcher": "^6.4|^7.0",
"symfony/framework-bundle": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0"
},
"type": "symfony-bridge",
"autoload": {
"psr-4": {
"Symfony\\Bridge\\PsrHttpMessage\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "PSR HTTP message bridge",
"homepage": "https://symfony.com",
"keywords": [
"http",
"http-message",
"psr-17",
"psr-7"
],
"support": {
"source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-26T08:57:56+00:00"
},
{
"name": "symfony/routing",
"version": "v7.3.0",
@@ -13398,7 +13997,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
@@ -13406,7 +14005,7 @@
"ext-ctype": "*",
"ext-iconv": "*"
},
"platform-dev": [],
"platform-dev": {},
"platform-overrides": {
"php": "8.4"
},

View File

@@ -23,4 +23,6 @@ return [
SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true],
Drenso\OidcBundle\DrensoOidcBundle::class => ['all' => true],
SpomkyLabs\PwaBundle\SpomkyLabsPwaBundle::class => ['all' => true],
Sentry\SentryBundle\SentryBundle::class => ['prod' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
];

View File

@@ -0,0 +1,63 @@
monolog:
channels:
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
when@dev:
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
# type: firephp
# level: info
#chromephp:
# type: chromephp
# level: info
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]
when@test:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
channels: ["!event"]
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
when@prod:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
channels: ["!deprecation"]
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
nested:
type: stream
path: php://stderr
level: debug
formatter: monolog.formatter.json
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
deprecation:
type: stream
channels: [deprecation]
path: php://stderr
formatter: monolog.formatter.json

View File

@@ -0,0 +1,34 @@
when@prod:
sentry:
register_error_listener: true # Disables the ErrorListener to avoid duplicated log in sentry
register_error_handler: true # Disables the ErrorListener, ExceptionListener and FatalErrorListener integrations of the base PHP SDK
tracing:
enabled: true
dbal: # DB queries
enabled: true
cache: # cache pools
enabled: true
twig: # templating engine
enabled: true
services:
# (Optionally) Configure the breadcrumb handler as a service (needed for the breadcrumb Monolog handler)
Sentry\Monolog\BreadcrumbHandler:
arguments:
- '@Sentry\State\HubInterface'
- !php/const Monolog\Logger::INFO # Configures the level of messages to capture as breadcrumbs
monolog:
handlers:
# (Optionally) Register the breadcrumb handler as a Monolog handler
sentry_breadcrumbs:
type: service
name: sentry_breadcrumbs
id: Sentry\Monolog\BreadcrumbHandler
# Register the handler as a Monolog handler to capture messages as events
sentry:
type: sentry
level: !php/const Monolog\Logger::ERROR # Configures the level of messages to capture as events
hub_id: Sentry\State\HubInterface
fill_extra_context: true # Enables sending monolog context to Sentry
process_psr_3_messages: false # Disables the resolution of PSR-3 placeholders in reported messages

View File

@@ -13,8 +13,6 @@ services:
- /mnt/media/downloads/tvshows:/var/download/tvshows
- mercure_data:/data
- mercure_config:/config
depends_on:
- database
worker:
@@ -22,36 +20,21 @@ services:
volumes:
- /mnt/media/downloads/movies:/var/download/movies
- /mnt/media/downloads/tvshows:/var/download/tvshows
restart: always
# command: -vv --time-limit=3600 --limit=10
deploy:
replicas: 2
depends_on:
- app
#
# scheduler:
# image: registry.caldwell.digital/home/torsearch-scheduler:${TAG}
# volumes:
# - /mnt/media/downloads/movies:/var/download/movies
# - /mnt/media/downloads/tvshows:/var/download/tvshows
# restart: always
# command: -vv
# depends_on:
# - app
redis:
image: redis:latest
scheduler:
image: registry.caldwell.digital/home/torsearch-scheduler:${TAG}
volumes:
- redis_data:/data
command: redis-server --maxmemory 512MB
restart: unless-stopped
- /mnt/media/downloads/movies:/var/download/movies
- /mnt/media/downloads/tvshows:/var/download/tvshows
depends_on:
- app
volumes:
mysql:
mercure_config:
mercure_data:
redis_data:

View File

@@ -1,19 +1,40 @@
ARG FRANKENPHP_TAG
#####
# This version of Torsearch runs the scheduler, downloader, and worker
# in a single container. Each process is managerd by supervisord
# and can be configured via environment variables and more
# than one of these containers cans till be run.
#####
ARG ALPINE_VERSION="3.22"
FROM alpine:${ALPINE_VERSION} AS build_stage
FROM dunglas/frankenphp:${FRANKENPHP_TAG}
RUN apk add --no-cache \
curl \
php84 \
php84-ctype \
php84-curl \
php84-dom \
php84-fileinfo \
php84-fpm \
php84-gd \
php84-mbstring \
php84-mysqli \
php84-opcache \
php84-openssl \
php84-pdo_mysql \
php84-tokenizer \
php84-xml \
supervisor
ENV SERVER_NAME=":80"
ENV CADDY_GLOBAL_OPTIONS="auto_https off"
ENV APP_RUNTIME="Runtime\\FrankenPhpSymfony\\Runtime"
RUN ln -s /usr/bin/php84 /usr/bin/php
ARG APP_VERSION="0.dev"
ENV APP_VERSION="${APP_VERSION}"
RUN mkdir -p /etc/supervisor/conf.d
RUN install-php-extensions \
pdo_mysql \
gd \
intl \
zip \
opcache
# We start supervisord and supervisord starts
# respective service in the configuration file.
ENTRYPOINT ["/app/bin/console", "init:worker"]
# Message transports can be enabled by passing them as command options.
# Inlcluding a number with the option will start that amount of processes
# for the transport. Not supplying a number will default to 1.
# --download --monitor OR --download 2 --monitor
RUN apk add --no-cache wget

View File

@@ -1,10 +1,24 @@
FROM code.caldwell.digital/home/torsearch-base-worker:php8.4-alpine
###
# This version of Torsearch can run the scheduler, downloader, and
# worker in one container. Each process is managerd by supervisord
# and can be configured via environment variables, and more than
# one of these containers can still be run.
###
ARG APP_VERSION="0.0.0-dev"
ENV APP_VERSION="${APP_VERSION}"
# Default to latest, but should pass in a version
ARG APP_VERSION="latest"
COPY . /app
# Set aside the actual app image so we can copy the app from there
FROM code.caldwell.digital/home/torsearch-app:${APP_VERSION} AS app_image
ENTRYPOINT [ "php", "/app/bin/console", "messenger:consume", "scheduler_monitor" ]
# Start with our base worker image
FROM code.caldwell.digital/home/torsearch-base-worker-supervisord:latest
HEALTHCHECK --interval=3s --timeout=3s --retries=10 CMD return 0
# Set the APP_VERSION in the image
ENV APP_VERSION=${APP_VERSION}
# Copy the actual application code from the previously built app
COPY --chown=1000:1000 --from=app_image /app /app
# To retain backwards compatibility, default to async & download transports
CMD [ "--monitor" ]

View File

@@ -1,40 +1,24 @@
###
# This version of Torsearch runs the scheduler, downloader, and worker
# in this one container. Each process is managerd by supervisord
# and can be configured via environment variables and more
# than one of these containers cans till be run.
# This version of Torsearch can run the scheduler, downloader, and
# worker in one container. Each process is managerd by supervisord
# and can be configured via environment variables, and more than
# one of these containers can still be run.
###
# Default to latest, but should pass in a version
ARG APP_VERSION="latest"
FROM code.caldwell.digital/home/torsearch-app:${APP_VERSION} AS base_image
# Set aside the actual app image so we can copy the app from there
FROM code.caldwell.digital/home/torsearch-app:${APP_VERSION} AS app_image
# Start with our base worker image
FROM code.caldwell.digital/home/torsearch-base-worker-supervisord:latest
FROM alpine:3.22 AS build_stage
# Set the APP_VERSION in the image
ENV APP_VERSION=${APP_VERSION}
COPY --from=base_image --chown=1000:1000 /app /app
# Copy the actual application code from the previously built app
COPY --chown=1000:1000 --from=app_image /app /app
RUN apk add --no-cache \
curl \
nginx \
php84 \
php84-ctype \
php84-curl \
php84-dom \
php84-fileinfo \
php84-fpm \
php84-gd \
php84-mbstring \
php84-mysqli \
php84-opcache \
php84-openssl \
php84-pdo_mysql \
php84-tokenizer \
supervisor
RUN ln -s /usr/bin/php84 /usr/bin/php
COPY docker/worker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# We start supervisord and supervisord starts
# respective service in the configuration file.
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
# To retain backwards compatibility, default to async & download transports
CMD [ "--async", "--download" ]

10
docker/worker/async.conf Normal file
View File

@@ -0,0 +1,10 @@
[program:torsearch-worker]
command=/app/bin/console messenger:consume async -vv --time-limit 3600
numprocs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d

View File

@@ -0,0 +1,10 @@
[program:torsearch-downloader]
command=/app/bin/console messenger:consume download -vv --time-limit 3600
numprocs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d

View File

@@ -0,0 +1,10 @@
[program:torsearch-scheduler]
command=/app/bin/console messenger:consume scheduler_monitor monitor -vv --time-limit 21600
numprocs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d

View File

@@ -3,36 +3,3 @@ nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=/run/supervisord.pid
[program:torsearch-worker]
command=/app/bin/console messenger:consume async -vv --time-limit 3600
numprocs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d
[program:torsearch-worker]
command=/app/bin/console messenger:consume download -vv --time-limit 3600
numprocs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d
[program:torsearch-scheduler]
command=/app/bin/console messenger:consume scheduler_monitor monitor -vv --time-limit 21600
numprocs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d

View File

@@ -0,0 +1,90 @@
<?php
namespace App\Base\Framework\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Twig\Environment;
class InitWorker extends Command
{
public function __construct(
private Environment $twig,
) {
parent::__construct();
}
protected function configure(): void
{
$this
->setName('init:worker')
->addOption('async', null, InputOption::VALUE_OPTIONAL, 'Run the async worker.',false)
->addOption('download', null, InputOption::VALUE_OPTIONAL, 'Run the download worker.', false)
->addOption('monitor', null, InputOption::VALUE_OPTIONAL, 'Run the monitor worker.', false)
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$configFile = $this->twig->render("config/supervisord.conf.twig", []);
if ($this->optionExists($input, $output, 'async')) {
$configFile .= $this->twig->render("config/async.conf.twig", [
'replicas' => $this->getOptionValue('async', $input),
]) . "\n\n";
}
if ($this->optionExists($input, $output, 'download')) {
$configFile .= $this->twig->render("config/download.conf.twig", [
'replicas' => $this->getOptionValue('download', $input),
]). "\n\n";
}
if ($this->optionExists($input, $output, 'monitor')) {
$configFile .= $this->twig->render("config/monitor.conf.twig", [
'replicas' => $this->getOptionValue('monitor', $input),
]). "\n\n";
}
if ("" !== $configFile) {
$output->writeln("[init:worker] Writing /etc/supervisor/conf.d/supervisord.conf");
file_put_contents("/etc/supervisor/conf.d/supervisord.conf", $configFile);
$output->writeln("[init:worker] Starting supervisord");
shell_exec("/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf");
return Command::SUCCESS;
}
$output->writeln("[init:worker] No workers selected. Exiting.");
return Command::FAILURE;
}
private function optionExists(InputInterface $input, OutputInterface $output, string $option): bool
{
if ($input->getOption($option) !== false) {
$value = $input->getOption($option) ?? 1;
$output->writeln("[init:worker] transport: $option // $value // input var");;
return true;
}
$optionKey = 'WORKER_' . strtoupper($option);
if (array_key_exists($optionKey, $_SERVER) && $_SERVER[$optionKey] !== null && $_SERVER[$optionKey] !== '') {
$output->writeln("[init:worker] transport: $option // $_SERVER[$optionKey] // env var");
return true;
}
return false;
}
private function getOptionValue(string $option, InputInterface $input): int
{
if ($input->getOption($option) !== false) {
return $input->getOption($option) ?? 1;
}
$optionKey = 'WORKER_' . strtoupper($option);
return $_SERVER[$optionKey];
}
}

View File

@@ -101,6 +101,18 @@
"bin/phpunit"
]
},
"sentry/sentry-symfony": {
"version": "5.6",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "5.0",
"ref": "b6cb4b34429dadecd7187852123be19d628fa37a"
},
"files": [
"config/packages/sentry.yaml"
]
},
"spomky-labs/pwa-bundle": {
"version": "1.2.5"
},
@@ -232,6 +244,18 @@
"config/packages/messenger.yaml"
]
},
"symfony/monolog-bundle": {
"version": "3.10",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.7",
"ref": "f5f5f3e4c23f5349796b7de587f19c51e7104299"
},
"files": [
"config/packages/monolog.yaml"
]
},
"symfony/notifier": {
"version": "7.3",
"recipe": {

View File

@@ -1,11 +1,10 @@
{% extends 'bare.html.twig' %}
{% block body %}
<h2 class="px-4 py-4 text-3xl font-extrabold text-orange-500">{{ }}</h2>
<h2 class="px-4 py-4 text-3xl font-extrabold text-orange-500">500</h2>
<div class="flex flex-col bg-orange-500/50 p-4 rounded-lg gap-4 w-full md:w-[420px] border-orange-500 border-2 text-gray-50 animate-fade">
<div class="flex flex-col m-0 text-center">
<h3 class="text-2xl text-bold text-center text-gray-50">Oh crap!</h3>
<small>(or is it?)</small>
</div>
<p class="mb-2">There are many things I'm capable of, but this ain't one of 'em!</p>
<pre class="bg-gray-800 text-white p-4 rounded-md overflow-x-auto">

View File

@@ -0,0 +1,10 @@
[program:torsearch-worker]
command=/app/bin/console messenger:consume async -vv --time-limit 3600
numprocs={{ replicas|default(1) }}
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d

View File

@@ -0,0 +1,10 @@
[program:torsearch-downloader]
command=/app/bin/console messenger:consume download -vv --time-limit 3600
numprocs={{ replicas|default(1) }}
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d

View File

@@ -0,0 +1,10 @@
[program:torsearch-scheduler]
command=/app/bin/console messenger:consume scheduler_monitor monitor -vv --time-limit 21600
numprocs={{ replicas|default(1) }}
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=true
startretries=3
process_name=%(program_name)s_%(process_num)02d

View File

@@ -0,0 +1,5 @@
[supervisord]
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=/run/supervisord.pid