docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,159 @@
<?php
declare(strict_types=1);
namespace App\Framework\Queue\Services;
use App\Framework\Queue\Contracts\DeadLetterQueueInterface;
use App\Framework\Queue\Entities\DeadLetterJob;
use App\Framework\Queue\Entities\JobIndexEntry;
use App\Framework\Queue\ValueObjects\DeadLetterQueueName;
use App\Framework\Queue\ValueObjects\FailureReason;
use App\Framework\Queue\ValueObjects\QueueName;
/**
* Manages dead letter queue operations and job failure handling
*/
final readonly class DeadLetterManager
{
public function __construct(
private DeadLetterQueueInterface $deadLetterQueue,
private ProductionJobPersistenceLayer $persistenceLayer
) {}
/**
* Move a failed job to the dead letter queue
*/
public function moveJobToDeadLetterQueue(
JobIndexEntry $failedJob,
FailureReason $failureReason,
?DeadLetterQueueName $deadLetterQueueName = null
): void {
// Use default dead letter queue name if not provided
$dlqName = $deadLetterQueueName ?? DeadLetterQueueName::forQueue(
QueueName::fromString($failedJob->queueType)
);
// Create dead letter job entry
$deadLetterJob = DeadLetterJob::fromFailedJob(
failedJob: $failedJob,
deadLetterQueueName: $dlqName,
failureReason: $failureReason
);
// Add to dead letter queue
$this->deadLetterQueue->addFailedJob($deadLetterJob);
// Remove from original job index
$this->persistenceLayer->deleteJob($failedJob->jobId);
}
/**
* Move a job to dead letter queue when max attempts are exceeded
*/
public function handleJobFailure(
string $jobId,
\Throwable $exception,
int $maxAttempts = 3
): bool {
$jobEntry = $this->persistenceLayer->getJobById($jobId);
if (!$jobEntry) {
return false;
}
// Check if max attempts exceeded
if ($jobEntry->attempts >= $maxAttempts) {
$failureReason = FailureReason::fromException($exception);
$this->moveJobToDeadLetterQueue(
failedJob: $jobEntry,
failureReason: $failureReason
);
return true;
}
return false;
}
/**
* Retry a job from dead letter queue
*/
public function retryJob(string $deadLetterJobId): bool
{
return $this->deadLetterQueue->retryJob($deadLetterJobId);
}
/**
* Get failed jobs for monitoring/admin interface
*/
public function getFailedJobs(
?QueueName $originalQueue = null,
int $limit = 100
): array {
if ($originalQueue) {
return $this->deadLetterQueue->getJobsByOriginalQueue($originalQueue, $limit);
}
// Get jobs from all dead letter queues
$allJobs = [];
$queues = $this->deadLetterQueue->getAvailableQueues();
foreach ($queues as $queueName) {
$jobs = $this->deadLetterQueue->getJobs($queueName, $limit);
$allJobs = array_merge($allJobs, $jobs);
}
// Sort by moved_to_dlq_at descending
usort($allJobs, fn ($a, $b) => strcmp($b->movedToDlqAt, $a->movedToDlqAt));
return array_slice($allJobs, 0, $limit);
}
/**
* Get dead letter queue statistics
*/
public function getStatistics(): array
{
$queues = $this->deadLetterQueue->getAvailableQueues();
$stats = [];
foreach ($queues as $queueName) {
$stats[$queueName->toString()] = $this->deadLetterQueue->getQueueStats($queueName);
}
return $stats;
}
/**
* Clear all jobs from a dead letter queue
*/
public function clearDeadLetterQueue(DeadLetterQueueName $queueName): int
{
return $this->deadLetterQueue->clearQueue($queueName);
}
/**
* Retry all jobs in a dead letter queue
*/
public function retryAllJobs(DeadLetterQueueName $queueName): int
{
return $this->deadLetterQueue->retryAllJobs($queueName);
}
/**
* Delete a specific job from dead letter queue
*/
public function deleteJob(string $deadLetterJobId): bool
{
return $this->deadLetterQueue->deleteJob($deadLetterJobId);
}
/**
* Get all available dead letter queues
*/
public function getAvailableQueues(): array
{
return $this->deadLetterQueue->getAvailableQueues();
}
}