feat: implement multi-line session failover with round-robin strategy and session readiness validation for OTP delivery.

This commit is contained in:
Hamza-Ayed
2026-08-29 22:11:10 +03:00
parent f9609b4403
commit aec9fcee72
4 changed files with 154 additions and 62 deletions
+57 -14
View File
@@ -49,26 +49,25 @@ class WhatsAppSession extends BaseModel
}
/**
* Get next connected session using Round-Robin strategy via Redis
* Get and increment Round-Robin index with Redis and file-based fallback
*/
public static function getRoundRobinSession(int $companyId): ?array
public static function getNextRoundRobinIndex(int $companyId, int $count): int
{
$connectedSessions = static::getConnectedSessionsForCompany($companyId);
if (empty($connectedSessions)) {
// Fallback to legacy single session if no connected sessions are found
return static::findByCompany($companyId, false);
}
$count = count($connectedSessions);
if ($count === 1) {
return $connectedSessions[0];
if ($count <= 1) {
return 0;
}
$rrKey = "rr_index:company_{$companyId}";
$currentIndex = Cache::get($rrKey);
if ($currentIndex === null || !is_numeric($currentIndex)) {
$currentIndex = 0;
// File-based persistent fallback if Redis is unavailable
$tempFile = sys_get_temp_dir() . "/nabeh_rr_company_{$companyId}.txt";
if (file_exists($tempFile)) {
$currentIndex = (int)@file_get_contents($tempFile);
} else {
$currentIndex = 0;
}
} else {
$currentIndex = (int)$currentIndex;
}
@@ -77,8 +76,52 @@ class WhatsAppSession extends BaseModel
$nextIndex = ($selectedIndex + 1) % $count;
Cache::set($rrKey, $nextIndex, 86400);
$tempFile = sys_get_temp_dir() . "/nabeh_rr_company_{$companyId}.txt";
@file_put_contents($tempFile, (string)$nextIndex, LOCK_EX);
return $connectedSessions[$selectedIndex];
return $selectedIndex;
}
/**
* Get all active connected sessions ordered by Round-Robin index for seamless failover
*/
public static function getRoundRobinSessionsList(int $companyId): array
{
$connectedSessions = static::getConnectedSessionsForCompany($companyId);
$count = count($connectedSessions);
if ($count === 0) {
return [];
}
if ($count === 1) {
return $connectedSessions;
}
$startIndex = static::getNextRoundRobinIndex($companyId, $count);
// Reorder list starting from $startIndex: [start..end, 0..start-1]
$ordered = [];
for ($i = 0; $i < $count; $i++) {
$ordered[] = $connectedSessions[($startIndex + $i) % $count];
}
return $ordered;
}
/**
* Get next connected session using Round-Robin strategy via Redis
*/
public static function getRoundRobinSession(int $companyId): ?array
{
$list = static::getRoundRobinSessionsList($companyId);
if (!empty($list)) {
return $list[0];
}
// Fallback to legacy single session if no connected sessions are found
return static::findByCompany($companyId, false);
}
/**