AGENT SKILL

04-resources

Effect-TS 4 resource management — Scope, acquireRelease, Layer.scoped, and safe resource lifecycle

License 许可
MIT
最近更新
2026-05-31
Stars
★ 0
Forks
0

01 前言 Front Matter

name
04-resources
license
MIT
description
Effect-TS 4 resource management — Scope, acquireRelease, Layer.scoped, and safe resource lifecycle
compatibility
opencode

03 SKILL.md 正文

Resource Management

acquireRelease — safe open/close pair

The release is guaranteed to run even on interruption or failure.

import { Effect } from "effect";

const connection =
  yield *
  Effect.acquireRelease(
    Effect.sync(() => db.connect()), // acquire
    (conn) => Effect.sync(() => conn.close()), // release — always runs
  );

Layer.scoped — resource tied to layer lifetime

Use when the resource should live as long as the layer's scope.

import { Context, Effect, Layer } from "effect";

export class DbPool extends Context.Service<
  DbPool,
  {
    query(sql: string): Effect.Effect<Array<unknown>>;
  }
>()("myapp/DbPool") {
  static readonly layer = Layer.scoped(
    DbPool,
    Effect.gen(function* () {
      const pool = yield* Effect.acquireRelease(
        Effect.promise(() => createPool(config)),
        (p) => Effect.promise(() => p.end()),
      );
      return DbPool.of({
        query: Effect.fn("DbPool.query")(function* (sql) {
          return yield* Effect.promise(() => pool.query(sql));
        }),
      });
    }),
  );
}

Effect.addFinalizer — finalizer in current scope

yield * Effect.addFinalizer(() => Effect.sync(() => console.log("scope closing")));

Scope — explicit lifetime management

import { Scope } from "effect";

const program = Effect.gen(function* () {
  const scope = yield* Scope.make();

  const conn = yield* Effect.acquireRelease(
    Effect.sync(() => db.connect()),
    (c) => Effect.sync(() => c.close()),
  ).pipe(Effect.provideService(Scope.Scope, scope));

  // ... use conn ...

  // Close explicitly when done
  yield* Scope.close(scope, Exit.void);
});

Effect.using — acquire + use + release in one expression

const result =
  yield *
  Effect.using(
    Effect.acquireRelease(
      Effect.sync(() => openFile(path)),
      (f) => Effect.sync(() => f.close()),
    ),
    (file) => readLines(file),
  );

forkScoped — fiber tied to scope

The fiber is interrupted when the enclosing scope closes.

yield *
  Effect.forkScoped(
    Effect.gen(function* () {
      while (true) {
        yield* Effect.sleep("5 seconds");
        yield* Effect.log("heartbeat");
      }
    }),
  );

Key rules

  • Never manage resources with try/finally inside Effect.gen — use acquireRelease.
  • Layer.scoped > Layer.effect when the service wraps a resource.
  • Effect.forkScoped > Effect.fork for long-running background tasks.

04 同仓库更多 Skills