|
@@ -45,10 +45,20 @@ class BetFactSynchronizer
|
|
|
$highestIdAtStart = $cursorEnabled ? (int) DB::table($table)->max('id') : 0;
|
|
$highestIdAtStart = $cursorEnabled ? (int) DB::table($table)->max('id') : 0;
|
|
|
$errorCount = count($result['errors']);
|
|
$errorCount = count($result['errors']);
|
|
|
$query = DB::table($table);
|
|
$query = DB::table($table);
|
|
|
- if ($table === 'lhc_order' && ($legacyMaxId = (int) config('sharing.lottery_legacy_max_id', 0)) > 0) {
|
|
|
|
|
- $query->where('id', '>', $legacyMaxId);
|
|
|
|
|
|
|
+ $legacyMaxId = $table === 'lhc_order' ? (int) config('sharing.lottery_legacy_max_id', 0) : 0;
|
|
|
|
|
+ $hasLotteryItems = $table === 'lhc_order' && Schema::hasTable('lhc_order_item');
|
|
|
|
|
+ $legacyBackfillMaxId = $hasLotteryItems ? $legacyMaxId : 0;
|
|
|
|
|
+ if ($legacyMaxId > 0) {
|
|
|
|
|
+ $query->where(function ($query) use ($legacyMaxId, $hasLotteryItems) {
|
|
|
|
|
+ $query->where('id', '>', $legacyMaxId);
|
|
|
|
|
+ if ($hasLotteryItems) {
|
|
|
|
|
+ $query->orWhereExists(DB::table('lhc_order_item')->selectRaw('1')
|
|
|
|
|
+ ->whereColumn('lhc_order_item.ordernum', 'lhc_order.ordernum'));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
$lastRun = null;
|
|
$lastRun = null;
|
|
|
|
|
+ $reconciledLegacyId = 0;
|
|
|
$scannedIds = [];
|
|
$scannedIds = [];
|
|
|
$process = function (int $id) use ($table, $from, $to, $write, &$result) {
|
|
$process = function (int $id) use ($table, $from, $to, $write, &$result) {
|
|
|
$result['scanned']++;
|
|
$result['scanned']++;
|
|
@@ -66,12 +76,17 @@ class BetFactSynchronizer
|
|
|
$lastRun = DB::table('share_system_state')->where('key', 'facts_cursor:' . $table)->value('value');
|
|
$lastRun = DB::table('share_system_state')->where('key', 'facts_cursor:' . $table)->value('value');
|
|
|
if ($lastRun) {
|
|
if ($lastRun) {
|
|
|
$cursor = json_decode($lastRun, true, 512, JSON_THROW_ON_ERROR);
|
|
$cursor = json_decode($lastRun, true, 512, JSON_THROW_ON_ERROR);
|
|
|
|
|
+ $reconciledLegacyId = (int) ($cursor['lottery_children_checked_through'] ?? 0);
|
|
|
$cutoff = EffectiveBet::time($cursor['updated_at'])->subMinutes(5);
|
|
$cutoff = EffectiveBet::time($cursor['updated_at'])->subMinutes(5);
|
|
|
$cutoffValue = in_array($table, ['lhc_order', 'sport_order'], true)
|
|
$cutoffValue = in_array($table, ['lhc_order', 'sport_order'], true)
|
|
|
? $cutoff->timestamp : $cutoff->setTimezone('Asia/Shanghai')->format('Y-m-d H:i:s');
|
|
? $cutoff->timestamp : $cutoff->setTimezone('Asia/Shanghai')->format('Y-m-d H:i:s');
|
|
|
- $query->where(function ($query) use ($cursorColumn, $cutoffValue, $cursor) {
|
|
|
|
|
|
|
+ $query->where(function ($query) use ($cursorColumn, $cutoffValue, $cursor, $legacyBackfillMaxId, $reconciledLegacyId) {
|
|
|
$query->where($cursorColumn, '>=', $cutoffValue)->orWhereNull($cursorColumn)
|
|
$query->where($cursorColumn, '>=', $cutoffValue)->orWhereNull($cursorColumn)
|
|
|
->orWhere('id', '>', (int) $cursor['last_id']);
|
|
->orWhere('id', '>', (int) $cursor['last_id']);
|
|
|
|
|
+ // Old cursors skipped this ID range even when child bets existed. Catch it up once.
|
|
|
|
|
+ if ($legacyBackfillMaxId > $reconciledLegacyId) {
|
|
|
|
|
+ $query->orWhereBetween('id', [$reconciledLegacyId + 1, $legacyBackfillMaxId]);
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -82,12 +97,18 @@ class BetFactSynchronizer
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
if ($cursorEnabled && count($result['errors']) === $errorCount) {
|
|
if ($cursorEnabled && count($result['errors']) === $errorCount) {
|
|
|
|
|
+ $cursor = ['updated_at' => $startedAt, 'last_id' => $highestIdAtStart];
|
|
|
|
|
+ if ($legacyBackfillMaxId > 0 || $reconciledLegacyId > 0) {
|
|
|
|
|
+ $cursor['lottery_children_checked_through'] = max($legacyBackfillMaxId, $reconciledLegacyId);
|
|
|
|
|
+ }
|
|
|
DB::table('share_system_state')->updateOrInsert(['key' => 'facts_cursor:' . $table],
|
|
DB::table('share_system_state')->updateOrInsert(['key' => 'facts_cursor:' . $table],
|
|
|
- ['value' => json_encode(['updated_at' => $startedAt, 'last_id' => $highestIdAtStart]),
|
|
|
|
|
|
|
+ ['value' => json_encode($cursor),
|
|
|
'updated_at' => $startedAt, 'created_at' => $startedAt]);
|
|
'updated_at' => $startedAt, 'created_at' => $startedAt]);
|
|
|
}
|
|
}
|
|
|
// Runs after the cursor is saved: a source that keeps failing here must not hold the cursor back.
|
|
// Runs after the cursor is saved: a source that keeps failing here must not hold the cursor back.
|
|
|
- if ($lastRun) $this->repairFinishedOrders($table, $scannedIds, $process, $result);
|
|
|
|
|
|
|
+ if ($lastRun && ($table !== 'lhc_order' || $hasLotteryItems)) {
|
|
|
|
|
+ $this->repairFinishedOrders($table, $scannedIds, $process, $result);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
$result['changed_dates'] = array_values($result['changed_dates']);
|
|
$result['changed_dates'] = array_values($result['changed_dates']);
|
|
|
sort($result['changed_dates']);
|
|
sort($result['changed_dates']);
|
|
@@ -146,7 +167,6 @@ class BetFactSynchronizer
|
|
|
if ($table === 'lhc_order') {
|
|
if ($table === 'lhc_order') {
|
|
|
$query = DB::table('lhc_order')->where('lottery_status', '<>', 0)
|
|
$query = DB::table('lhc_order')->where('lottery_status', '<>', 0)
|
|
|
->whereIn('ordernum', DB::table('lhc_order_item')->whereIn('id', $sourceIds)->distinct()->pluck('ordernum')->all());
|
|
->whereIn('ordernum', DB::table('lhc_order_item')->whereIn('id', $sourceIds)->distinct()->pluck('ordernum')->all());
|
|
|
- if (($legacyMaxId = (int) config('sharing.lottery_legacy_max_id', 0)) > 0) $query->where('id', '>', $legacyMaxId);
|
|
|
|
|
} elseif ($table === 'sport_order') {
|
|
} elseif ($table === 'sport_order') {
|
|
|
$query = DB::table('sport_order')->whereIn('id', $sourceIds)
|
|
$query = DB::table('sport_order')->whereIn('id', $sourceIds)
|
|
|
->where(fn ($q) => $q->where('settlement_status', 1)->orWhere('status', 2)->orWhere('return_status', 2));
|
|
->where(fn ($q) => $q->where('settlement_status', 1)->orWhere('status', 2)->orWhere('return_status', 2));
|