两处原因,分别处理: 1. contentsync 只按 _id 水位线插新增,源库事后打上的 isDelete 传不过来, 源站删掉的重复集在目标库一直留着。每轮同步后补扫一次 media / media_content / video_info,把源库的软删除标记同步过去,并按 web/service/mediacontentser 的同一口径重算父级 currentEpisode / freeEpisode。只做「源库删了→目标也删」一个方向,不与本地下架保护冲突。 2. 各站 skd 的媒资库同步会为同一集(mediaId+hashId 相同)另插一条自己的 _id, 与 contentsync 带过来的源库那条并存。媒资库那条在 SaleCoin=0 时 listenPermission=2,本该收费的集可以白看。插入时若发现本地已有同一集, 把本地那条 isActive:false 下架;并新增 skd 配置开关 switch.mediaSyncDisabled,非源站可直接关掉这条同步链。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
78 lines
2.7 KiB
Go
78 lines
2.7 KiB
Go
package main
|
|
|
|
// CollSpec 描述一个集合怎么同步。
|
|
//
|
|
// localFields 是「站点本地字段」:目标库自己产生、源库无权覆盖的字段。
|
|
// 判定依据有三类,改动前请先确认属于哪一类:
|
|
// 1. 运行时计数器 —— 各站点自己累积的播放/点赞/收藏/购买数
|
|
// 2. 本地定时任务写入 —— 如 skd/job/hotvalue 会重算并写回 hot
|
|
// 3. 后台运营编排 —— 如 web/service/vidser 写的 happinessPlazaTop、liaoBaTopSort
|
|
//
|
|
// 这些字段走 $setOnInsert:新文档插入时给初值,之后永不再覆盖。
|
|
// 其余字段走 $set。
|
|
//
|
|
// 注意:常规同步只按 _id 水位线取新增,不比对存量修改,所以 $set 实际只在
|
|
// 新文档插入、或手动 --full 重扫时才起作用。
|
|
type CollSpec struct {
|
|
Name string
|
|
// LocalFields 走 $setOnInsert,只在首次插入时写入,之后永不覆盖。
|
|
LocalFields []string
|
|
}
|
|
|
|
// 各集合的本地字段清单,来自对源库与目标库 400/300 条抽样的逐字段比对,
|
|
// 并交叉核对了 web/ 与 skd/ 中的写入点。
|
|
var specs = []CollSpec{
|
|
{
|
|
Name: "video_info",
|
|
LocalFields: []string{
|
|
// 运行时计数器
|
|
"playCount", "fakePlayCount", "effectivePlayCount", "pageViewCount",
|
|
"likeCount", "fakeLikeCount", "collectCount", "forwardCount",
|
|
"shareCount", "fakeShareCount", "commentCount", "fakeCommentCount",
|
|
"validCommentCount", "purchaseCount", "rewarded", "fakeRewarded",
|
|
// 本地 skd 重算:skd/job/hotvalue/video.go
|
|
"hot", "hotCommentExposureUntil", "lastHotTriggerAt",
|
|
// 后台运营编排:web/service/vidser/vid.go
|
|
"happinessPlazaTop", "liaoBaTop", "liaoBaTopSort",
|
|
"isTopping", "isRecommend", "chosen", "chosenDate",
|
|
"sortCode", "tagSort", "recoWeight", "upTag", "shareSort", "worksSort",
|
|
// 本地修改时间戳
|
|
"updatedAt",
|
|
},
|
|
},
|
|
{
|
|
Name: "media",
|
|
LocalFields: []string{
|
|
"countBrowse", "countCollect", "countComment", "countContentPurchases",
|
|
"countDisLike", "countLike", "countPurchases", "countView",
|
|
"hot",
|
|
// 短剧在各站点的编排位
|
|
"choice", "choiceSort", "general", "generalSort", "sectionSort",
|
|
"updateTime", "updatedAt", "updatedAct", "updatedDesc",
|
|
},
|
|
},
|
|
{
|
|
Name: "media_content",
|
|
LocalFields: []string{
|
|
"countBrowse", "countLike", "countPurchases", "fakeCountBrowse",
|
|
"updateTime", "updatedAt", "updatedAct",
|
|
},
|
|
},
|
|
{
|
|
Name: "media_tag",
|
|
LocalFields: []string{"updatedAt"},
|
|
},
|
|
{
|
|
Name: "media_tag_dimension",
|
|
LocalFields: []string{"updatedAt"},
|
|
},
|
|
{
|
|
Name: "tag",
|
|
LocalFields: []string{
|
|
"collCount", "fakeCollCount", "fakePlayCount", "likeCount",
|
|
"playRating", "tPlayCount", "vPlayCount", "videoCount", "hotMark",
|
|
"updatedAt",
|
|
},
|
|
},
|
|
}
|