一、需求
课程下可以创建多个讲次,然后分享出去。
在没有更新分享前,通过分享链接看到的课程及讲次详情是快照。课程制作者可以继续修改调整自己的课程,对分享用户是不可见。
当制作者完成修改后,更新分享,让用户看到的是课程的最新版本。
但是,当制作者仅修改了某个讲次,不进行全量的更新,而仅仅更新那个改动的讲次。
本文主要是讲述如何使用时间戳机制,实现分享的增量更新,而非全量更新。只有首次分享的时候,才会触发全量更新。
二、流程图
三、复制
1、全量更新
第一次分享课程的时候,进行全量复制,这个过程可能会比较耗时,所以异步操作完成。后期文章将会详细介绍。
2、增量更新
当第2讲次有内容变动时,再次分享的时候,只增量更新第2讲次到分享表。
四、数模设计
1、讲次表
name | refresh_date |
---|---|
第一讲次 | 2023-11-17 20:00:00 |
第二讲次 | 2023-11-17 20:00:00 |
第三讲次 | 2023-11-17 20:00:00 |
首次分享之后,把第二讲次修改:
name | refresh_date |
---|---|
第一讲次 | 2023-11-17 20:00:00 |
第二讲次_修改 | 2023-11-17 20:10:00 |
第三讲次 | 2023-11-17 20:00:00 |
2、分享表
首次分享(分享的具体时间是20:05:00):
- 第一阶段
name | last_share_date | share_date |
---|---|---|
第一讲次 | null | 2023-11-17 20:05:00 |
第二讲次 | null | 2023-11-17 20:05:00 |
第三讲次 | null | 2023-11-17 20:05:00 |
- 第二阶段
name | last_share_date | share_date |
---|---|---|
第一讲次 | 2023-11-17 20:05:00 | 2023-11-17 20:05:00 |
第二讲次 | 2023-11-17 20:05:00 | 2023-11-17 20:05:00 |
第三讲次 | 2023-11-17 20:05:00 | 2023-11-17 20:05:00 |
第二次分享(分享的具体时间是20:15:00):
- 第一阶段
name | last_share_date | share_date |
---|---|---|
第一讲次 | 2023-11-17 20:05:00 | 2023-11-17 20:15:00 |
第二讲次_修改 | 2023-11-17 20:05:00 | 2023-11-17 20:15:00 |
第三讲次 | 2023-11-17 20:05:00 | 2023-11-17 20:15:00 |
- 第二阶段
name | last_share_date | share_date |
---|---|---|
第一讲次 | 2023-11-17 20:05:00 | 2023-11-17 20:15:00 |
第二讲次_修改 | 2023-11-17 20:15:00 | 2023-11-17 20:15:00 |
第三讲次 | 2023-11-17 20:05:00 | 2023-11-17 20:15:00 |
六、自问自答
-
为什么上面的分享会分为两个阶段?
分享需要把讲次的内容再次生成快照,这个过程比较耗时,涉及到调用内网的其他服务。所以,我们先保存分享的基本信息,包括本次分享时间。这样,课程的制作者就无需也不能再次分享。因为课程或讲次的编辑时间早于分享时间,换句话说,分享是在编辑之后的行为,快照已经是最新的版本。 -
在分享快照里,同一个课程下的讲次,为什么它们的分享时间不尽相同?
这也正是增量更新的结果所致。可以看到,在第二次分享后,只有第二讲次的分享时间变化了。其他讲次的分享时间,只有当它们对应的讲次发生修改之后,才也会发生变化。 -
为什么分享表中要设计两个分享时间?
分享时间是指每次发起分享的时间,因为我们的课程只要有任意一个讲次变动,都是可以再次发起分享。所以share_date就是我们所理解的分享时间。上面也说到一个关键点,整个分享的实现是异步操作,只有全部完成后,分享才算完成。
既然share_date无法帮助我们实现增量更新,只好再设计一个时间戳字段last_share_date。分享完成前,last_share_date是不更新的,待分享完成后,last_share_date赋值等于share_date。
七、伪代码实现
1、发起分享
Share share = shareRepository.findByCourseNoAndDeletedIsFalse(courseNo);
if (null == share) {
share = new Share();
// 首次分享,上一次分享时间为空,本次分享时间为当前时间
share.setShareDate(DateUtil.date());
} else {
// 记录上一次分享时间
share.setLastShareDate(share.getShareDate());
share.setShareDate(DateUtil.date());
}
shareRepository.save(share);
// 每次分享的时候,发送事件。下文会异步订阅。
2、分享事件
实现增量更新的关键代码
// 讲次
final Lecture lecture = lectureRepository.findByNoAndDeletedIsFalse(share.getCourseNo());
// 最近一次分享时间为空,说明是首次分享
// 最近一次分享时间早于讲次的最新修改时间,说明是二次分享。
// 实现增量更新的关键代码。
if (null == share.getLastShareDate() || share.getLastShareDate().before(lecture.getRefreshDate())) {
// 向外部服务发起请求
// 略
// 最近一次分享的时间也即当前分享的时间
share.setLastShareDate(share.getShareDate());
shareRepository.save(share);
}