|
|
@@ -16,10 +16,11 @@ import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Date;
|
|
|
import java.util.List;
|
|
|
|
|
|
/**
|
|
|
- * 跨库同步:邮件库 mkt_mail_status → 业务库 market_emails,再回写 status_updated_at。
|
|
|
+ * 跨库同步:邮件库 mkt_mail_status → 业务库 market_emails,再回写 synced_at。
|
|
|
* <p>
|
|
|
* 邮件侧走 {@link MktMailStatusService}(@DS mail),业务侧走 trade 数据源;不做跨库事务。
|
|
|
*/
|
|
|
@@ -47,7 +48,7 @@ public class MarketEmailsStatusSyncServiceImpl implements MarketEmailsStatusSync
|
|
|
Long lastId = null;
|
|
|
|
|
|
for (int page = 0; page < MAX_PAGES; page++) {
|
|
|
- // 1. 邮件库:update_time > status_updated_at
|
|
|
+ // 1. 邮件库:status_updated_at > synced_at or synced_at is null
|
|
|
List<MktMailStatusEntity> changes;
|
|
|
try {
|
|
|
changes = mktMailStatusService.listPendingChanges(lastId, BATCH_LIMIT);
|
|
|
@@ -79,16 +80,16 @@ public class MarketEmailsStatusSyncServiceImpl implements MarketEmailsStatusSync
|
|
|
// UNMATCHED:尚无 email_id 关联,不 ack,下次继续等
|
|
|
}
|
|
|
|
|
|
- // 3. 邮件库:回写 status_updated_at
|
|
|
+ // 3. 邮件库:回写 synced_at
|
|
|
if (!syncedMailIds.isEmpty()) {
|
|
|
try {
|
|
|
boolean ackOk = mktMailStatusService.ackStatusSync(syncedMailIds);
|
|
|
if (!ackOk) {
|
|
|
- log.warn("回写 mkt_mail_status.status_updated_at 失败 mailIds={}", syncedMailIds);
|
|
|
+ log.warn("回写 mkt_mail_status.synced_at 失败 mailIds={}", syncedMailIds);
|
|
|
break;
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- log.error("回写 mkt_mail_status.status_updated_at 异常 mailIds={}", syncedMailIds, e);
|
|
|
+ log.error("回写 mkt_mail_status.synced_at 异常 mailIds={}", syncedMailIds, e);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -136,9 +137,11 @@ public class MarketEmailsStatusSyncServiceImpl implements MarketEmailsStatusSync
|
|
|
update.set(MarketEmailsEntity::getHasReply, 1);
|
|
|
changed = true;
|
|
|
}
|
|
|
- //补充首次打开时间(仅在业务表为空时写入,保持“首次”语义)
|
|
|
- if (existing.getFirstOpenTime() == null && change.getFirstOpenTime() != null) {
|
|
|
- update.set(MarketEmailsEntity::getFirstOpenTime, change.getFirstOpenTime());
|
|
|
+ // last_open_time 与 FirstOpenTime 不一致时,回写打开时间并同步 open_count
|
|
|
+ if (change.getLastOpenTime() != null
|
|
|
+ && !sameOpenTime(existing.getFirstOpenTime(), change.getLastOpenTime())) {
|
|
|
+ update.set(MarketEmailsEntity::getFirstOpenTime, change.getLastOpenTime());
|
|
|
+ update.set(MarketEmailsEntity::getOpenCount, change.getOpenCount());
|
|
|
changed = true;
|
|
|
}
|
|
|
//补充首次回复时间
|
|
|
@@ -175,6 +178,16 @@ public class MarketEmailsStatusSyncServiceImpl implements MarketEmailsStatusSync
|
|
|
return TRADE_STATUS_DRAFT;
|
|
|
}
|
|
|
|
|
|
+ private static boolean sameOpenTime(Date existingFirstOpenTime, Date lastOpenTime) {
|
|
|
+ if (existingFirstOpenTime == lastOpenTime) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (existingFirstOpenTime == null || lastOpenTime == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return existingFirstOpenTime.getTime() == lastOpenTime.getTime();
|
|
|
+ }
|
|
|
+
|
|
|
private static Integer resolveReader(MktMailStatusEntity change) {
|
|
|
if (Integer.valueOf(1).equals(change.getOpened()) || Integer.valueOf(1).equals(change.getIsRead())) {
|
|
|
return 1;
|