项目简介
Effect 是一个用于构建健壮、易维护且类型安全的生产级 TypeScript 应用的库。它提供类型化错误处理、依赖注入、结构化并发、调度、链路追踪和统一的数据模式校验。该 monorepo 还包含 Node.js、Bun、Deno 与浏览器的平台包,以及多种 SQL 与 AI 集成。
README 预览
\n\n[](https://pkg.pr.new/~/Effect-TS/effect)\n\n# Effect\n\nEffect is a library for building robust, maintainable, type-safe, and production grade applications in TypeScript. It helps you handle the hard problems at scale: typed errors, dependency injection, structured concurrency, scheduling, tracing, and unified schema validation.\n\n> **Effect 4.x is a long-term support (LTS) release.** If you are upgrading from Effect 3.x, follow the [migration guide](MIGRATION.md).\n\n## Installation\n\n```sh\nnpm install effect\n```\n\n## Requirements\n\n- **TypeScript 5.9 or newer.** TypeScript 7 is recommended for the best performance and compatibility with [Effect's TypeScript tooling](https://github.com/Effect-TS/tsgo#installation).\n- **Node.js 18 or newer** is the general minimum for running Effect on Node.js. Some integration packages require newer runtimes; for example, `@effect/sql-sqlite-node` requires Node.js 22.16 or newer.\n- **Strict type-checking:** the `strict` flag must be enabled in your `tsconfig.json`.\n\n## Links\n\n- [Website](https://effect.website): documentation, guides, and news\n- [Discord](https://discord.gg/effect-ts): ask questions, share what you're building, and talk to the core team\n- [Community](https://effect.website/community-hub): meetups and events, or bring Effect to your own\n- [Issues](https://github.com/Effect-TS/effect/issues): bug reports and feature requests\n- [Jobs](https://effect.website/effect-jobs): companies hiring Effect developers\n- Follow us on [X](https://x.com/EffectTS_), [Bluesky](https://bsky.app/profile/effect-ts.bsky.social), and [LinkedIn](https://www.linkedin.com/company/effect-ts)\n\n## Let's talk\n\nWhether your team is considering Effect, rolling it out, or already running it in production, we'd love to hear from you: what you're building, what works, and what you need from Effect next.\n\n- **Talk to the maintainers.** Introduce your team on [Discord](https://discord.gg/effect-ts) or email [contact@effectful.
常见问题 (2)
故障排除为什么 Effect 的 RequestResolver.persisted 在 staleWhileRevalidate 刷新失败后,仍然持续提供陈旧数据,并且 TTL 还被重新续期?
这是 Effect 4.0.5 中的一个 bug(在 main 分支上仍然存在)。在使用 staleWhileRevalidate 时,当后台刷新的 runAll 作为整个批次失败(或成功但未完成该 entry)时,persisted 会将旧的存储值连同新的 TTL 一起写回,而不是持久化该失败——因此过期的 entry 会被复活并被无限期延长。单个 entry 的失败则能被正确存储。变通方法:让你的 resolver 逐个完成每个请求,而不是让整个 effect 失败。在 resolver 内部捕获错误,并自行使每个 entry 失败:
const resolver = RequestResolver.make<GetValue>((entries) =>
Effect.catchAll(backendCall(entries), (err) =>
Effect.sync(() => {
for (const entry of entries) entry.completeUnsafe(Exit.fail(err))
})
)
)
通过逐个完成 entry,失败会经由 PersistenceStore.setMany 被持久化,且过期值不会被重写。可在 effect-ts issue #9583 中跟踪上游修复进展。
故障排除为什么 Effect 中的 FiberMap.run / FiberHandle.run 在 Scope 关闭时不会等待被替换的 Fiber 完成清理?
在 effect@4.0.5 中,对已被占用的 key/handle 调用 FiberMap.run(或 FiberHandle.run、set、runtime)会中断先前的 fiber 而不等待它,并将其从容器中分离。scope 的 finalizer 只会等待仍在容器中的 fiber,因此 scope 会关闭——释放资源——而此时被替换 fiber 的中断清理(例如 Effect.onInterrupt)仍在运行。在 NodeRuntime.runMain 下,这甚至可能导致进程在收到 SIGTERM 后、该清理完成之前就退出。
解决方法:在替换之前显式移除并等待旧的 fiber,因为 remove/clear 会等待中断完成:
// FiberMap: 先 remove,再 run
yield* FiberMap.remove(map, "k")
yield* FiberMap.run(map, "k", newEffect)
// FiberHandle: 先 clear,再 run
yield* FiberHandle.clear(handle)
yield* FiberHandle.run(handle, newEffect)
这可以保证旧 fiber 的清理在替换启动之前以及 scope 关闭之前完成,从而恢复预期的释放顺序(清理在外层资源释放之前运行)。