|
|
@@ -125,6 +125,12 @@ abstract class BaseLogCollector
|
|
|
$maxId = 0;
|
|
|
|
|
|
foreach ($records as $record) {
|
|
|
+ // 检查是否已经收集过此记录,避免重复收集
|
|
|
+ if ($this->isDuplicateRecord($this->sourceTable, $record->id)) {
|
|
|
+ $maxId = max($maxId, $record->id);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
$userLogData = $this->convertToUserLog($record);
|
|
|
if ($userLogData) {
|
|
|
$userLogs[] = $userLogData;
|
|
|
@@ -196,14 +202,17 @@ abstract class BaseLogCollector
|
|
|
* 获取上次处理的最大ID
|
|
|
* 从user_logs表中查询该收集器最后处理的记录ID
|
|
|
*
|
|
|
+ * 注意:对于同一个source_table可能有多个source_type的情况(如FundLogCollector),
|
|
|
+ * 需要查询该表的所有记录的最大source_id,而不是仅查询当前source_type的记录
|
|
|
+ *
|
|
|
* @return int
|
|
|
*/
|
|
|
protected function getLastProcessedId(): int
|
|
|
{
|
|
|
try {
|
|
|
- // 直接查询对应表的最大source_id
|
|
|
+ // 查询该source_table的所有记录的最大source_id
|
|
|
+ // 这样可以避免因为动态source_type导致的重复收集问题
|
|
|
$maxId = \App\Module\Game\Models\UserLog::where('source_table', $this->sourceTable)
|
|
|
- ->where('source_type', $this->sourceType)
|
|
|
->max('source_id');
|
|
|
|
|
|
return $maxId ?: 0;
|
|
|
@@ -280,6 +289,9 @@ abstract class BaseLogCollector
|
|
|
/**
|
|
|
* 检查是否为重复记录
|
|
|
*
|
|
|
+ * 注意:不使用source_type进行检查,因为同一个source_table的记录可能有不同的source_type
|
|
|
+ * 只要source_table和source_id相同,就认为是重复记录
|
|
|
+ *
|
|
|
* @param string $sourceTable 源表名
|
|
|
* @param int $sourceId 源记录ID
|
|
|
* @return bool
|
|
|
@@ -287,8 +299,7 @@ abstract class BaseLogCollector
|
|
|
protected function isDuplicateRecord(string $sourceTable, int $sourceId): bool
|
|
|
{
|
|
|
try {
|
|
|
- $exists = \App\Module\Game\Models\UserLog::where('source_type', $this->sourceType)
|
|
|
- ->where('source_table', $sourceTable)
|
|
|
+ $exists = \App\Module\Game\Models\UserLog::where('source_table', $sourceTable)
|
|
|
->where('source_id', $sourceId)
|
|
|
->exists();
|
|
|
|