更新
This commit is contained in:
@@ -261,8 +261,13 @@ class QywxPromotionMemberSchedulerService
|
||||
return ['pool_id' => $poolId, 'next_member_id' => 0, 'queued' => false, 'blocked' => true];
|
||||
}
|
||||
$appliedUserIds = self::linkRangeUserIds($linkId);
|
||||
$changed = !QywxPromotionMemberRange::same($range['userids'], $appliedUserIds);
|
||||
$alreadyPending = in_array((int) ($sync['status'] ?? 0), [1, 3], true);
|
||||
$departmentJson = (string) (Db::name('qywx_promotion_link')->where('id', $linkId)->value('range_department_json') ?? '[]');
|
||||
$departmentIds = json_decode($departmentJson, true);
|
||||
$changed = !QywxPromotionMemberRange::same($range['userids'], $appliedUserIds)
|
||||
|| !empty($departmentIds);
|
||||
// 活跃或超时的租约、尚未应用的版本都不能仅凭旧快照被重算成“已同步”。
|
||||
$alreadyPending = in_array((int) ($sync['status'] ?? 0), [1, 2, 3], true)
|
||||
|| (int) ($sync['desired_version'] ?? 0) > (int) ($sync['applied_version'] ?? 0);
|
||||
$needsSync = $changed || $alreadyPending;
|
||||
self::upsertSync($poolId, $linkId, $needsSync, $sync, $now);
|
||||
|
||||
|
||||
@@ -99,33 +99,42 @@ class QywxPromotionRangeSyncService
|
||||
$response = $this->api->getLink($remoteLinkId);
|
||||
$remote = QywxCustomerAcquisitionLinkService::normaliseRemoteResponse($response, $remoteLinkId);
|
||||
$actualUserIds = $remote['range_userids'];
|
||||
if (!QywxPromotionMemberRange::same($actualUserIds, $desiredUserIds)) {
|
||||
if (!QywxPromotionMemberRange::same($actualUserIds, $desiredUserIds)
|
||||
|| $remote['range_department_ids'] !== []) {
|
||||
throw new RuntimeException('企业微信返回的多人路由成员范围与方案可用医助不一致');
|
||||
}
|
||||
$url = $remote['url'];
|
||||
$snapshot = json_encode($remote['snapshot'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
Db::name('qywx_promotion_link')->where('id', (int) $link['id'])->update([
|
||||
'wecom_url' => $url,
|
||||
'remote_status' => 1,
|
||||
'range_user_json' => json_encode($actualUserIds, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||
'range_department_json' => json_encode($remote['range_department_ids'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||
'remote_snapshot' => $snapshot === false ? null : $snapshot,
|
||||
'last_sync_time' => time(),
|
||||
'sync_error' => '',
|
||||
'update_time' => time(),
|
||||
]);
|
||||
|
||||
$freshVersion = (int) (Db::name('qywx_promotion_range_sync')
|
||||
->where('pool_id', $poolId)->value('desired_version') ?? 0);
|
||||
Db::name('qywx_promotion_range_sync')
|
||||
->where('pool_id', $poolId)
|
||||
->where('lock_token', $token)
|
||||
->update([
|
||||
'status' => $freshVersion === $desiredVersion ? 0 : 1,
|
||||
$confirmed = Db::transaction(function () use (
|
||||
$poolId, $token, $desiredVersion, $link, $url, $actualUserIds, $remote, $snapshot
|
||||
): bool {
|
||||
$fresh = Db::name('qywx_promotion_range_sync')->where('pool_id', $poolId)->lock(true)->find();
|
||||
if (!$fresh || (int) ($fresh['status'] ?? 0) === 5) {
|
||||
return false;
|
||||
}
|
||||
if ((string) ($fresh['lock_token'] ?? '') !== $token
|
||||
|| (int) ($fresh['lock_until'] ?? 0) <= time()) {
|
||||
// 过期工作不能覆盖新工作的确认结果。它可能较晚触达企微,需再推一次最新范围。
|
||||
QywxPromotionMemberSchedulerService::requestPoolSync($poolId, (int) $fresh['promotion_link_id']);
|
||||
return false;
|
||||
}
|
||||
Db::name('qywx_promotion_link')->where('id', (int) $link['id'])->update([
|
||||
'wecom_url' => $url,
|
||||
'remote_status' => 1,
|
||||
'range_user_json' => json_encode($actualUserIds, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||
'range_department_json' => json_encode($remote['range_department_ids'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||
'remote_snapshot' => $snapshot === false ? null : $snapshot,
|
||||
'last_sync_time' => time(),
|
||||
'sync_error' => '',
|
||||
'update_time' => time(),
|
||||
]);
|
||||
$isLatest = (int) ($fresh['desired_version'] ?? 0) === $desiredVersion;
|
||||
Db::name('qywx_promotion_range_sync')->where('pool_id', $poolId)->update([
|
||||
'status' => $isLatest ? 0 : 1,
|
||||
'desired_member_id' => 0,
|
||||
'applied_member_id' => 0,
|
||||
'applied_version' => $desiredVersion,
|
||||
'next_retry' => $freshVersion === $desiredVersion ? 0 : time(),
|
||||
'next_retry' => $isLatest ? 0 : time(),
|
||||
'attempts' => 0,
|
||||
'lock_token' => '',
|
||||
'lock_until' => 0,
|
||||
@@ -133,13 +142,19 @@ class QywxPromotionRangeSyncService
|
||||
'update_time' => time(),
|
||||
]);
|
||||
|
||||
return ['status' => 'synced', 'pool_id' => $poolId, 'member_id' => 0];
|
||||
return $isLatest;
|
||||
});
|
||||
|
||||
return ['status' => $confirmed ? 'synced' : 'pending', 'pool_id' => $poolId, 'member_id' => 0];
|
||||
} catch (\Throwable $e) {
|
||||
$attempts = max(1, (int) ($claim['attempts'] ?? 0) + 1);
|
||||
Db::name('qywx_promotion_range_sync')
|
||||
->where('pool_id', $poolId)
|
||||
->where('lock_token', $token)
|
||||
->update([
|
||||
Db::transaction(function () use ($poolId, $token, $attempts, $claim, $e): void {
|
||||
$fresh = Db::name('qywx_promotion_range_sync')->where('pool_id', $poolId)->lock(true)->find();
|
||||
if (!$fresh || (string) ($fresh['lock_token'] ?? '') !== $token
|
||||
|| (int) ($fresh['status'] ?? 0) === 5) {
|
||||
return;
|
||||
}
|
||||
Db::name('qywx_promotion_range_sync')->where('pool_id', $poolId)->update([
|
||||
'status' => 3,
|
||||
'next_retry' => time() + min(300, 15 * $attempts),
|
||||
'lock_token' => '',
|
||||
@@ -147,9 +162,10 @@ class QywxPromotionRangeSyncService
|
||||
'last_error' => mb_substr($e->getMessage(), 0, 500),
|
||||
'update_time' => time(),
|
||||
]);
|
||||
Db::name('qywx_promotion_link')
|
||||
->where('id', (int) ($claim['promotion_link_id'] ?? 0))
|
||||
->update(['sync_error' => mb_substr($e->getMessage(), 0, 500), 'update_time' => time()]);
|
||||
Db::name('qywx_promotion_link')
|
||||
->where('id', (int) ($claim['promotion_link_id'] ?? 0))
|
||||
->update(['sync_error' => mb_substr($e->getMessage(), 0, 500), 'update_time' => time()]);
|
||||
});
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user