Files
social-app/docs/bugs/2026-03-27-repository缓存抽象.md
T

141 lines
4.5 KiB
Markdown
Raw Normal View History

# Repository 缓存层抽象优化
## 问题描述
### 现有架构
```
┌─────────────────────────────────────────┐
│ HybridCacheStore │
│ (Memory + Persistent 二级缓存) │
├─────────────────────────────────────────┤
│ CacheEntry<T> │
│ (value + fetchedAt 时间戳) │
├─────────────────────────────────────────┤
│ CachePolicy │
│ (softTtl / hardTtl / minRefreshInterval)│
├─────────────────────────────────────────┤
│ CacheInvalidator │
│ (统一失效管理) │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ CalendarRepository │ ← 重复实现
│ TodoRepository │ ← 重复实现
│ UsersRepository │ ← 重复实现
│ ... │
└─────────────────────────────────────────┘
```
### 重复内容
| 重复内容 | 例子 |
|---------|------|
| key 命名空间 | `calendar:day:$day``todo:list:pending` |
| 缓存读取逻辑 | `store.read<CacheEntry<...>>(key)` |
| 数据转换 | API 返回 → CacheEntry 包装 |
| 刷新逻辑 | `_refreshDayAndRead()` |
| 强制刷新 | `forceRefresh` 参数处理 |
| 后台刷新防重 | `_refreshInFlight` map |
### 涉及文件
- `apps/lib/features/calendar/data/services/calendar_repository.dart`
- `apps/lib/features/todo/data/todo_repository.dart`
- `apps/lib/features/contacts/data/users/users_repository_impl.dart`
- `apps/lib/features/settings/data/services/user_profile_cache_repository.dart`
## 建议方案
### 1. 抽取 `CachedRepository` 基类
```dart
abstract class CachedRepository<T, R> {
HybridCacheStore get store;
CacheInvalidator get invalidator;
CachePolicy get policy;
String get namespace; // 'calendar', 'todo', etc.
Future<T> getOrLoad(
String key, {
bool forceRefresh = false,
required Future<R> Function() loader,
});
Future<void> invalidate(String key);
String buildKey(String suffix);
}
```
### 2. 各模块简化
```dart
// CalendarRepository
class CalendarRepository extends CachedRepository<List<ScheduleItemModel>, ScheduleItemModel> {
@override
String get namespace => 'calendar';
@override
Future<List<ScheduleItemModel>> getDayEvents(DateTime date, {bool forceRefresh}) {
return getOrLoad(
'day:${_formatDate(date)}',
forceRefresh: forceRefresh,
loader: () => calendarService.getEventsForDay(date),
);
}
String _formatDate(DateTime date) =>
'${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
}
// TodoRepository
class TodoRepository extends CachedRepository<List<TodoResponse>, TodoResponse> {
@override
String get namespace => 'todo';
Future<List<TodoResponse>> getPendingTodos({bool forceRefresh = false}) {
return getOrLoad(
'list:pending',
forceRefresh: forceRefresh,
loader: () => api.getPendingTodos(),
);
}
}
```
### 3. 可选:泛型缓存装饰器
```dart
class CachedApiCall<T> {
final HybridCacheStore store;
final CachePolicy policy;
final String key;
final DateTime Function() now;
Future<T> execute(Future<T> Function() loader);
}
```
## 收益
| 收益 | 说明 |
|------|------|
| 减少重复代码 | 各 Repository 移除 60%+ 相似逻辑 |
| 统一缓存行为 | 刷新策略、key 格式、并发控制一致 |
| 易维护 | 修复 bug 或优化逻辑只需改一处 |
| 易测试 | 基类可独立测试,子类继承即可 |
## 前置依赖
- 现有 `HybridCacheStore``CacheEntry``CachePolicy``CacheInvalidator` 已就绪
- 无需引入新依赖
## 状态
- [ ] 待评估优先级
- [ ] 待设计 CachedRepository 基类接口
- [ ] 先在一个 Repository 上试点
- [ ] 推广到其他 Repository