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,218 @@
<?php
declare(strict_types=1);
namespace App\Framework\Performance\Repository;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Database\ConnectionInterface;
use App\Framework\Database\Migration\MigrationVersion;
use App\Framework\Database\Query\QueryBuilder;
use App\Framework\Database\Query\QueryBuilderFactory;
use App\Framework\Performance\Entity\PerformanceMetric;
use App\Framework\Performance\PerformanceCategory;
use DateTimeImmutable;
final readonly class PerformanceMetricsRepository
{
private QueryBuilder $queryBuilder;
public function __construct(
private ConnectionInterface $connection,
private QueryBuilderFactory $queryBuilderFactory
) {
$this->queryBuilder = $this->queryBuilderFactory->create($connection);
}
public function save(PerformanceMetric $metric): int
{
$data = [
'operation_id' => $metric->operationId,
'operation_type' => $metric->operationType,
'category' => $metric->category->value,
'migration_version' => $metric->migrationVersion?->toString(),
'execution_time_ms' => $metric->executionTime->toMilliseconds(),
'memory_start_bytes' => $metric->memoryStart->toBytes(),
'memory_end_bytes' => $metric->memoryEnd->toBytes(),
'memory_peak_bytes' => $metric->memoryPeak->toBytes(),
'memory_delta_bytes' => $metric->memoryDelta->toBytes(),
'success' => $metric->success,
'error_message' => $metric->errorMessage,
'metadata' => $metric->metadata ? json_encode($metric->metadata) : null,
'created_at' => $metric->createdAt->format('Y-m-d H:i:s'),
'updated_at' => $metric->updatedAt?->format('Y-m-d H:i:s'),
];
return $this->queryBuilder
->table('performance_metrics')
->insert($data);
}
public function saveBatch(array $metrics): bool
{
if (empty($metrics)) {
return true;
}
$data = array_map(fn (PerformanceMetric $metric) => [
'operation_id' => $metric->operationId,
'operation_type' => $metric->operationType,
'category' => $metric->category->value,
'migration_version' => $metric->migrationVersion?->toString(),
'execution_time_ms' => $metric->executionTime->toMilliseconds(),
'memory_start_bytes' => $metric->memoryStart->toBytes(),
'memory_end_bytes' => $metric->memoryEnd->toBytes(),
'memory_peak_bytes' => $metric->memoryPeak->toBytes(),
'memory_delta_bytes' => $metric->memoryDelta->toBytes(),
'success' => $metric->success,
'error_message' => $metric->errorMessage,
'metadata' => $metric->metadata ? json_encode($metric->metadata) : null,
'created_at' => $metric->createdAt->format('Y-m-d H:i:s'),
'updated_at' => $metric->updatedAt?->format('Y-m-d H:i:s'),
], $metrics);
return $this->queryBuilder
->table('performance_metrics')
->insertBatch($data) > 0;
}
public function findById(int $id): ?PerformanceMetric
{
$result = $this->queryBuilder
->table('performance_metrics')
->where('id', '=', $id)
->first();
return $result ? PerformanceMetric::fromArray($result) : null;
}
public function findByOperationId(string $operationId): array
{
$results = $this->queryBuilder
->table('performance_metrics')
->where('operation_id', '=', $operationId)
->orderBy('created_at', 'DESC')
->get();
return array_map(
fn (array $row) => PerformanceMetric::fromArray($row),
$results
);
}
public function findByMigrationVersion(MigrationVersion $version): array
{
$results = $this->queryBuilder
->table('performance_metrics')
->where('migration_version', '=', $version->toString())
->orderBy('created_at', 'DESC')
->get();
return array_map(
fn (array $row) => PerformanceMetric::fromArray($row),
$results
);
}
public function findByCategory(PerformanceCategory $category, int $limit = 100): array
{
$results = $this->queryBuilder
->table('performance_metrics')
->where('category', '=', $category->value)
->orderBy('created_at', 'DESC')
->limit($limit)
->get();
return array_map(
fn (array $row) => PerformanceMetric::fromArray($row),
$results
);
}
public function findFailures(int $limit = 50): array
{
$results = $this->queryBuilder
->table('performance_metrics')
->where('success', '=', false)
->orderBy('created_at', 'DESC')
->limit($limit)
->get();
return array_map(
fn (array $row) => PerformanceMetric::fromArray($row),
$results
);
}
public function findSlowOperations(Duration $threshold, int $limit = 50): array
{
$results = $this->queryBuilder
->table('performance_metrics')
->where('execution_time_ms', '>', $threshold->toMilliseconds())
->orderBy('execution_time_ms', 'DESC')
->limit($limit)
->get();
return array_map(
fn (array $row) => PerformanceMetric::fromArray($row),
$results
);
}
public function getAverageExecutionTime(PerformanceCategory $category): ?Duration
{
$result = $this->queryBuilder
->table('performance_metrics')
->where('category', '=', $category->value)
->where('success', '=', true)
->average('execution_time_ms');
return $result ? Duration::fromMilliseconds((int) $result) : null;
}
public function getPerformanceStatistics(DateTimeImmutable $since): array
{
$results = $this->queryBuilder
->table('performance_metrics')
->select([
'category',
'COUNT(*) as total_operations',
'AVG(execution_time_ms) as avg_execution_time',
'MAX(execution_time_ms) as max_execution_time',
'MIN(execution_time_ms) as min_execution_time',
'SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as successful_operations',
'AVG(memory_peak_bytes) as avg_memory_peak',
])
->where('created_at', '>=', $since->format('Y-m-d H:i:s'))
->groupBy('category')
->get();
return array_map(function (array $row) {
return [
'category' => PerformanceCategory::from($row['category']),
'total_operations' => (int) $row['total_operations'],
'avg_execution_time' => Duration::fromMilliseconds((int) $row['avg_execution_time']),
'max_execution_time' => Duration::fromMilliseconds((int) $row['max_execution_time']),
'min_execution_time' => Duration::fromMilliseconds((int) $row['min_execution_time']),
'successful_operations' => (int) $row['successful_operations'],
'success_rate' => (float) $row['successful_operations'] / (float) $row['total_operations'],
'avg_memory_peak' => \App\Framework\Core\ValueObjects\Byte::fromBytes((int) $row['avg_memory_peak']),
];
}, $results);
}
public function deleteOlderThan(DateTimeImmutable $cutoff): int
{
return $this->queryBuilder
->table('performance_metrics')
->where('created_at', '<', $cutoff->format('Y-m-d H:i:s'))
->delete();
}
public function count(): int
{
return $this->queryBuilder
->table('performance_metrics')
->count();
}
}