feat: implement multi-line session failover with round-robin strategy and session readiness validation for OTP delivery.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user