fn_b/docs/maintenance/ARTICLE_LIKES.md

58 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 文章自动点赞维护
适用FNA_V3;2026-10-29用户要求新增“一年内增加指定额度,完成后停止”,并为后续AI新文章配置默认参数。AI写作默认值与业务口径的唯一正文为[写作规范](../content/WRITING.md#ai-新文章的点赞参数2026-10-29),发布调用入口为[独立文章API](EDITORIAL_API.md)。2026-10-29已按用户“上线,把之前没处理的文章也处理”授权发布正式cfn并补齐10篇教程,test未更新,本机调度未启动。部署与回退记录见本文末尾。
## 三项独立机制
- 原短期机制:`i7like`为剩余量,`article:sync-likes`按原随机逻辑扣减。保留原年龄窗口及频率实现,没有借本次改造重写短期算法。
- 原持续年度机制:`i365like`为每日中奖概率的分子,每日只按原缓存日期锁执行一轮,不扣余额、不以一年为终点。参数50是统计期望,不是精确年度配额;该原有缓存锁不等同于数据库并发锁。
- 新一次性年度机制:`iYearLikeTarget`是本轮额外增加量,`iYearLikeAdded`是本轮已增加量,`sYearLikeStartedAt`是开始时间。三项分别保存,不能用总点赞数倒推本轮进度,也不能拿其他机制或真实点赞抵扣本轮额度。
## 新年度额度的执行
`app/Services/OneYearArticleLikes.php`负责进度,沿用现有每5分钟的`article:sync-likes`调度,不新增独立cron。`due = floor(target × 已过秒数 / 本日历年总秒数)`,实际增加`max(0, due - added)`;已过时间限制在0~一年长度之间。起点到周年日计算使用`addYearNoOverflow`,闰日对应下一年2月28日。完成后保留target和added供核对,后续扫描不再选中满额文章。
未公开文章不执行;暂停期间仍按原开始时间计时,重新公开后补至应有进度,不自动延长周期。没有开始时间但额度非零的手动计划,首次执行只填当前时间,不按旧文章创建日追补。调度延误时下一次执行补到应有量,周年后恢复则补足余额;停机时不能保证准点完成。
每篇通过事务与`lockForUpdate`读取最新进度,额度计数和总点赞数在同一次SQL更新中累加,防止本项重入重复支付,并保留同时发生的真实点赞。使用Query Builder避免触发文章内容`updated_at`、模型搜索同步等副作用;仅更新`iLikeCount`、`iYearLikeAdded`、`sLastLikedAt`,任务结束后刷新原“点赞活跃”缓存。其他两项原有代码保留。
## 独立文章API
`Publisher::draft()`支持可选`like_settings`对象,键为`seven_day`、`yearly`、`one_year`;创建新文章时缺省键使用写作规范默认值。`seven_day`与`one_year`接受0~1000000整数,`yearly`接受0~365整数;0关闭对应机制。保存草稿时为每篇独立取随机值并保存在冻结items中,`getDraft()`返回实际设置,查询及同请求重试不再随机。
发布新文章时将冻结值落入对应字段,已支付为0,年度开始时间为实际发布时间。更改现有文章、显式接管和内容回退保留全部计数、参数与年度进度;已存在文章的普通改稿不接受`like_settings`,返回422,防止重写时意外重置。旧版本冻结草稿没有该对象的,保留其原来全0语义,不在发布时临时抽值。
鉴权`GET source-articles/{id}`返回`like_growth`:`seven_day_remaining`、`yearly`、`one_year_target`、`one_year_added`、`one_year_started_at`,只用于维护回读,不进入公开模板或文章正文。内容回退不回退点赞进度。
## 迁移、验证与回退
新增迁移`database/migrations/2026_10_29_200000_add_one_year_article_likes.php`仅给articles增加三列,默认0/0/null,不启用旧文计划。部署时先备份并执行这一条指定迁移,再启用依赖新字段的应用/任务代码,不执行整库重置或导入。
```sh
php artisan migrate --path=database/migrations/2026_10_29_200000_add_one_year_article_likes.php --force
```
2026-10-29已在本地`fna_v3`执行此迁移;迁移前后170篇原有行字段SHA256一致,现有启用新计划数为0。证据为`output/article-like-growth-20261029/local-before.json`、`local-after.json`。正常命令依赖现有系统调度器;本次没有手工运行真实数据的加赞任务或安装cron。
测试位于`tests/Feature/OneYearArticleLikesTest.php`、`tests/Feature/EditorialApiTest.php`,使用SQLite内存数据库。覆盖渐进增加、满额停止、重复执行、真实赞独立、原年度机制独立继续、停机补进度、禁用/未来开始时间、闰日、空起点、CLI任务接入、草稿随机默认值稳定、发布映射、编辑保留和非法输入;结果为23项测试、225次断言全部通过,回执见输出目录tests.xml。原项目存在命令类文件名与类名不一致的遗留注册问题,测试沿用原编辑API测试的独立进程模式避免重复注册,不修改无关遗留命令。
回退功能时先停用调用新service的任务代码及新版发布代码,保留新字段和历史进度。不要在仍有新版写入者时drop列;需要撤销迁移时先备份新字段、确认没有活动计划和依赖调用方,再在独立维护窗口执行其down。已有文章总点赞数不会自动减回,避免删除真实/其他来源的赞。
本地鉴权`source-articles/365`只读HTTP回读200,新进度字段返回正确的0/0/null,原有文章字段哈希保持一致;证据为输出目录source-check.json。未发布临时文章、未触发真实文章加赞。
## 已有编辑文章补配命令
`article:backfill-editorial-likes`默认只预览;显式`--apply`才写入。仅处理editorial_documents已绑定且已发布的文章,不处理日更资源。目标额、已支付量均为0且开始时间为空时才补一次性年度额度;短期和持续年度参数同时为0的,另补默认值。已有年度参数和短期余额保留,已过短期窗口的文章不重启短期计划。使用事务行锁,重复执行候选数为0,不重抽、不覆盖进度,也不修改正文、总点赞数和内容日期。
## 正式部署与补齐(2026-10-29)
- 生产目录`/www/wwwroot/clashfreenode-new.com`经白色机SSH更新到已推送Git提交`ea394987069cc0e7a980c60ebe2dc845c03b5fbe`,分支`codex/article-like-growth-20261029`,父提交`cbb847aed89f5452fdbd351968cc2b9c993d9f66`。后续如有仅文档提交,应用代码仍以上述提交为准。
- 服务器私有恢复点`VPS-003:/root/backups/cfn-likes-20261029/`:生产数据库一致性快照、Git bundle、原生成模板、补配前公开文章快照、补配预览和回执。秘密与数据库备份未导出本机。
- 只执行本次指定迁移。10篇教程全部补新增年度额度:原7篇ID206~212分别253/204/137/492/194/297/274,原短期余额0及持续年度30/30/40/30/30/30/50保持。3篇新文:DNS ID375短期30/持续年度50/一次性444;系统代理TUN ID376为34/50/106;Windows ID377为23/50/165。一次性额度从本次补配时计时。
- 生产184篇文章完整保留;补配阶段总点赞数、正文、创建/更新时间、标签和其他元数据不改,174篇资源文章逐行不变。命令重复执行候选数为0;任务正常执行后的短期赞数可持续变化,不能把初始额度当作当前剩余。
- 验证任务时发现原root调度创建的文件缓存目录造成nginx无权刷新,且发布前已有同类真实点赞报错。仅将该站现有每分钟schedule:run条目的PHP执行用户改为nginx,原调度频率、工作目录、日志重定向和其他cron条目保留;业务命令仍由Laravel每5分钟调度。修复该站file cache下6个root所有项的归属,权限模式不扩大;原cron和权限元数据已私有备份。随后以nginx执行命令成功,新增额度与短期原逻辑均接入。
- 2026-10-29 13:32:52 UTC服务器侧首页、综合栏目及系统代理TUN文章HTTP200;编辑API维持关闭,生产环境和原生成模板保留。没有修改广告、Resource、test、DNS、Nginx或其他站点。未做线上页面验收。
- 非秘密发布回执:[ARTICLE_LIKES_RELEASE_2026-10-29.json](ARTICLE_LIKES_RELEASE_2026-10-29.json)。已观察13:35:01 UTC(北京时间21:35:01)自动刷新,缓存写入用户nginx;手动验收后另有4次新调度唤起,证据在回执`automatic_schedule`字段,未为观察再次手动加赞。
回退本次代码可检出上述父提交,但保留新增列、已支付进度及增加的总赞,不自动扣赞或覆盖整库。需要撤销某个额度时先依据本次精确回执、当前已支付量及并行配置生成定点方案;不得把原始快照整行回灌。已修复的调度用户与缓存权限默认保留,不能为回退代码重新引入root缓存写入问题;其原始状态仍留恢复点供审计。