- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
107 lines
3.2 KiB
PHP
107 lines
3.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Framework\Async;
|
|
|
|
use App\Framework\Async\AsyncMutex;
|
|
use App\Framework\Async\FiberManager;
|
|
use App\Framework\DateTime\SystemClock;
|
|
use App\Framework\DateTime\SystemTimer;
|
|
|
|
describe('AsyncMutex', function () {
|
|
beforeEach(function () {
|
|
$clock = new SystemClock();
|
|
$timer = new SystemTimer();
|
|
$this->fiberManager = new FiberManager($clock, $timer);
|
|
$this->mutex = new AsyncMutex('test-mutex');
|
|
});
|
|
|
|
it('acquires and releases lock', function () {
|
|
expect($this->mutex->isLocked())->toBeFalse();
|
|
|
|
// Run in fiber context
|
|
$this->fiberManager->async(function () {
|
|
$this->mutex->acquire();
|
|
expect($this->mutex->isLocked())->toBeTrue();
|
|
|
|
$this->mutex->release();
|
|
expect($this->mutex->isLocked())->toBeFalse();
|
|
});
|
|
});
|
|
|
|
it('tries to acquire lock non-blocking', function () {
|
|
$this->fiberManager->async(function () {
|
|
$acquired = $this->mutex->tryAcquire();
|
|
expect($acquired)->toBeTrue();
|
|
expect($this->mutex->isLocked())->toBeTrue();
|
|
|
|
// Try again while locked
|
|
$acquiredAgain = $this->mutex->tryAcquire();
|
|
expect($acquiredAgain)->toBeFalse();
|
|
|
|
$this->mutex->release();
|
|
});
|
|
});
|
|
|
|
it('executes synchronized operation', function () {
|
|
$result = $this->fiberManager->async(function () {
|
|
return $this->mutex->synchronized(function () {
|
|
return 'synchronized-result';
|
|
});
|
|
});
|
|
|
|
expect($result->getReturn())->toBe('synchronized-result');
|
|
expect($this->mutex->isLocked())->toBeFalse(); // Should be released after
|
|
});
|
|
|
|
it('releases lock even if exception occurs', function () {
|
|
$this->fiberManager->async(function () {
|
|
try {
|
|
$this->mutex->synchronized(function () {
|
|
throw new \RuntimeException('error in synchronized block');
|
|
});
|
|
} catch (\RuntimeException $e) {
|
|
// Expected
|
|
}
|
|
|
|
expect($this->mutex->isLocked())->toBeFalse(); // Should still be released
|
|
});
|
|
});
|
|
|
|
it('provides mutex statistics', function () {
|
|
$stats = $this->mutex->getStats();
|
|
|
|
expect($stats)->toHaveKey('name');
|
|
expect($stats)->toHaveKey('locked');
|
|
expect($stats)->toHaveKey('owner');
|
|
expect($stats)->toHaveKey('waiting_fibers');
|
|
|
|
expect($stats['name'])->toBe('test-mutex');
|
|
expect($stats['locked'])->toBeFalse();
|
|
});
|
|
|
|
it('prevents multiple acquisitions', function () {
|
|
$this->fiberManager->async(function () {
|
|
$this->mutex->acquire();
|
|
|
|
$stats = $this->mutex->getStats();
|
|
expect($stats['locked'])->toBeTrue();
|
|
expect($stats['owner'])->not->toBeNull();
|
|
|
|
$this->mutex->release();
|
|
});
|
|
});
|
|
|
|
it('tracks waiting fibers', function () {
|
|
$this->fiberManager->async(function () {
|
|
$this->mutex->acquire();
|
|
|
|
$stats = $this->mutex->getStats();
|
|
expect($stats['waiting_fibers'])->toBe(0); // None waiting yet
|
|
|
|
$this->mutex->release();
|
|
});
|
|
});
|
|
});
|