Resource Management by andrueandersoncs/claude-skill-effect-ts
npx skills add https://github.com/andrueandersoncs/claude-skill-effect-ts --skill 'Resource Management'Effect 提供了结构化的资源管理,即使在发生错误或效果被中断时也能保证清理工作。这对于以下场景至关重要:
Scope 是一个跟踪资源并确保其被清理的上下文:
Effect<A, E, R | Scope>
// ^^^^^ 表示资源需要清理
安全资源管理的基本模式:
import { Effect } from "effect"
const managedFile = Effect.acquireRelease(
Effect.sync(() => fs.openSync("file.txt", "r")),
(fd) => Effect.sync(() => fs.closeSync(fd))
)
const program = Effect.gen(function* () {
const fd = yield* managedFile
const content = yield* Effect.sync(() => fs.readFileSync(fd, "utf-8"))
return content
})
// 通过自动作用域管理运行
const result = yield* Effect.scoped(program)
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
通过管理作用域,将有作用域的效果转换为常规效果:
const runnable = Effect.scoped(program)
当作用域块完成时,作用域关闭,触发所有终结器。
对于更简单的情况,可以在一次调用中组合获取/使用/释放:
const readFile = (path: string) =>
Effect.acquireUseRelease(
Effect.sync(() => fs.openSync(path, "r")),
(fd) => Effect.sync(() => fs.readFileSync(fd, "utf-8")),
(fd) => Effect.sync(() => fs.closeSync(fd))
)
向当前作用域添加清理逻辑:
const program = Effect.gen(function* () {
yield* Effect.addFinalizer(() =>
Effect.log("Cleanup running!")
)
// ... 执行工作 ...
return result
})
在效果完成后(无论成功或失败)运行清理:
const withCleanup = someEffect.pipe(
Effect.ensuring(
Effect.log("Always runs after effect")
)
)
根据退出状态运行不同的清理:
const withExitHandler = someEffect.pipe(
Effect.onExit((exit) =>
Exit.isSuccess(exit)
? Effect.log("Succeeded!")
: Effect.log("Failed or interrupted")
)
)
const program = Effect.gen(function* () {
const db = yield* acquireDbConnection
const cache = yield* acquireRedisConnection
})
const result = yield* Effect.scoped(program)
const program = Effect.gen(function* () {
const [db, cache] = yield* Effect.all([
acquireDbConnection,
acquireRedisConnection
])
})
const DbPool = Effect.acquireRelease(
Effect.promise(() => createPool({
host: "localhost",
database: "mydb",
max: 10
})),
(pool) => Effect.promise(() => pool.end())
)
const query = (sql: string) =>
Effect.gen(function* () {
const pool = yield* DbPool
return yield* Effect.tryPromise(() => pool.query(sql))
})
const withFile = <A>(
path: string,
use: (handle: FileHandle) => Effect.Effect<A>
) =>
Effect.acquireUseRelease(
Effect.promise(() => fs.promises.open(path)),
use,
(handle) => Effect.promise(() => handle.close())
)
const withLock = <A>(
lock: Lock,
effect: Effect.Effect<A>
) =>
Effect.acquireUseRelease(
lock.acquire,
() => effect,
() => lock.release
)
使用 Layer.scoped 处理服务级资源:
const DatabaseLive = Layer.scoped(
Database,
Effect.gen(function* () {
const pool = yield* Effect.acquireRelease(
createPool(),
(pool) => Effect.promise(() => pool.end())
)
return {
query: (sql) => Effect.tryPromise(() => pool.query(sql))
}
})
)
终结器不应失败,但如果失败:
const safeRelease = (resource: Resource) =>
Effect.sync(() => resource.close()).pipe(
Effect.catchAll((error) =>
Effect.logError("Cleanup failed", error)
)
)
const managed = Effect.acquireRelease(
acquire,
safeRelease
)
即使在中断时也会清理资源:
const program = Effect.gen(function* () {
const resource = yield* acquireResource
yield* Effect.sleep("1 hour")
})
const result = yield* program.pipe(
Effect.scoped,
Effect.timeout("1 second")
)
如需全面的资源管理文档,请查阅 ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt。
搜索以下部分:
每周安装量
0
代码仓库
GitHub 星标数
5
首次出现
1970年1月1日
安全审计
Effect provides structured resource management that guarantees cleanup even when errors occur or the effect is interrupted. This is essential for:
A Scope is a context that tracks resources and ensures their cleanup:
Effect<A, E, R | Scope>
// ^^^^^ Indicates resource needs cleanup
The fundamental pattern for safe resource management:
import { Effect } from "effect"
const managedFile = Effect.acquireRelease(
Effect.sync(() => fs.openSync("file.txt", "r")),
(fd) => Effect.sync(() => fs.closeSync(fd))
)
const program = Effect.gen(function* () {
const fd = yield* managedFile
const content = yield* Effect.sync(() => fs.readFileSync(fd, "utf-8"))
return content
})
// Run with automatic scope management
const result = yield* Effect.scoped(program)
Converts a scoped effect into a regular effect by managing the scope:
const runnable = Effect.scoped(program)
The scope closes when the scoped block completes, triggering all finalizers.
For simpler cases, combine acquire/use/release in one call:
const readFile = (path: string) =>
Effect.acquireUseRelease(
Effect.sync(() => fs.openSync(path, "r")),
(fd) => Effect.sync(() => fs.readFileSync(fd, "utf-8")),
(fd) => Effect.sync(() => fs.closeSync(fd))
)
Add cleanup logic to the current scope:
const program = Effect.gen(function* () {
yield* Effect.addFinalizer(() =>
Effect.log("Cleanup running!")
)
// ... do work ...
return result
})
Run cleanup after effect completes (success or failure):
const withCleanup = someEffect.pipe(
Effect.ensuring(
Effect.log("Always runs after effect")
)
)
Run different cleanup based on exit status:
const withExitHandler = someEffect.pipe(
Effect.onExit((exit) =>
Exit.isSuccess(exit)
? Effect.log("Succeeded!")
: Effect.log("Failed or interrupted")
)
)
const program = Effect.gen(function* () {
const db = yield* acquireDbConnection
const cache = yield* acquireRedisConnection
})
const result = yield* Effect.scoped(program)
const program = Effect.gen(function* () {
const [db, cache] = yield* Effect.all([
acquireDbConnection,
acquireRedisConnection
])
})
const DbPool = Effect.acquireRelease(
Effect.promise(() => createPool({
host: "localhost",
database: "mydb",
max: 10
})),
(pool) => Effect.promise(() => pool.end())
)
const query = (sql: string) =>
Effect.gen(function* () {
const pool = yield* DbPool
return yield* Effect.tryPromise(() => pool.query(sql))
})
const withFile = <A>(
path: string,
use: (handle: FileHandle) => Effect.Effect<A>
) =>
Effect.acquireUseRelease(
Effect.promise(() => fs.promises.open(path)),
use,
(handle) => Effect.promise(() => handle.close())
)
const withLock = <A>(
lock: Lock,
effect: Effect.Effect<A>
) =>
Effect.acquireUseRelease(
lock.acquire,
() => effect,
() => lock.release
)
Use Layer.scoped for service-level resources:
const DatabaseLive = Layer.scoped(
Database,
Effect.gen(function* () {
const pool = yield* Effect.acquireRelease(
createPool(),
(pool) => Effect.promise(() => pool.end())
)
return {
query: (sql) => Effect.tryPromise(() => pool.query(sql))
}
})
)
Finalizers should not fail, but if they do:
const safeRelease = (resource: Resource) =>
Effect.sync(() => resource.close()).pipe(
Effect.catchAll((error) =>
Effect.logError("Cleanup failed", error)
)
)
const managed = Effect.acquireRelease(
acquire,
safeRelease
)
Resources are cleaned up even on interruption:
const program = Effect.gen(function* () {
const resource = yield* acquireResource
yield* Effect.sleep("1 hour")
})
const result = yield* program.pipe(
Effect.scoped,
Effect.timeout("1 second")
)
For comprehensive resource management documentation, consult ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt.
Search for these sections:
Weekly Installs
0
Repository
GitHub Stars
5
First Seen
Jan 1, 1970
Security Audits
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
111,800 周安装