Addresses #42 — race condition in EntitlementService usage recording. Changes: 1. New atomic check-and-record methods: - checkAndRecordUsage() — workspace-scoped - checkAndRecordNamespaceUsage() — namespace-scoped These use DB::transaction() with lockForUpdate() on usage records to prevent concurrent requests from reading the same count and both passing the limit check (TOCTOU race). 2. New locked usage query methods: - getLockedCurrentUsage() — bypasses cache, uses SELECT FOR UPDATE - getLockedNamespaceCurrentUsage() — namespace equivalent These are used within the atomic transactions to get a consistent usage count under pessimistic locking. 3. provisionPackage() and provisionNamespacePackage(): Wrapped base-package check-and-cancel in DB::transaction() with lockForUpdate() to prevent duplicate active base packages from concurrent provisioning requests. 4. provisionBoost(): Wrapped in DB::transaction() with lockForUpdate() on existing boosts. Added duplicate detection for blesta_addon_id to prevent the same external addon from being provisioned twice. 5. provisionNamespaceBoost(): Wrapped in DB::transaction() with lockForUpdate() on existing namespace boosts to serialise concurrent provisioning. The existing can() + recordUsage() pattern is preserved for backward compatibility. Callers should migrate to checkAndRecordUsage() for race-safe usage tracking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| EntitlementResult.php | ||
| EntitlementService.php | ||
| EntitlementWebhookService.php | ||
| NamespaceManager.php | ||
| NamespaceService.php | ||
| TotpService.php | ||
| UsageAlertService.php | ||
| UserStatsService.php | ||
| WorkspaceCacheManager.php | ||
| WorkspaceManager.php | ||
| WorkspaceService.php | ||
| WorkspaceTeamService.php | ||