文件与缓存是后端的两大"隐性基础设施"。Encore 把它们同样收进声明式原语:Bucket 映射 S3/GCS,CacheCluster 映射 Redis,附带一套很少见的类型安全键空间设计。
包级变量(老规矩);本地由框架模拟,云上映射 Amazon S3、Google Cloud Storage 或任意 S3 兼容服务(MinIO 等,自托管时在 infra 配置指定)。
错误类型:ObjectNotFound(对象不存在)、PreconditionFailed(上传前置条件不满足)、ObjectsError(基类)。
大文件让客户端直连对象存储,不过服务器中转:
典型流程:前端请求你的 API → API 鉴权后返回 signed URL → 前端直接 PUT/GET 对象存储。服务器带宽零占用,权限窗口受 TTL 约束。
把桶访问权传给其他模块时,不传整个桶对象,传带权限约束的引用:
可选权限:Downloader / Uploader / Lister / Attrser / Remover / ReadWriter(组合权限)。引用必须在服务内创建——静态分析器据此把"哪个服务对哪个桶有什么权限"画进应用模型,云上生成对应的最小 IAM 策略。这是"声明即权限"的少见实现:权限收敛不靠运维配置,靠代码里的类型参数。
驱逐策略:allkeys-lru(默认)/ noeviction / allkeys-lfu / allkeys-random / volatile-lru / volatile-lfu / volatile-ttl / volatile-random——即 Redis 原生策略集。
云上映射托管 Redis(AWS ElastiCache / GCP Memorystore);本地是内存模拟,约 100 个键上限——本地只验证逻辑,不做容量测试。
Encore 不让你直接拼 Redis key 字符串,而是声明键空间:键的结构、值的类型、过期策略都进类型系统:
键空间家族全表:
| Keyspace | 值类型 | 特有操作 |
|---|---|---|
| StringKeyspace | string | get / set / delete |
| IntKeyspace | 整数 | increment / decrement |
| FloatKeyspace | 浮点 | increment |
| StructKeyspace | 任意接口 | get / set / delete |
| StringListKeyspace / NumberListKeyspace | 列表 | pushLeft / pushRight / popLeft / popRight / getRange / items |
| StringSetKeyspace / NumberSetKeyspace | 集合 | add / remove / contains / items |
错误与缺失语义:get() miss 返回 undefined(不抛错);replace() miss 抛 CacheMiss;setIfNotExists 冲突抛 CacheKeyExists。
keyPattern 的工程价值 keyPattern: "flight/:flightNo/:date" 把 Redis 最常见的事故源——手拼 key 时的拼写不一致、参数漏拼——变成编译期问题:键的字段名和类型都在泛型里,拼错编译不过。等于把团队的"Redis key 命名规范文档"直接写成了类型。
| 需求 | 用什么 |
|---|---|
| 行程单 PDF、发票、用户上传凭证 | Bucket(私有 + signedDownloadUrl) |
| 前端静态资源 / 公开图片 | Bucket(public: true)或 api.static |
| 会话、验证码、限流计数 | CacheCluster(短 TTL keyspace) |
| 航班搜索结果缓存 | StructKeyspace + 分钟级过期 |
| 必须不丢的业务数据 | 都不是——进 SQLDatabase;缓存与对象存储都不承诺持久语义(volatile 策略下缓存会被驱逐) |
请继续阅读:第10章:鉴权。