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/finallyinsideEffect.gen— useacquireRelease. Layer.scoped>Layer.effectwhen the service wraps a resource.Effect.forkScoped>Effect.forkfor long-running background tasks.
04 同仓库更多 Skills
tmux-workflow
Development workflow with tmux — run dev servers, Storybook, and background processes in persistent sessions with live logs, while keeping OpenCode free for chat
04-anti-patterns
React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps
03-state-management
React state management patterns — lifting state, colocation, URL state, server state with TanStack Query, local state with useState/useReducer
02-component-composition
React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives
01-fp-style
React functional programming style — pure components, hooks conventions, Effect Atom integration, and Tailwind patterns
react-animation
React animation with react/motion (Framer Motion) — declarative animations, gestures, layout animations, and performance best practices