0数据源
0登录域
0重试次数上限
0退避间隔
0自动刷新刻度
堆栈全景 · 调度演示
循环演示
L4消费层 · Consumers
HTML 插件platform.data.get / refresh / subscribe
Renderer 看板allStatuses · fetchPaths · dataChangeEvents
Agent 工具getByName / streamByName
L3数据服务层 · DataHttpServer
REST 拉取GET /data/types/:name · POST …/refresh
状态与连通GET /data/status · POST /data/connectivity/test
SSE 订阅GET /data/stream/:name · GET /data/events
L2中枢核心层 · DataOrchestrator
数据中枢
DataOrchestrator
注册表register / unregister
两级缓存Cache · 磁盘 + 内存
状态与轨迹status · fetchPath
diff 变更通知DataChangeEvent
同域重试调度domainRetry
会话中心SessionCoordinator
L1数据源层 · 按登录域分组
zju.jwxt.edu.cn
provider · zju
成绩单scores
课程表courses
考试安排exams
github.com
未注册 provider
GitHub Starsgithub_stars
Releasesgithub_releases
本地 · 无登录域
不介入重试
插件存储plugin_storage
PHASE 01
初始化调度演示 …
schedulingSnapshot { … }
同域后台重试 · 退避 2s · 上限 3 次
1第 1 次
2第 2 次
3第 3 次
待命
演示为示意循环;prefers-reduced-motion 下自动静止为终态。
💡
机制对照:本演示对应 evg-base/lib/core/data/orchestrator.dart ——
refreshAllStale(过期源并发)→ _scheduleDomainRetry(按登录域登记)→
_runDomainRetries(有 provider 的域域内并发 / 无 provider 的域域内串行)→
_retryOne(退避 2s · 上限 3 次 · 达上限保留 lastError)。
核心机制
6 项
失败重试 · 退避调度
domainRetryDelay · _scheduleDomainRetry
- 拉取失败立即返回,不堵塞调用方 / 启动期并行拉取
- 按 name 去重登记进后台队列,启动 2s Timer
- 后台 Timer 中执行;单源失败只记录,不阻塞同域其他源
关键
次数上限 · 防无限循环
domainRetryMaxAttempts · _retryOne
- 每源独立计数(_domainRetryAttempts),默认 3 次可配置
- 未达上限 → 重新入队,等待下一个周期再试;达上限 → 放弃
- ≤0 完全禁用后台重试;_domainRetryRunning 防重入
关键
最终状态 · 降级语义
DataSourceStatus · 契约⑤
- 成功 → 覆写磁盘+内存缓存 · connected=true
- 重试耗尽 → connected=false · lastError 保留(真实失败)
- 有真实旧缓存 → 仅警告「已展示缓存数据」,永不硬报错
- 空数据门控:空结果视为失败,旧缓存保持可用
状态
订阅刷新 · 时钟对齐
startAutoRefresh · refreshAllStale
- 默认 5 分钟刻度(:00/:05/:10…),首 tick 对齐不立即执行
- 过期源并发刷新(Future.wait),单源失败不拖垮整批
- 报错 ≠ 终态:每个 tick 都会再次尝试失败源,直至成功或注销
周期
变更通知 · diff
DataChangeEvent · data_diff
- 后台刷新覆写缓存且内容实质变化 → 广播变更事件
- 忽略易变字段(ts / timestamp / updatedAt …);首次拉取与空数据不发
- 消费方:addDataChangeListener / dataChangeEvents / SSE /data/events
事件
缓存与取数链
get · fastRead · Cache · 会话重登
- 缓存优先:磁盘 → 内存 → 拉取;过期也返回;fastRead 零 I/O
- 静态兜底 fallback:失败且无旧缓存时返回预设值
- 会话失效:SessionCoordinator 单点重登 → 重拉一次(登录锁分组)
链路
单次拉取阶段链 · fetchPath
T2e 轨迹
01queued
→
02cacheLookup
→
03fetching
→
04validating
→
05caching
→
06done
或
✕failed
成功链 / 失败链循环演示 …
🔁
分支路径:会话失效且注册 provider → refreshSessionFor 单点重登 → 重新进入 fetching 重拉一次;
失败无缓存 → failed 后登记同域后台重试,回到 fetching 周期重试(轨迹 isActive=true · retryCount 累计)。