|
@@ -9,6 +9,11 @@ use App\Application\Admin\MeController;
|
|
|
use App\Application\Admin\ReportersController;
|
|
use App\Application\Admin\ReportersController;
|
|
|
use App\Application\Admin\TokensController;
|
|
use App\Application\Admin\TokensController;
|
|
|
use App\Application\Auth\AuthController;
|
|
use App\Application\Auth\AuthController;
|
|
|
|
|
+use App\Application\Internal\JobsController;
|
|
|
|
|
+use App\Application\Jobs\CleanupAuditJob;
|
|
|
|
|
+use App\Application\Jobs\EnrichPendingJob;
|
|
|
|
|
+use App\Application\Jobs\RecomputeScoresJob;
|
|
|
|
|
+use App\Application\Jobs\TickJob;
|
|
|
use App\Application\Public\ReportController;
|
|
use App\Application\Public\ReportController;
|
|
|
use App\Domain\Auth\Role;
|
|
use App\Domain\Auth\Role;
|
|
|
use App\Domain\Auth\TokenHasher;
|
|
use App\Domain\Auth\TokenHasher;
|
|
@@ -25,9 +30,15 @@ use App\Infrastructure\Consumer\ConsumerRepository;
|
|
|
use App\Infrastructure\Db\ConnectionFactory;
|
|
use App\Infrastructure\Db\ConnectionFactory;
|
|
|
use App\Infrastructure\Http\JsonErrorHandler;
|
|
use App\Infrastructure\Http\JsonErrorHandler;
|
|
|
use App\Infrastructure\Http\Middleware\ImpersonationMiddleware;
|
|
use App\Infrastructure\Http\Middleware\ImpersonationMiddleware;
|
|
|
|
|
+use App\Infrastructure\Http\Middleware\InternalNetworkMiddleware;
|
|
|
|
|
+use App\Infrastructure\Http\Middleware\InternalTokenMiddleware;
|
|
|
use App\Infrastructure\Http\Middleware\RateLimitMiddleware;
|
|
use App\Infrastructure\Http\Middleware\RateLimitMiddleware;
|
|
|
use App\Infrastructure\Http\Middleware\TokenAuthenticationMiddleware;
|
|
use App\Infrastructure\Http\Middleware\TokenAuthenticationMiddleware;
|
|
|
use App\Infrastructure\Http\RateLimiter;
|
|
use App\Infrastructure\Http\RateLimiter;
|
|
|
|
|
+use App\Infrastructure\Jobs\JobLockRepository;
|
|
|
|
|
+use App\Infrastructure\Jobs\JobRegistry;
|
|
|
|
|
+use App\Infrastructure\Jobs\JobRunner;
|
|
|
|
|
+use App\Infrastructure\Jobs\JobRunRepository;
|
|
|
use App\Infrastructure\Reporter\ReporterRepository;
|
|
use App\Infrastructure\Reporter\ReporterRepository;
|
|
|
use App\Infrastructure\Reputation\IpScoreRepository;
|
|
use App\Infrastructure\Reputation\IpScoreRepository;
|
|
|
use App\Infrastructure\Reputation\ReportRepository;
|
|
use App\Infrastructure\Reputation\ReportRepository;
|
|
@@ -75,6 +86,10 @@ final class Container
|
|
|
'settings.oidc_default_role' => $settings['oidc_default_role'] ?? Role::Viewer,
|
|
'settings.oidc_default_role' => $settings['oidc_default_role'] ?? Role::Viewer,
|
|
|
'settings.score_hard_cutoff_days' => (int) ($settings['score_hard_cutoff_days'] ?? 365),
|
|
'settings.score_hard_cutoff_days' => (int) ($settings['score_hard_cutoff_days'] ?? 365),
|
|
|
'settings.rate_limit_per_second' => (int) ($settings['rate_limit_per_second'] ?? 60),
|
|
'settings.rate_limit_per_second' => (int) ($settings['rate_limit_per_second'] ?? 60),
|
|
|
|
|
+ 'settings.internal_job_token' => (string) ($settings['internal_job_token'] ?? ''),
|
|
|
|
|
+ 'settings.job_recompute_max_runtime_seconds' => (int) ($settings['job_recompute_max_runtime_seconds'] ?? 240),
|
|
|
|
|
+ 'settings.job_recompute_max_rows_per_tick' => (int) ($settings['job_recompute_max_rows_per_tick'] ?? 5000),
|
|
|
|
|
+ 'settings.job_audit_retention_days' => (int) ($settings['job_audit_retention_days'] ?? 180),
|
|
|
ConnectionFactory::class => factory(static function (ContainerInterface $c): ConnectionFactory {
|
|
ConnectionFactory::class => factory(static function (ContainerInterface $c): ConnectionFactory {
|
|
|
/** @var array{driver: string, sqlite_path: string, mysql_host: string, mysql_port: int, mysql_database: string, mysql_username: string, mysql_password: string} $db */
|
|
/** @var array{driver: string, sqlite_path: string, mysql_host: string, mysql_port: int, mysql_database: string, mysql_username: string, mysql_password: string} $db */
|
|
|
$db = $c->get('settings.db');
|
|
$db = $c->get('settings.db');
|
|
@@ -134,6 +149,84 @@ final class Container
|
|
|
return new RateLimiter($clock, (float) $perSecond, (float) ($perSecond * 2));
|
|
return new RateLimiter($clock, (float) $perSecond, (float) ($perSecond * 2));
|
|
|
}),
|
|
}),
|
|
|
RateLimitMiddleware::class => autowire(),
|
|
RateLimitMiddleware::class => autowire(),
|
|
|
|
|
+ JobLockRepository::class => autowire(),
|
|
|
|
|
+ JobRunRepository::class => autowire(),
|
|
|
|
|
+ JobRunner::class => factory(static function (ContainerInterface $c): JobRunner {
|
|
|
|
|
+ /** @var JobLockRepository $locks */
|
|
|
|
|
+ $locks = $c->get(JobLockRepository::class);
|
|
|
|
|
+ /** @var JobRunRepository $runs */
|
|
|
|
|
+ $runs = $c->get(JobRunRepository::class);
|
|
|
|
|
+ /** @var Clock $clock */
|
|
|
|
|
+ $clock = $c->get(Clock::class);
|
|
|
|
|
+ /** @var LoggerInterface $logger */
|
|
|
|
|
+ $logger = $c->get(LoggerInterface::class);
|
|
|
|
|
+
|
|
|
|
|
+ return new JobRunner($locks, $runs, $clock, $logger);
|
|
|
|
|
+ }),
|
|
|
|
|
+ RecomputeScoresJob::class => factory(static function (ContainerInterface $c): RecomputeScoresJob {
|
|
|
|
|
+ /** @var ReportRepository $reports */
|
|
|
|
|
+ $reports = $c->get(ReportRepository::class);
|
|
|
|
|
+ /** @var IpScoreRepository $ipScores */
|
|
|
|
|
+ $ipScores = $c->get(IpScoreRepository::class);
|
|
|
|
|
+ /** @var PairScorer $scorer */
|
|
|
|
|
+ $scorer = $c->get(PairScorer::class);
|
|
|
|
|
+ /** @var int $maxRuntime */
|
|
|
|
|
+ $maxRuntime = $c->get('settings.job_recompute_max_runtime_seconds');
|
|
|
|
|
+ /** @var int $maxRows */
|
|
|
|
|
+ $maxRows = $c->get('settings.job_recompute_max_rows_per_tick');
|
|
|
|
|
+
|
|
|
|
|
+ return new RecomputeScoresJob($reports, $ipScores, $scorer, $maxRuntime, $maxRows);
|
|
|
|
|
+ }),
|
|
|
|
|
+ CleanupAuditJob::class => factory(static function (ContainerInterface $c): CleanupAuditJob {
|
|
|
|
|
+ /** @var Connection $conn */
|
|
|
|
|
+ $conn = $c->get(Connection::class);
|
|
|
|
|
+ /** @var int $days */
|
|
|
|
|
+ $days = $c->get('settings.job_audit_retention_days');
|
|
|
|
|
+
|
|
|
|
|
+ return new CleanupAuditJob($conn, $days);
|
|
|
|
|
+ }),
|
|
|
|
|
+ EnrichPendingJob::class => autowire(),
|
|
|
|
|
+ TickJob::class => factory(static function (ContainerInterface $c): TickJob {
|
|
|
|
|
+ /** @var JobRunner $runner */
|
|
|
|
|
+ $runner = $c->get(JobRunner::class);
|
|
|
|
|
+ /** @var JobRunRepository $runs */
|
|
|
|
|
+ $runs = $c->get(JobRunRepository::class);
|
|
|
|
|
+
|
|
|
|
|
+ // Closure indirection: TickJob iterates JobRegistry at
|
|
|
|
|
+ // run() time, after the registry is fully populated. A
|
|
|
|
|
+ // direct JobRegistry dependency would create a build-time
|
|
|
|
|
+ // cycle (registry → tick → registry).
|
|
|
|
|
+ $resolver = static fn (): array => $c->get(JobRegistry::class)->all();
|
|
|
|
|
+
|
|
|
|
|
+ return new TickJob($resolver, $runner, $runs);
|
|
|
|
|
+ }),
|
|
|
|
|
+ JobRegistry::class => factory(static function (ContainerInterface $c): JobRegistry {
|
|
|
|
|
+ $registry = new JobRegistry();
|
|
|
|
|
+ /** @var RecomputeScoresJob $recompute */
|
|
|
|
|
+ $recompute = $c->get(RecomputeScoresJob::class);
|
|
|
|
|
+ /** @var CleanupAuditJob $cleanup */
|
|
|
|
|
+ $cleanup = $c->get(CleanupAuditJob::class);
|
|
|
|
|
+ /** @var EnrichPendingJob $enrich */
|
|
|
|
|
+ $enrich = $c->get(EnrichPendingJob::class);
|
|
|
|
|
+ /** @var TickJob $tick */
|
|
|
|
|
+ $tick = $c->get(TickJob::class);
|
|
|
|
|
+ $registry->register($recompute);
|
|
|
|
|
+ $registry->register($cleanup);
|
|
|
|
|
+ $registry->register($enrich);
|
|
|
|
|
+ $registry->register($tick);
|
|
|
|
|
+
|
|
|
|
|
+ return $registry;
|
|
|
|
|
+ }),
|
|
|
|
|
+ JobsController::class => autowire(),
|
|
|
|
|
+ InternalNetworkMiddleware::class => autowire(),
|
|
|
|
|
+ InternalTokenMiddleware::class => factory(static function (ContainerInterface $c): InternalTokenMiddleware {
|
|
|
|
|
+ /** @var ResponseFactoryInterface $rf */
|
|
|
|
|
+ $rf = $c->get(ResponseFactoryInterface::class);
|
|
|
|
|
+ /** @var string $token */
|
|
|
|
|
+ $token = $c->get('settings.internal_job_token');
|
|
|
|
|
+
|
|
|
|
|
+ return new InternalTokenMiddleware($rf, $token);
|
|
|
|
|
+ }),
|
|
|
JsonErrorHandler::class => factory(static function (ContainerInterface $c): JsonErrorHandler {
|
|
JsonErrorHandler::class => factory(static function (ContainerInterface $c): JsonErrorHandler {
|
|
|
/** @var ResponseFactoryInterface $factory */
|
|
/** @var ResponseFactoryInterface $factory */
|
|
|
$factory = $c->get(ResponseFactoryInterface::class);
|
|
$factory = $c->get(ResponseFactoryInterface::class);
|