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,165 @@
<?php
declare(strict_types=1);
namespace App\Framework\Queue\ValueObjects;
/**
* Value Object representing a chain of jobs with their execution order
*/
final readonly class JobChain
{
/** @var string[] */
public array $jobIds;
public function __construct(
public string $chainId,
public string $name,
array $jobIds,
public ChainExecutionMode $executionMode = ChainExecutionMode::SEQUENTIAL,
public bool $stopOnFailure = true,
public ?array $metadata = null
) {
$this->jobIds = array_values(array_unique($jobIds));
$this->validate();
}
public static function sequential(string $chainId, string $name, array $jobIds): self
{
return new self($chainId, $name, $jobIds, ChainExecutionMode::SEQUENTIAL);
}
public static function parallel(string $chainId, string $name, array $jobIds): self
{
return new self($chainId, $name, $jobIds, ChainExecutionMode::PARALLEL);
}
public static function conditional(string $chainId, string $name, array $jobIds): self
{
return new self($chainId, $name, $jobIds, ChainExecutionMode::CONDITIONAL);
}
public function isSequential(): bool
{
return $this->executionMode === ChainExecutionMode::SEQUENTIAL;
}
public function isParallel(): bool
{
return $this->executionMode === ChainExecutionMode::PARALLEL;
}
public function isConditional(): bool
{
return $this->executionMode === ChainExecutionMode::CONDITIONAL;
}
public function shouldStopOnFailure(): bool
{
return $this->stopOnFailure;
}
public function getJobCount(): int
{
return count($this->jobIds);
}
public function getFirstJob(): ?string
{
return $this->jobIds[0] ?? null;
}
public function getLastJob(): ?string
{
return end($this->jobIds) ?: null;
}
public function containsJob(string $jobId): bool
{
return in_array($jobId, $this->jobIds, true);
}
public function getJobPosition(string $jobId): ?int
{
$position = array_search($jobId, $this->jobIds, true);
return $position !== false ? $position : null;
}
public function getNextJob(string $currentJobId): ?string
{
$position = $this->getJobPosition($currentJobId);
if ($position === null) {
return null;
}
return $this->jobIds[$position + 1] ?? null;
}
public function getPreviousJob(string $currentJobId): ?string
{
$position = $this->getJobPosition($currentJobId);
if ($position === null || $position === 0) {
return null;
}
return $this->jobIds[$position - 1];
}
public function withMetadata(array $metadata): self
{
return new self(
chainId: $this->chainId,
name: $this->name,
jobIds: $this->jobIds,
executionMode: $this->executionMode,
stopOnFailure: $this->stopOnFailure,
metadata: array_merge($this->metadata ?? [], $metadata)
);
}
public function withStopOnFailure(bool $stopOnFailure): self
{
return new self(
chainId: $this->chainId,
name: $this->name,
jobIds: $this->jobIds,
executionMode: $this->executionMode,
stopOnFailure: $stopOnFailure,
metadata: $this->metadata
);
}
public function toArray(): array
{
return [
'chain_id' => $this->chainId,
'name' => $this->name,
'job_ids' => $this->jobIds,
'execution_mode' => $this->executionMode->value,
'stop_on_failure' => $this->stopOnFailure,
'job_count' => $this->getJobCount(),
'metadata' => $this->metadata
];
}
private function validate(): void
{
if (empty(trim($this->chainId))) {
throw new \InvalidArgumentException('Chain ID cannot be empty');
}
if (empty(trim($this->name))) {
throw new \InvalidArgumentException('Chain name cannot be empty');
}
if (empty($this->jobIds)) {
throw new \InvalidArgumentException('Job chain must contain at least one job');
}
foreach ($this->jobIds as $jobId) {
if (empty(trim($jobId))) {
throw new \InvalidArgumentException('Job ID cannot be empty');
}
}
}
}