Add session synchronization tests and ensure atomic session closure
This commit is contained in:
@@ -483,8 +483,8 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
|||||||
if (!$session->markForceStoppedIfOpen($orderId, $eventPayload)) {
|
if (!$session->markForceStoppedIfOpen($orderId, $eventPayload)) {
|
||||||
$summary = $this->getSessionSummary((int)$session->id);
|
$summary = $this->getSessionSummary((int)$session->id);
|
||||||
} else {
|
} else {
|
||||||
$this->logSessionEvent((int)$session->id, selfserve_wash_event_type::SESSION_FORCE_STOPPED, $eventPayload);
|
$this->logSessionEvent((int)$session->id, selfserve_wash_event_type::SESSION_FORCE_STOPPED, $eventPayload);
|
||||||
$summary = $this->getSessionSummary((int)$session->id);
|
$summary = $this->getSessionSummary((int)$session->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
it('serializes self-serve session synchronization before reading or creating open sessions', function (): void {
|
||||||
|
$washFlow = file_get_contents(app_path('modules/selfserve/classes/selfserve_wash_flow.php'));
|
||||||
|
|
||||||
|
expect($washFlow)->not->toBeFalse()
|
||||||
|
->and($washFlow)->toContain('withSessionMutationLock')
|
||||||
|
->and($washFlow)->toContain('sessionMutationLockKey')
|
||||||
|
->and($washFlow)->toContain('set_if_absent_with_expiration')
|
||||||
|
->and($washFlow)->toContain('GET_LOCK');
|
||||||
|
|
||||||
|
$syncOffset = strpos($washFlow, 'public function synchronizeSession');
|
||||||
|
expect($syncOffset)->not->toBeFalse();
|
||||||
|
|
||||||
|
$syncMethod = substr($washFlow, (int)$syncOffset, 9000);
|
||||||
|
$snapshotOffset = strpos($syncMethod, '$snapshot = $this->buildEligibilitySnapshot');
|
||||||
|
$lockOffset = strpos($syncMethod, '$mutationResult = $this->withSessionMutationLock');
|
||||||
|
$findOffset = strpos($syncMethod, '$session = $this->findLatestOpenSession');
|
||||||
|
$addOffset = strpos($syncMethod, '$session = (new selfserve_wash_sessions_o())->add');
|
||||||
|
$relayOffset = strpos($syncMethod, '$this->syncMachineRelayFromVisibleServices');
|
||||||
|
|
||||||
|
expect($snapshotOffset)->not->toBeFalse()
|
||||||
|
->and($lockOffset)->not->toBeFalse()
|
||||||
|
->and($findOffset)->not->toBeFalse()
|
||||||
|
->and($addOffset)->not->toBeFalse()
|
||||||
|
->and($relayOffset)->not->toBeFalse()
|
||||||
|
->and($snapshotOffset)->toBeLessThan($lockOffset)
|
||||||
|
->and($lockOffset)->toBeLessThan($findOffset)
|
||||||
|
->and($findOffset)->toBeLessThan($addOffset)
|
||||||
|
->and($addOffset)->toBeLessThan($relayOffset);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('closes self-serve wash sessions with an atomic open-session guard', function (): void {
|
||||||
|
$sessionObject = file_get_contents(app_path('objects/selfserve_wash_sessions_o.php'));
|
||||||
|
$washFlow = file_get_contents(app_path('modules/selfserve/classes/selfserve_wash_flow.php'));
|
||||||
|
|
||||||
|
expect($sessionObject)->not->toBeFalse()
|
||||||
|
->and($sessionObject)->toContain('markCompletedIfOpen')
|
||||||
|
->and($sessionObject)->toContain('markForceStoppedIfOpen')
|
||||||
|
->and($sessionObject)->toContain('AND `completed_at` IS NULL')
|
||||||
|
->and($sessionObject)->toContain('AND UPPER(TRIM(`status`)) NOT IN ($terminalStatuses)');
|
||||||
|
|
||||||
|
expect($washFlow)->not->toBeFalse()
|
||||||
|
->and($washFlow)->toContain('if (!$session->markCompletedIfOpen($orderId))')
|
||||||
|
->and($washFlow)->toContain('if (!$session->markForceStoppedIfOpen($orderId, $eventPayload))');
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user