feat(guild-messaging): add gap-detection metadata for seq backfill responses
This commit is contained in:
@@ -132,6 +132,26 @@ export class MessagingController {
|
|||||||
? Math.min(requestedLimit, MAX_PAGE_LIMIT)
|
? Math.min(requestedLimit, MAX_PAGE_LIMIT)
|
||||||
: DEFAULT_PAGE_LIMIT;
|
: DEFAULT_PAGE_LIMIT;
|
||||||
|
|
||||||
|
if (from > to) {
|
||||||
|
return {
|
||||||
|
items: [],
|
||||||
|
page: {
|
||||||
|
seqFrom: from,
|
||||||
|
seqTo: to,
|
||||||
|
limit: safeLimit,
|
||||||
|
returned: 0,
|
||||||
|
hasMore: false,
|
||||||
|
nextExpectedSeq: from,
|
||||||
|
highestCommittedSeq: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = await this.channelRepo.findOne({ where: { id: channelId } });
|
||||||
|
if (!channel) {
|
||||||
|
throw new NotFoundException('channel not found');
|
||||||
|
}
|
||||||
|
|
||||||
const qb = this.messageRepo
|
const qb = this.messageRepo
|
||||||
.createQueryBuilder('m')
|
.createQueryBuilder('m')
|
||||||
.where('m.channelId = :channelId', { channelId })
|
.where('m.channelId = :channelId', { channelId })
|
||||||
@@ -143,6 +163,16 @@ export class MessagingController {
|
|||||||
const rows = await qb.limit(safeLimit).getMany();
|
const rows = await qb.limit(safeLimit).getMany();
|
||||||
const items = rows.map((m) => this.toView(m));
|
const items = rows.map((m) => this.toView(m));
|
||||||
|
|
||||||
|
let nextExpectedSeq = from;
|
||||||
|
for (const row of rows) {
|
||||||
|
if (row.seq > nextExpectedSeq) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (row.seq === nextExpectedSeq) {
|
||||||
|
nextExpectedSeq += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items,
|
items,
|
||||||
page: {
|
page: {
|
||||||
@@ -151,6 +181,8 @@ export class MessagingController {
|
|||||||
limit: safeLimit,
|
limit: safeLimit,
|
||||||
returned: items.length,
|
returned: items.length,
|
||||||
hasMore: total > items.length,
|
hasMore: total > items.length,
|
||||||
|
nextExpectedSeq,
|
||||||
|
highestCommittedSeq: channel.lastSeq,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,8 @@
|
|||||||
- [x] seq 分配改为 DB 原子方案(避免并发冲突)
|
- [x] seq 分配改为 DB 原子方案(避免并发冲突)
|
||||||
|
|
||||||
### 2.3 一致性与回补
|
### 2.3 一致性与回补
|
||||||
- [ ] 回补接口:`seq_from/seq_to`
|
- [x] 回补接口:`seq_from/seq_to`
|
||||||
- [ ] 断片检测辅助响应字段(next_expected_seq 等)
|
- [x] 断片检测辅助响应字段(next_expected_seq 等)
|
||||||
- [ ] 幂等键支持(写接口)
|
- [ ] 幂等键支持(写接口)
|
||||||
|
|
||||||
### 2.4 实时通信(MVP 后半)
|
### 2.4 实时通信(MVP 后半)
|
||||||
|
|||||||
Reference in New Issue
Block a user