Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:22:25 +08:00
commit c3294f28aa
60 changed files with 10297 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
# Handling Data Changes During Pagination
## The Problem
**Offset Pagination Issue:** Duplicates or missing records when data changes between page loads.
### Example Scenario
1. User loads page 1 (posts 1-20)
2. New post is inserted at position 1
3. User loads page 2 (posts 21-40)
4. **Post 21 appears on both pages** (was post 20, now post 21)
### Why It Happens
Offset pagination uses absolute positions:
- Page 1: Records at positions 0-19
- Page 2: Records at positions 20-39
When a record is inserted:
- Page 1 positions: 0-19 (includes new record at position 0)
- Page 2 positions: 20-39 (old position 20 is now position 21)
- **Position 20 was seen on page 1, appears again on page 2**
## Cursor Pagination Solution
Cursor pagination is immune to this problem:
```typescript
const posts = await prisma.post.findMany({
take: 20,
skip: cursor ? 1 : 0,
cursor: cursor ? { id: cursor } : undefined,
orderBy: { createdAt: 'desc' },
});
```
**Why it works:**
- Uses record identity (cursor), not position
- Always starts from the last seen record
- New records appear in correct position
- No duplicates or gaps
## Mitigation for Offset Pagination
If you must use offset pagination:
### Strategy 1: Accept the Limitation
Document behavior for admin tools where occasional duplicates are acceptable.
### Strategy 2: Timestamp Filtering
Create stable snapshots using timestamp filtering:
```typescript
const snapshotTime = new Date();
async function getPage(page: number) {
return await prisma.post.findMany({
where: {
createdAt: { lte: snapshotTime },
},
skip: page * pageSize,
take: pageSize,
orderBy: { createdAt: 'desc' },
});
}
```
**Limitations:**
- Doesn't show new records during pagination session
- User must refresh to see new data
### Strategy 3: Switch to Cursor
The best solution is to redesign using cursor pagination.