encore-cache
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEncore Caching (Redis)
Encore 缓存(Redis)
Instructions
说明
Encore's cache is a typed wrapper around Redis. Declare a once, then create objects for each shape of data you need.
CacheClusterKeyspaceEncore 的缓存是对 Redis 的类型化封装。只需声明一次 ,然后为所需的每种数据类型创建相应的 对象。
CacheClusterKeyspaceCluster
集群
typescript
import { CacheCluster } from "encore.dev/storage/cache";
const cluster = new CacheCluster("my-cache", {
evictionPolicy: "allkeys-lru",
});Reference a cluster from another service:
const cluster = CacheCluster.named("my-cache");Eviction policies: (default), , , , , , , .
"allkeys-lru""noeviction""allkeys-lfu""allkeys-random""volatile-lru""volatile-lfu""volatile-ttl""volatile-random"typescript
import { CacheCluster } from "encore.dev/storage/cache";
const cluster = new CacheCluster("my-cache", {
evictionPolicy: "allkeys-lru",
});从另一个服务引用集群:
const cluster = CacheCluster.named("my-cache");淘汰策略:(默认)、、、、、、、。
"allkeys-lru""noeviction""allkeys-lfu""allkeys-random""volatile-lru""volatile-lfu""volatile-ttl""volatile-random"Keyspace types
Keyspace 类型
Each keyspace has a key shape (used to build the Redis key from ) and a value type.
keyPatterntypescript
import {
StringKeyspace,
IntKeyspace,
FloatKeyspace,
StructKeyspace,
StringListKeyspace,
NumberListKeyspace,
StringSetKeyspace,
NumberSetKeyspace,
expireIn,
} from "encore.dev/storage/cache";
// Strings
const tokens = new StringKeyspace<{ tokenId: string }>(cluster, {
keyPattern: "token/:tokenId",
defaultExpiry: expireIn(3600 * 1000),
});
await tokens.set({ tokenId: "abc" }, "value");
const val = await tokens.get({ tokenId: "abc" }); // undefined on miss
// Integers (atomic counters)
const counters = new IntKeyspace<{ userId: string }>(cluster, {
keyPattern: "requests/:userId",
defaultExpiry: expireIn(10 * 1000),
});
const count = await counters.increment({ userId: "user123" }, 1);
// Structs (JSON)
interface UserProfile { name: string; email: string; }
const profiles = new StructKeyspace<{ userId: string }, UserProfile>(cluster, {
keyPattern: "profile/:userId",
defaultExpiry: expireIn(3600 * 1000),
});
await profiles.set({ userId: "123" }, { name: "Alice", email: "alice@example.com" });
// Lists
const recent = new StringListKeyspace<{ userId: string }>(cluster, {
keyPattern: "recent/:userId",
});
await recent.pushRight({ userId: "user123" }, "item1", "item2");
// Sets
const tags = new StringSetKeyspace<{ articleId: string }>(cluster, {
keyPattern: "tags/:articleId",
});
await tags.add({ articleId: "post1" }, "typescript", "encore");
const has = await tags.contains({ articleId: "post1" }, "typescript");每个 keyspace 都有一种键结构(用于根据 构建 Redis 键)和一种值类型。
keyPatterntypescript
import {
StringKeyspace,
IntKeyspace,
FloatKeyspace,
StructKeyspace,
StringListKeyspace,
NumberListKeyspace,
StringSetKeyspace,
NumberSetKeyspace,
expireIn,
} from "encore.dev/storage/cache";
// Strings
const tokens = new StringKeyspace<{ tokenId: string }>(cluster, {
keyPattern: "token/:tokenId",
defaultExpiry: expireIn(3600 * 1000),
});
await tokens.set({ tokenId: "abc" }, "value");
const val = await tokens.get({ tokenId: "abc" }); // undefined on miss
// Integers (atomic counters)
const counters = new IntKeyspace<{ userId: string }>(cluster, {
keyPattern: "requests/:userId",
defaultExpiry: expireIn(10 * 1000),
});
const count = await counters.increment({ userId: "user123" }, 1);
// Structs (JSON)
interface UserProfile { name: string; email: string; }
const profiles = new StructKeyspace<{ userId: string }, UserProfile>(cluster, {
keyPattern: "profile/:userId",
defaultExpiry: expireIn(3600 * 1000),
});
await profiles.set({ userId: "123" }, { name: "Alice", email: "alice@example.com" });
// Lists
const recent = new StringListKeyspace<{ userId: string }>(cluster, {
keyPattern: "recent/:userId",
});
await recent.pushRight({ userId: "user123" }, "item1", "item2");
// Sets
const tags = new StringSetKeyspace<{ articleId: string }>(cluster, {
keyPattern: "tags/:articleId",
});
await tags.add({ articleId: "post1" }, "typescript", "encore");
const has = await tags.contains({ articleId: "post1" }, "typescript");Multi-field key patterns
多字段键模式
typescript
interface Key { userId: string; resourcePath: string; }
const requests = new IntKeyspace<Key>(cluster, {
keyPattern: "requests/:userId/:resourcePath",
defaultExpiry: expireIn(10 * 1000),
});typescript
interface Key { userId: string; resourcePath: string; }
const requests = new IntKeyspace<Key>(cluster, {
keyPattern: "requests/:userId/:resourcePath",
defaultExpiry: expireIn(10 * 1000),
});Expiry helpers
过期时间辅助函数
typescript
import {
expireIn, // milliseconds
expireInSeconds,
expireInMinutes,
expireInHours,
expireDailyAt, // a specific UTC time each day
neverExpire,
keepTTL, // keep existing TTL when updating
} from "encore.dev/storage/cache";typescript
import {
expireIn, // milliseconds
expireInSeconds,
expireInMinutes,
expireInHours,
expireDailyAt, // a specific UTC time each day
neverExpire,
keepTTL, // keep existing TTL when updating
} from "encore.dev/storage/cache";Write options
写入选项
typescript
await keyspace.set(key, value, { expiry: expireInMinutes(30) });
await keyspace.set(key, value, { expiry: keepTTL });
await keyspace.setIfNotExists(key, value); // throws CacheKeyExists if present
await keyspace.replace(key, value); // throws CacheMiss if absenttypescript
await keyspace.set(key, value, { expiry: expireInMinutes(30) });
await keyspace.set(key, value, { expiry: keepTTL });
await keyspace.setIfNotExists(key, value); // throws CacheKeyExists if present
await keyspace.replace(key, value); // throws CacheMiss if absentErrors
错误
typescript
import { CacheMiss, CacheKeyExists } from "encore.dev/storage/cache";
const value = await keyspace.get(key); // undefined on miss (does not throw)typescript
import { CacheMiss, CacheKeyExists } from "encore.dev/storage/cache";
const value = await keyspace.get(key); // undefined on miss (does not throw)Guidelines
指南
- Declare and keyspaces at package level.
CacheCluster - Pick the most specific keyspace type — for counters gives you atomic
IntKeyspace/incrementfor free.decrement - returns
get()on miss;undefinedandreplace()throw on conflict.setIfNotExists() - Local development uses an in-memory Redis with a ~100-key cap — don't load-test it.
- For durable storage, use (Postgres) or
encore-database(object storage) instead.encore-bucket
- 在包级别声明 和 keyspace。
CacheCluster - 选择最具体的 keyspace 类型——对于计数器,可直接提供原子的
IntKeyspace/increment。decrement - 在未命中时返回
get();undefined和replace()在发生冲突时抛出异常。setIfNotExists() - 本地开发使用带约 100 个键上限的内存版 Redis——不要对其进行负载测试。
- 对于持久化存储,请改用 (Postgres)或
encore-database(对象存储)。encore-bucket