Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
264
src/Framework/Database/Examples/AsyncDatabaseDemo.php
Normal file
264
src/Framework/Database/Examples/AsyncDatabaseDemo.php
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Database\Examples;
|
||||
|
||||
use App\Framework\Database\AsyncDatabaseDecorator;
|
||||
use App\Framework\Database\ConnectionInterface;
|
||||
|
||||
/**
|
||||
* Performance Demo: Sequential vs Parallel Database Operations
|
||||
*/
|
||||
final class AsyncDatabaseDemo
|
||||
{
|
||||
public static function run(ConnectionInterface $syncDb, AsyncDatabaseDecorator $asyncDb): void
|
||||
{
|
||||
echo "🚀 AsyncDatabase Performance Demo\n";
|
||||
echo "=================================\n\n";
|
||||
|
||||
self::demonstrateParallelQueries($syncDb, $asyncDb);
|
||||
self::demonstrateBatchOperations($asyncDb);
|
||||
self::demonstrateDataAggregation($asyncDb);
|
||||
self::demonstrateReplicaQueries($asyncDb);
|
||||
self::demonstrateOptimisticLocking($asyncDb);
|
||||
}
|
||||
|
||||
private static function demonstrateParallelQueries(ConnectionInterface $syncDb, AsyncDatabaseDecorator $asyncDb): void
|
||||
{
|
||||
echo "📊 Test 1: Sequential vs Parallel Database Queries\n";
|
||||
echo "-" . str_repeat("-", 50) . "\n";
|
||||
|
||||
// Setup: Create test queries that simulate different load times
|
||||
$queries = [
|
||||
'users' => 'SELECT COUNT(*) as user_count FROM users',
|
||||
'orders' => 'SELECT COUNT(*) as order_count FROM orders',
|
||||
'products' => 'SELECT COUNT(*) as product_count FROM products',
|
||||
'reviews' => 'SELECT COUNT(*) as review_count FROM reviews',
|
||||
'sessions' => 'SELECT COUNT(*) as session_count FROM user_sessions WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 DAY)',
|
||||
];
|
||||
|
||||
// Sequential execution
|
||||
echo "⏳ Executing 5 queries sequentially...\n";
|
||||
$start = microtime(true);
|
||||
|
||||
$syncResults = [];
|
||||
foreach ($queries as $name => $sql) {
|
||||
try {
|
||||
$syncResults[$name] = $syncDb->queryScalar($sql);
|
||||
} catch (\Exception $e) {
|
||||
$syncResults[$name] = "Error: " . $e->getMessage();
|
||||
echo "❌ Query '$name' failed: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$syncTime = microtime(true) - $start;
|
||||
|
||||
// Parallel execution
|
||||
echo "⚡ Executing 5 queries in parallel...\n";
|
||||
$start = microtime(true);
|
||||
|
||||
try {
|
||||
$queryData = [];
|
||||
foreach ($queries as $name => $sql) {
|
||||
$queryData[$name] = ['sql' => $sql, 'method' => 'queryScalar'];
|
||||
}
|
||||
|
||||
$asyncResults = $asyncDb->aggregate($queryData);
|
||||
} catch (\Exception $e) {
|
||||
$asyncResults = ["Error: " . $e->getMessage()];
|
||||
}
|
||||
|
||||
$asyncTime = microtime(true) - $start;
|
||||
|
||||
$improvement = $syncTime > 0 ? (($syncTime - $asyncTime) / $syncTime) * 100 : 0;
|
||||
|
||||
echo "Sequential time: " . number_format($syncTime * 1000, 0) . "ms\n";
|
||||
echo "Parallel time: " . number_format($asyncTime * 1000, 0) . "ms\n";
|
||||
echo "Improvement: " . number_format($improvement, 1) . "%\n";
|
||||
|
||||
$successCount = 0;
|
||||
foreach ($asyncResults as $name => $result) {
|
||||
if ($result['success']) {
|
||||
$successCount++;
|
||||
echo "✅ $name: {$result['data']}\n";
|
||||
} else {
|
||||
echo "❌ $name: {$result['error']}\n";
|
||||
}
|
||||
}
|
||||
echo "Successful queries: $successCount/" . count($queries) . "\n\n";
|
||||
}
|
||||
|
||||
private static function demonstrateBatchOperations(AsyncDatabaseDecorator $asyncDb): void
|
||||
{
|
||||
echo "📦 Test 2: Batch Insert Performance\n";
|
||||
echo "-" . str_repeat("-", 50) . "\n";
|
||||
|
||||
// Generate test data
|
||||
$testData = [];
|
||||
for ($i = 1; $i <= 500; $i++) {
|
||||
$testData[] = [
|
||||
'name' => "Test User $i",
|
||||
'email' => "user$i@example.com",
|
||||
'status' => 'active',
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
echo "Inserting 500 records in batches of 50...\n";
|
||||
$start = microtime(true);
|
||||
|
||||
try {
|
||||
$results = $asyncDb->batchInsert(
|
||||
'test_users',
|
||||
['name', 'email', 'status', 'created_at'],
|
||||
$testData,
|
||||
50
|
||||
);
|
||||
|
||||
$time = microtime(true) - $start;
|
||||
$totalInserted = array_sum($results);
|
||||
|
||||
echo "✅ Inserted $totalInserted records in " . number_format($time * 1000, 0) . "ms\n";
|
||||
echo "Batches completed: " . count($results) . "\n";
|
||||
echo "Average per batch: " . number_format(($time / count($results)) * 1000, 0) . "ms\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "❌ Batch insert failed: " . $e->getMessage() . "\n";
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
private static function demonstrateDataAggregation(AsyncDatabaseDecorator $asyncDb): void
|
||||
{
|
||||
echo "📈 Test 3: Dashboard Data Aggregation\n";
|
||||
echo "-" . str_repeat("-", 50) . "\n";
|
||||
|
||||
$start = microtime(true);
|
||||
|
||||
try {
|
||||
$results = $asyncDb->aggregate([
|
||||
'total_users' => [
|
||||
'sql' => 'SELECT COUNT(*) FROM users',
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
'active_sessions' => [
|
||||
'sql' => 'SELECT COUNT(*) FROM user_sessions WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)',
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
'recent_orders' => [
|
||||
'sql' => 'SELECT COUNT(*) as count, COALESCE(SUM(total), 0) as revenue FROM orders WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 DAY)',
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'top_products' => [
|
||||
'sql' => 'SELECT p.name, COUNT(*) as sales FROM order_items oi JOIN products p ON oi.product_id = p.id JOIN orders o ON oi.order_id = o.id WHERE o.created_at > DATE_SUB(NOW(), INTERVAL 7 DAYS) GROUP BY p.id ORDER BY sales DESC LIMIT 5',
|
||||
],
|
||||
'system_health' => [
|
||||
'sql' => 'SELECT COUNT(*) as error_count FROM error_logs WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)',
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
]);
|
||||
|
||||
$time = microtime(true) - $start;
|
||||
|
||||
echo "Dashboard data loaded in: " . number_format($time * 1000, 0) . "ms\n";
|
||||
|
||||
foreach ($results as $metric => $result) {
|
||||
if ($result['success']) {
|
||||
if (is_array($result['data'])) {
|
||||
$count = is_countable($result['data']) ? count($result['data']) : 'N/A';
|
||||
echo "✅ $metric: $count items loaded\n";
|
||||
} else {
|
||||
echo "✅ $metric: {$result['data']}\n";
|
||||
}
|
||||
} else {
|
||||
echo "❌ $metric: {$result['error']}\n";
|
||||
}
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "❌ Data aggregation failed: " . $e->getMessage() . "\n";
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
private static function demonstrateReplicaQueries(AsyncDatabaseDecorator $asyncDb): void
|
||||
{
|
||||
echo "🔄 Test 4: Replica Query Distribution\n";
|
||||
echo "-" . str_repeat("-", 50) . "\n";
|
||||
|
||||
$sql = 'SELECT COUNT(*) as total FROM users WHERE status = "active"';
|
||||
|
||||
echo "Testing replica query distribution...\n";
|
||||
$start = microtime(true);
|
||||
|
||||
try {
|
||||
$results = $asyncDb->queryReplicas($sql);
|
||||
$time = microtime(true) - $start;
|
||||
|
||||
echo "Query executed on " . count($results) . " replica(s) in " . number_format($time * 1000, 0) . "ms\n";
|
||||
|
||||
if (count($results) > 1) {
|
||||
echo "Results from replicas:\n";
|
||||
foreach ($results as $i => $result) {
|
||||
if ($result instanceof \App\Framework\Database\ResultInterface) {
|
||||
$data = $result->getIterator()->current();
|
||||
echo " Replica $i: {$data['total']} active users\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "Single connection used (no replicas available)\n";
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "❌ Replica query failed: " . $e->getMessage() . "\n";
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
private static function demonstrateOptimisticLocking(AsyncDatabaseDecorator $asyncDb): void
|
||||
{
|
||||
echo "🔒 Test 5: Optimistic Locking Performance\n";
|
||||
echo "-" . str_repeat("-", 50) . "\n";
|
||||
|
||||
echo "Testing optimistic locking with version control...\n";
|
||||
|
||||
// Simulate concurrent updates to the same record
|
||||
$tests = [
|
||||
['product_id' => 1, 'reserved' => 5],
|
||||
['product_id' => 1, 'reserved' => 10], // This should trigger retry
|
||||
['product_id' => 2, 'reserved' => 3],
|
||||
];
|
||||
|
||||
foreach ($tests as $i => $test) {
|
||||
$start = microtime(true);
|
||||
|
||||
try {
|
||||
$success = $asyncDb->optimisticUpdate(
|
||||
'inventory',
|
||||
['reserved' => $test['reserved']],
|
||||
['product_id' => $test['product_id']],
|
||||
'version',
|
||||
maxRetries: 3
|
||||
);
|
||||
|
||||
$time = microtime(true) - $start;
|
||||
$status = $success ? "✅ Success" : "❌ Failed";
|
||||
|
||||
echo "Test " . ($i + 1) . " (Product {$test['product_id']}): $status - " .
|
||||
number_format($time * 1000, 0) . "ms\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$time = microtime(true) - $start;
|
||||
echo "Test " . ($i + 1) . " (Product {$test['product_id']}): ❌ Error - " .
|
||||
number_format($time * 1000, 0) . "ms - " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Usage example:
|
||||
// $syncDb = new PdoConnection($pdo);
|
||||
// $asyncDb = new AsyncDatabaseDecorator($syncDb, $asyncService);
|
||||
// AsyncDatabaseDemo::run($syncDb, $asyncDb);
|
||||
295
src/Framework/Database/Examples/AsyncDatabaseExample.php
Normal file
295
src/Framework/Database/Examples/AsyncDatabaseExample.php
Normal file
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Database\Examples;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Duration;
|
||||
use App\Framework\Database\AsyncDatabaseDecorator;
|
||||
|
||||
/**
|
||||
* Real-world examples for AsyncDatabaseDecorator
|
||||
*/
|
||||
final readonly class AsyncDatabaseExample
|
||||
{
|
||||
public function __construct(
|
||||
private AsyncDatabaseDecorator $db
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Dashboard data aggregation
|
||||
*/
|
||||
public function loadDashboardData(int $userId): array
|
||||
{
|
||||
return $this->db->aggregate([
|
||||
'user_profile' => [
|
||||
'sql' => 'SELECT id, name, email, avatar FROM users WHERE id = ?',
|
||||
'params' => [$userId],
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'user_stats' => [
|
||||
'sql' => 'SELECT COUNT(*) as post_count FROM posts WHERE user_id = ?',
|
||||
'params' => [$userId],
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
'recent_orders' => [
|
||||
'sql' => 'SELECT id, total, created_at FROM orders WHERE user_id = ? ORDER BY created_at DESC LIMIT 5',
|
||||
'params' => [$userId],
|
||||
],
|
||||
'unread_notifications' => [
|
||||
'sql' => 'SELECT COUNT(*) FROM notifications WHERE user_id = ? AND read_at IS NULL',
|
||||
'params' => [$userId],
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
'account_balance' => [
|
||||
'sql' => 'SELECT balance FROM accounts WHERE user_id = ?',
|
||||
'params' => [$userId],
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: E-commerce product page data
|
||||
*/
|
||||
public function loadProductPageData(int $productId): array
|
||||
{
|
||||
return $this->db->aggregate([
|
||||
'product' => [
|
||||
'sql' => 'SELECT * FROM products WHERE id = ?',
|
||||
'params' => [$productId],
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'inventory' => [
|
||||
'sql' => 'SELECT quantity, reserved FROM inventory WHERE product_id = ?',
|
||||
'params' => [$productId],
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'reviews_summary' => [
|
||||
'sql' => 'SELECT AVG(rating) as avg_rating, COUNT(*) as review_count FROM reviews WHERE product_id = ?',
|
||||
'params' => [$productId],
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'recent_reviews' => [
|
||||
'sql' => 'SELECT rating, comment, user_name, created_at FROM reviews WHERE product_id = ? ORDER BY created_at DESC LIMIT 5',
|
||||
'params' => [$productId],
|
||||
],
|
||||
'related_products' => [
|
||||
'sql' => 'SELECT id, name, price, image FROM products WHERE category_id = (SELECT category_id FROM products WHERE id = ?) AND id != ? LIMIT 4',
|
||||
'params' => [$productId, $productId],
|
||||
],
|
||||
'price_history' => [
|
||||
'sql' => 'SELECT price, created_at FROM price_history WHERE product_id = ? ORDER BY created_at DESC LIMIT 10',
|
||||
'params' => [$productId],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Bulk user import
|
||||
*/
|
||||
public function importUsers(array $userData): array
|
||||
{
|
||||
$columns = ['name', 'email', 'password_hash', 'created_at'];
|
||||
|
||||
// Prepare data
|
||||
$rows = [];
|
||||
foreach ($userData as $user) {
|
||||
$rows[] = [
|
||||
$user['name'],
|
||||
$user['email'],
|
||||
password_hash($user['password'], PASSWORD_DEFAULT),
|
||||
date('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
// Insert in batches of 100
|
||||
return $this->db->batchInsert('users', $columns, $rows, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Bulk order status updates
|
||||
*/
|
||||
public function updateOrderStatuses(array $orderUpdates): array
|
||||
{
|
||||
// Each update: ['id' => 123, 'status' => 'shipped', 'shipped_at' => '2024-01-01']
|
||||
return $this->db->batchUpdate('orders', $orderUpdates, 'id', 25);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Analytics data collection
|
||||
*/
|
||||
public function collectAnalyticsData(\DateTime $date): array
|
||||
{
|
||||
$dateStr = $date->format('Y-m-d');
|
||||
|
||||
return $this->db->aggregate([
|
||||
'daily_users' => [
|
||||
'sql' => 'SELECT COUNT(DISTINCT user_id) FROM user_sessions WHERE DATE(created_at) = ?',
|
||||
'params' => [$dateStr],
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
'daily_orders' => [
|
||||
'sql' => 'SELECT COUNT(*), SUM(total) as revenue FROM orders WHERE DATE(created_at) = ?',
|
||||
'params' => [$dateStr],
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'popular_products' => [
|
||||
'sql' => 'SELECT p.name, COUNT(*) as sales FROM order_items oi JOIN products p ON oi.product_id = p.id JOIN orders o ON oi.order_id = o.id WHERE DATE(o.created_at) = ? GROUP BY p.id ORDER BY sales DESC LIMIT 10',
|
||||
'params' => [$dateStr],
|
||||
],
|
||||
'top_customers' => [
|
||||
'sql' => 'SELECT u.name, u.email, SUM(o.total) as spent FROM users u JOIN orders o ON u.id = o.user_id WHERE DATE(o.created_at) = ? GROUP BY u.id ORDER BY spent DESC LIMIT 10',
|
||||
'params' => [$dateStr],
|
||||
],
|
||||
'page_views' => [
|
||||
'sql' => 'SELECT page, COUNT(*) as views FROM page_views WHERE DATE(created_at) = ? GROUP BY page ORDER BY views DESC LIMIT 20',
|
||||
'params' => [$dateStr],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Database health monitoring
|
||||
*/
|
||||
public function monitorDatabaseHealth(): array
|
||||
{
|
||||
$tables = ['users', 'orders', 'products', 'order_items', 'reviews'];
|
||||
|
||||
$tableStats = $this->db->getTableStats($tables);
|
||||
|
||||
$systemStats = $this->db->aggregate([
|
||||
'active_connections' => [
|
||||
'sql' => 'SHOW STATUS LIKE "Threads_connected"',
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'slow_queries' => [
|
||||
'sql' => 'SHOW STATUS LIKE "Slow_queries"',
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'uptime' => [
|
||||
'sql' => 'SHOW STATUS LIKE "Uptime"',
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'innodb_buffer_pool_usage' => [
|
||||
'sql' => 'SELECT (1 - (FREE_BUFFERS / TOTAL_BUFFERS)) * 100 as usage_percent FROM (SELECT VARIABLE_VALUE as FREE_BUFFERS FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = "Innodb_buffer_pool_pages_free") f CROSS JOIN (SELECT VARIABLE_VALUE as TOTAL_BUFFERS FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = "Innodb_buffer_pool_pages_total") t',
|
||||
'method' => 'queryScalar',
|
||||
],
|
||||
]);
|
||||
|
||||
return [
|
||||
'table_stats' => $tableStats,
|
||||
'system_stats' => $systemStats,
|
||||
'timestamp' => time(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: User activity timeline
|
||||
*/
|
||||
public function getUserActivityTimeline(int $userId, int $days = 30): array
|
||||
{
|
||||
$since = date('Y-m-d', strtotime("-$days days"));
|
||||
|
||||
return $this->db->aggregate([
|
||||
'login_history' => [
|
||||
'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as logins FROM user_sessions WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
|
||||
'params' => [$userId, $since],
|
||||
],
|
||||
'order_history' => [
|
||||
'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as orders, SUM(total) as spent FROM orders WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
|
||||
'params' => [$userId, $since],
|
||||
],
|
||||
'page_views' => [
|
||||
'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as views FROM page_views WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
|
||||
'params' => [$userId, $since],
|
||||
],
|
||||
'support_tickets' => [
|
||||
'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as tickets FROM support_tickets WHERE user_id = ? AND created_at >= ? GROUP BY DATE(created_at) ORDER BY date DESC',
|
||||
'params' => [$userId, $since],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Inventory management with optimistic locking
|
||||
*/
|
||||
public function reserveInventory(int $productId, int $quantity): bool
|
||||
{
|
||||
return $this->db->optimisticUpdate(
|
||||
'inventory',
|
||||
['reserved' => $quantity],
|
||||
['product_id' => $productId],
|
||||
'version',
|
||||
maxRetries: 5
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Complex reporting with timeout protection
|
||||
*/
|
||||
public function generateSalesReport(\DateTime $startDate, \DateTime $endDate): array
|
||||
{
|
||||
return $this->db->transactionWithTimeout(function ($db) use ($startDate, $endDate) {
|
||||
$start = $startDate->format('Y-m-d');
|
||||
$end = $endDate->format('Y-m-d');
|
||||
|
||||
return $db->aggregate([
|
||||
'summary' => [
|
||||
'sql' => 'SELECT COUNT(*) as total_orders, SUM(total) as total_revenue, AVG(total) as avg_order_value FROM orders WHERE created_at BETWEEN ? AND ?',
|
||||
'params' => [$start, $end],
|
||||
'method' => 'queryOne',
|
||||
],
|
||||
'by_day' => [
|
||||
'sql' => 'SELECT DATE(created_at) as date, COUNT(*) as orders, SUM(total) as revenue FROM orders WHERE created_at BETWEEN ? AND ? GROUP BY DATE(created_at) ORDER BY date',
|
||||
'params' => [$start, $end],
|
||||
],
|
||||
'by_product' => [
|
||||
'sql' => 'SELECT p.name, SUM(oi.quantity) as units_sold, SUM(oi.price * oi.quantity) as revenue FROM order_items oi JOIN products p ON oi.product_id = p.id JOIN orders o ON oi.order_id = o.id WHERE o.created_at BETWEEN ? AND ? GROUP BY p.id ORDER BY revenue DESC LIMIT 20',
|
||||
'params' => [$start, $end],
|
||||
],
|
||||
'by_customer' => [
|
||||
'sql' => 'SELECT u.name, u.email, COUNT(o.id) as orders, SUM(o.total) as total_spent FROM users u JOIN orders o ON u.id = o.user_id WHERE o.created_at BETWEEN ? AND ? GROUP BY u.id ORDER BY total_spent DESC LIMIT 20',
|
||||
'params' => [$start, $end],
|
||||
],
|
||||
]);
|
||||
}, Duration::fromMinutes(5));
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Background data cleanup
|
||||
*/
|
||||
public function cleanupOldData(): void
|
||||
{
|
||||
// Non-blocking cleanup operations
|
||||
$this->db->executeAsync('DELETE FROM user_sessions WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)');
|
||||
$this->db->executeAsync('DELETE FROM page_views WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY)');
|
||||
$this->db->executeAsync('DELETE FROM audit_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 YEAR)');
|
||||
$this->db->executeAsync('DELETE FROM temporary_uploads WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 DAY)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Read-ahead caching for related data
|
||||
*/
|
||||
public function preloadRelatedData(array $productIds): array
|
||||
{
|
||||
$queries = [];
|
||||
|
||||
foreach ($productIds as $productId) {
|
||||
$queries["reviews_$productId"] = [
|
||||
'sql' => 'SELECT COUNT(*) as count, AVG(rating) as avg_rating FROM reviews WHERE product_id = ?',
|
||||
'params' => [$productId],
|
||||
'method' => 'queryOne',
|
||||
];
|
||||
|
||||
$queries["inventory_$productId"] = [
|
||||
'sql' => 'SELECT quantity FROM inventory WHERE product_id = ?',
|
||||
'params' => [$productId],
|
||||
'method' => 'queryScalar',
|
||||
];
|
||||
}
|
||||
|
||||
return $this->db->readAhead($queries, Duration::fromSeconds(5));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user