# Resourceful Streams

Resources acquired by a stream must remain open for the whole period in which the stream is consumed. Compose `Effect.acquireRelease`, `Stream.fromEffect`, and `Stream.scoped` to tie the resource lifetime to the stream. Use `Stream.ensuring` when a stream only needs a finalizer.

## Acquire Release

The following example acquires a file, emits its lines, and closes it when stream consumption ends.

```ts
import { Stream, Console, Effect } from "effect"

// Simulating File operations
const open = (filename: string) =>
  Effect.gen(function* () {
    yield* Console.log(`Opening ${filename}`)
    return {
      getLines: Effect.succeed(["Line 1", "Line 2", "Line 3"]),
      close: Console.log(`Closing ${filename}`),
    }
  })

const stream = Stream.scoped(
  Stream.fromEffect(
    Effect.acquireRelease(open("file.txt"), (file) => file.close),
  ),
).pipe(Stream.flatMap((file) => Stream.fromIterableEffect(file.getLines)))

await Effect.runPromise(Stream.runCollect(stream)) // => ["Line 1", "Line 2", "Line 3"]
```

`Effect.acquireRelease` registers `file.close` in the scope created by `Stream.scoped`. The file therefore remains open while `Stream.fromIterableEffect` emits its contents.

## Finalization

`Stream.ensuring` runs a finalizer after the stream's own finalizers, whether the stream succeeds, fails, or is interrupted.

```ts
import { Stream, Console, Effect } from "effect"

const application = Stream.fromEffect(Console.log("Application Logic."))

const deleteDir = (dir: string) => Console.log(`Deleting dir: ${dir}`)

const program = application.pipe(
  Stream.ensuring(
    deleteDir("tmp").pipe(
      Effect.andThen(Console.log("Temporary directory was deleted.")),
    ),
  ),
)

await Effect.runPromise(Stream.runCollect(program)) // => [undefined]
```
