Files
zyt/server/app/common/service/ImChatSyncSession.php
T
2026-09-09 15:47:48 +08:00

72 lines
2.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\common\service;
/** 一次 HTTP 请求只拉一页;只有归档成功后才推进游标。 */
final class ImChatSyncSession
{
public static function start(array $accounts): array
{
return [
'accounts' => array_values(array_unique($accounts)),
'index' => 0, 'side' => 0, 'cursor' => [], 'inserted' => 0, 'errors' => [],
];
}
public static function step(array $state, callable $fetchPage, callable $archive): array
{
if ($state['index'] >= count($state['accounts'])) {
return $state;
}
$account = $state['accounts'][$state['index']];
try {
$page = $fetchPage($account, $state['cursor']);
} catch (\Throwable $e) {
// 失败的会话不妨碍其他医生记录落库,下一轮仍从头补拉该会话。
$state['errors'][] = $account . ($state['side'] === 0 ? '(医生侧)' : '(患者侧)') . '' . $e->getMessage();
return self::nextSide($state);
}
// 落库异常交由调用者处理,绝不能把未归档的页标记为已同步。
$state['inserted'] += $archive($account, $page['msgList']);
if ($page['completed']) {
$state = self::nextSide($state);
} else {
$state['cursor'] = $page['cursor'];
}
return $state;
}
private static function nextSide(array $state): array
{
$state['cursor'] = [];
if ($state['side'] === 0) {
$state['side'] = 1;
} else {
$state['side'] = 0;
$state['index']++;
}
return $state;
}
public static function progress(array $state): array
{
$checking = array_key_exists('accounts_verified', $state) && !$state['accounts_verified'];
$check = $state['account_check'] ?? null;
$completed = !$checking && $state['index'] >= count($state['accounts']);
return [
'completed' => $completed,
'phase' => $checking ? 'checking_accounts' : ($completed ? 'completed' : 'syncing'),
'checked_accounts' => $check['offset'] ?? 0,
'candidate_accounts' => $check ? count($check['candidates']) : 0,
'skipped_accounts' => $check ? count($check['missing']) : 0,
'inserted' => $state['inserted'],
'processed_peers' => $state['index'],
'total_peers' => count($state['accounts']),
'errors' => $state['errors'],
];
}
}