ABDM: auto-expire stale pending consent requests after 1 hour
Previously, clicking 'Fetch ABDM Records' when a prior consent request was stuck in REQUESTED/PENDING (no GRANTED/DENIED callback ever received from the ABDM bridge/PHR - e.g. patient never opened/approved it in their PHR app) would just resume/re-poll that same dead request indefinitely, since getLatestAbdmSyncSnapshot() always prioritized the existing REQUESTED request over starting a new one. Now: - getLatestAbdmSyncSnapshot() computes the age of a REQUESTED/PENDING snapshot's updated_at and marks restart_required = true once it has been pending for more than ABDM_PENDING_STALE_SECONDS (1 hour). - abdm_content_auto_flow() honors this flag: when the last sync is stale, it no longer resumes the old request_id and instead falls through to create a brand-new consent_request against the bridge. Verified locally: a 6h-old stale REQUESTED request for a test ABHA was correctly abandoned and a fresh consent_request was created and granted on the next 'Fetch ABDM Records' click, instead of re-polling the dead request.
This commit is contained in:
parent
2c9e5755d2
commit
37c3592f69
|
|
@ -11,6 +11,11 @@ use App\Models\PatientModel;
|
|||
|
||||
class Patient extends BaseController
|
||||
{
|
||||
// A consent request left in REQUESTED/PENDING for longer than this (no GRANTED/DENIED
|
||||
// callback from the ABDM bridge) is treated as abandoned/stale so "Fetch ABDM Records"
|
||||
// starts a fresh consent request instead of resuming a request that will never resolve.
|
||||
private const ABDM_PENDING_STALE_SECONDS = 3600;
|
||||
|
||||
public function index()
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
|
@ -1367,7 +1372,10 @@ class Patient extends BaseController
|
|||
if ($flowRefId === '') {
|
||||
$lastRequestId = trim((string) ($lastSync['request_id'] ?? ''));
|
||||
$lastPhase = strtoupper(trim((string) ($lastSync['phase'] ?? '')));
|
||||
if ($lastRequestId !== '' && in_array($lastPhase, ['REQUESTED', 'PENDING', 'GRANTED'], true)) {
|
||||
$lastSyncStale = (bool) ($lastSync['restart_required'] ?? false);
|
||||
// Do not resume a stale pending request (older than 1 hour with no bridge
|
||||
// callback) — fall through so a fresh consent_request is created instead.
|
||||
if ($lastRequestId !== '' && ! $lastSyncStale && in_array($lastPhase, ['REQUESTED', 'PENDING', 'GRANTED'], true)) {
|
||||
$flowRefId = $lastRequestId;
|
||||
$consentRequestRef = trim((string) ($lastSync['consent_request_id'] ?? ''));
|
||||
$consentArtifactRef = trim((string) ($lastSync['consent_id'] ?? ''));
|
||||
|
|
@ -3334,11 +3342,34 @@ class Patient extends BaseController
|
|||
$snapshot['updated_at'] = (string) ($best['updated_at'] ?? '');
|
||||
$snapshot['operation'] = (string) ($best['operation'] ?? '');
|
||||
$snapshot['status'] = (string) ($best['status'] ?? '');
|
||||
|
||||
// A consent request stuck in REQUESTED/PENDING for more than ABDM_PENDING_STALE_SECONDS
|
||||
// (1 hour) with no GRANTED/DENIED callback from the bridge is considered abandoned by
|
||||
// PHR/ABHA — the patient likely never saw/approved it, or the bridge silently dropped
|
||||
// it. Flag it so the UI/auto-flow can start a brand-new consent request instead of
|
||||
// resuming (and thus indefinitely polling) a request that will never resolve.
|
||||
$isStalePending = false;
|
||||
if (in_array($snapshot['phase'], ['REQUESTED', 'PENDING'], true) && $snapshot['updated_at'] !== '') {
|
||||
try {
|
||||
$updatedAt = new \DateTimeImmutable($snapshot['updated_at'], new \DateTimeZone('Asia/Kolkata'));
|
||||
$nowIst = new \DateTimeImmutable('now', new \DateTimeZone('Asia/Kolkata'));
|
||||
$pendingAgeSeconds = $nowIst->getTimestamp() - $updatedAt->getTimestamp();
|
||||
$isStalePending = $pendingAgeSeconds > self::ABDM_PENDING_STALE_SECONDS;
|
||||
} catch (\Throwable $e) {
|
||||
$isStalePending = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isStalePending) {
|
||||
$snapshot['message'] = 'Previous consent request has been pending for over 1 hour with no response from ABDM/PHR. Click "Fetch ABDM Records" to start a fresh request.';
|
||||
}
|
||||
|
||||
$snapshot['restart_required'] = (bool) (
|
||||
($snapshot['phase'] === 'FAILED')
|
||||
|| (($snapshot['phase'] === 'REQUESTED')
|
||||
&& ($snapshot['status'] === 'failed')
|
||||
&& stripos((string) ($snapshot['message'] ?? ''), 'not found on bridge') !== false)
|
||||
|| $isStalePending
|
||||
);
|
||||
|
||||
return $snapshot;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user