8.8 KiB
文章自动点赞维护
适用FNA_V3;2026-10-29用户要求新增“一年内增加指定额度,完成后停止”,并为后续AI新文章配置默认参数。AI写作默认值与业务口径的唯一正文为写作规范,发布调用入口为独立文章API。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,不启用旧文计划。部署时先备份并执行这一条指定迁移,再启用依赖新字段的应用/任务代码,不执行整库重置或导入。
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。已观察13:35:01 UTC(北京时间21:35:01)自动刷新,缓存写入用户nginx;手动验收后另有4次新调度唤起,证据在回执
automatic_schedule字段,未为观察再次手动加赞。
回退本次代码可检出上述父提交,但保留新增列、已支付进度及增加的总赞,不自动扣赞或覆盖整库。需要撤销某个额度时先依据本次精确回执、当前已支付量及并行配置生成定点方案;不得把原始快照整行回灌。已修复的调度用户与缓存权限默认保留,不能为回退代码重新引入root缓存写入问题;其原始状态仍留恢复点供审计。