SuperAPI AI 工具集

resource management

编程与开发

查看项目

更新于 10-16 10:44

技能介绍

用途

本技能用于指导在 Effect(TypeScript)中进行结构化资源管理。Effect 提供结构化资源管理能力,保证即使在发生错误或效果被中断时也能执行清理。这适用于数据库连接、文件句柄、网络套接字、锁和信号量,以及任何需要清理的资源。当用户询问 Effect 资源、acquireRelease、Scope、finalizers、资源清理、Effect.addFinalizer 等话题时使用。

核心概念:Scope

Scope 是一个跟踪资源并确保其清理的上下文:

Effect<A, E, R | Scope>
//              ^^^^^ 表示资源需要清理

主要能力

Effect.acquireRelease

安全资源管理的基本模式:

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
})

// 运行并自动管理 scope
const result = yield* Effect.scoped(program)

Effect.scoped

通过管理 scope 将带 scope 的 effect 转换为常规 effect:

const runnable = Effect.scoped(program)

当 scoped 块完成时 scope 关闭,触发所有 finalizer。

acquireUseRelease 模式

对于更简单的场景,将 acquire/use/release 合并为一次调用:

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))
  )

Finalizers

Effect.addFinalizer —— 向当前 scope 添加清理逻辑:

const program = Effect.gen(function* () {
  yield* Effect.addFinalizer(() =>
    Effect.log("Cleanup running!")
  )

  // ... 执行工作 ...

  return result
})

Effect.ensuring —— 在 effect 完成后(成功或失败)运行清理:

const withCleanup = someEffect.pipe(
  Effect.ensuring(
    Effect.log("Always runs after effect")
  )
)

Effect.onExit —— 根据退出状态运行不同的清理:

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())
  )

锁/Mutex:

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))
    }
  })
)

清理中的错误处理

Finalizer 不应失败,但如果失败:

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")
)

最佳实践

  • 对成对操作使用 acquireRelease——保证清理。
  • 保持 finalizer 简单且不可失败——记录错误而不是抛出。
  • 在合适的边界使用 Effect.scoped——既不过宽也不过窄。
  • 按获取的反序进行清理——Effect 会自动处理。
  • 对服务级资源使用 Layer.scoped——生命周期与 layer 绑定。

额外资源

关于全面的资源管理文档,请查阅 ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt。

搜索以下章节:

  • "Introduction"(Resource Management)了解核心概念
  • "Scope"了解详细的 scope 机制
  • "Managing Layers"了解 Layer.scoped 模式

限制

除上述内容外,本技能的收费、价格、平台支持、实际效果等具体信息暂未提供。