Ship production optimization M1-M12.5A: queues, metrics, HTTP observability, and vector search reliability.
Keep similar-ai from tripping the global circuit on a lone URL 502, clamp Qdrant search to 100, and add Server-Timing plus slow-request logging. Studio shared props, Academy S3 exists caching, heat chunking, and Redis/scheduler hygiene stay in this rollout.
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
use cPad\Plugins\Forum\Jobs\AnalyzeForumPostJob;
|
||||
use cPad\Plugins\Forum\Jobs\BotActivityMonitor;
|
||||
use cPad\Plugins\Forum\Jobs\FirewallActivityMonitor;
|
||||
use cPad\Plugins\Forum\Models\ForumPost;
|
||||
use cPad\Plugins\Forum\Services\ForumModerationService;
|
||||
use cPad\Plugins\Forum\Services\Security\BotProtectionService;
|
||||
use cPad\Plugins\Forum\Services\Security\ForumSecurityFirewallService;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
|
||||
it('does not dispatch AnalyzeForumPostJob when AI queue dispatch is disabled', function () {
|
||||
config(['skinbase_ai_moderation.queue.dispatch_enabled' => false]);
|
||||
Queue::fake();
|
||||
|
||||
$post = new ForumPost();
|
||||
$post->id = 42;
|
||||
|
||||
$queued = app(ForumModerationService::class)->dispatchAsyncScan($post);
|
||||
|
||||
expect($queued)->toBeFalse();
|
||||
Queue::assertNotPushed(AnalyzeForumPostJob::class);
|
||||
});
|
||||
|
||||
it('dispatches AnalyzeForumPostJob when AI queue dispatch is enabled', function () {
|
||||
config(['skinbase_ai_moderation.queue.dispatch_enabled' => true]);
|
||||
Queue::fake();
|
||||
|
||||
$post = new ForumPost();
|
||||
$post->id = 43;
|
||||
|
||||
$queued = app(ForumModerationService::class)->dispatchAsyncScan($post);
|
||||
|
||||
expect($queued)->toBeTrue();
|
||||
Queue::assertPushedOn(
|
||||
(string) config('skinbase_ai_moderation.queue.name', 'forum-moderation'),
|
||||
AnalyzeForumPostJob::class,
|
||||
);
|
||||
});
|
||||
|
||||
it('does not dispatch BotActivityMonitor when security queue dispatch is disabled', function () {
|
||||
config(['forum_security.queues.dispatch_enabled' => false]);
|
||||
Queue::fake();
|
||||
|
||||
$this->artisan('forum:bot-scan')->assertSuccessful();
|
||||
|
||||
Queue::assertNotPushed(BotActivityMonitor::class);
|
||||
});
|
||||
|
||||
it('dispatches BotActivityMonitor when security queue dispatch is enabled', function () {
|
||||
config(['forum_security.queues.dispatch_enabled' => true]);
|
||||
Queue::fake();
|
||||
|
||||
$this->artisan('forum:bot-scan')->assertSuccessful();
|
||||
|
||||
Queue::assertPushed(BotActivityMonitor::class);
|
||||
});
|
||||
|
||||
it('does not dispatch FirewallActivityMonitor when security queue dispatch is disabled', function () {
|
||||
config(['forum_security.queues.dispatch_enabled' => false]);
|
||||
Queue::fake();
|
||||
|
||||
$this->artisan('forum:firewall-scan')->assertSuccessful();
|
||||
|
||||
Queue::assertNotPushed(FirewallActivityMonitor::class);
|
||||
});
|
||||
|
||||
it('dispatches FirewallActivityMonitor when security queue dispatch is enabled', function () {
|
||||
config(['forum_security.queues.dispatch_enabled' => true]);
|
||||
Queue::fake();
|
||||
|
||||
$this->artisan('forum:firewall-scan')->assertSuccessful();
|
||||
|
||||
Queue::assertPushed(FirewallActivityMonitor::class);
|
||||
});
|
||||
|
||||
it('runs forum bot scan synchronously without queueing when --sync is passed', function () {
|
||||
config(['forum_security.queues.dispatch_enabled' => false]);
|
||||
Queue::fake();
|
||||
|
||||
$this->mock(BotProtectionService::class, function ($mock): void {
|
||||
$mock->shouldReceive('scanRecentActivity')->once()->andReturn(['processed' => 0]);
|
||||
});
|
||||
|
||||
$this->artisan('forum:bot-scan --sync')->assertSuccessful();
|
||||
|
||||
Queue::assertNothingPushed();
|
||||
});
|
||||
|
||||
it('runs forum firewall scan synchronously without queueing when --sync is passed', function () {
|
||||
config(['forum_security.queues.dispatch_enabled' => false]);
|
||||
Queue::fake();
|
||||
|
||||
$this->mock(ForumSecurityFirewallService::class, function ($mock): void {
|
||||
$mock->shouldReceive('scanRecentThreats')->once()->andReturn(['processed' => 0]);
|
||||
});
|
||||
|
||||
$this->artisan('forum:firewall-scan --sync')->assertSuccessful();
|
||||
|
||||
Queue::assertNothingPushed();
|
||||
});
|
||||
|
||||
it('does not enqueue AnalyzeForumPostJob from forum:ai-scan without --sync when dispatch is disabled', function () {
|
||||
config(['skinbase_ai_moderation.queue.dispatch_enabled' => false]);
|
||||
Queue::fake();
|
||||
|
||||
$this->artisan('forum:ai-scan')->assertSuccessful();
|
||||
|
||||
Queue::assertNotPushed(AnalyzeForumPostJob::class);
|
||||
});
|
||||
|
||||
it('keeps synchronous forum:scan-posts on the schedule and omits async forum enqueue commands when dispatch is disabled', function () {
|
||||
$this->artisan('schedule:list')
|
||||
->expectsOutputToContain('forum:scan-posts')
|
||||
->doesntExpectOutputToContain('forum:ai-scan')
|
||||
->doesntExpectOutputToContain('forum:bot-scan')
|
||||
->doesntExpectOutputToContain('forum:firewall-scan')
|
||||
->assertSuccessful();
|
||||
});
|
||||
Reference in New Issue
Block a user