# Resource

A `Resource<A, E>` keeps a single value loaded in memory and lets you reload it
on demand or on a schedule. It is the right tool when you have something that is
expensive to acquire and changes occasionally — an auth token, a feature-flag
snapshot, a remote configuration, a signing key — and you want every reader to
see the latest loaded value without re-running the acquisition each time.

Internally a `Resource` wraps an acquisition effect whose latest result is stored
in a scoped reference. Reading it returns the current value; refreshing re-runs
acquisition and atomically swaps in the new result, releasing any resources held
by the previous one.

## Manual refresh

`Resource.manual` builds a resource you refresh yourself. Creation runs the
acquisition once and stores the result; `Resource.get` reads it; `Resource.refresh`
reloads it.

```ts
import { Effect, Resource } from "effect"

const program = Effect.gen(function*() {
  let version = 0

  // Acquire a config snapshot. In a real app this would read from a file
  // or a remote service; here we just bump a counter so refreshes are
  // observable.
  const resource = yield* Resource.manual(
    Effect.sync(() => ({ version: ++version }))
  )

  const first = yield* Resource.get(resource) // { version: 1 }
  const cached = yield* Resource.get(resource) // { version: 1 } (no reload)

  yield* Resource.refresh(resource) // re-runs acquisition
  const reloaded = yield* Resource.get(resource) // { version: 2 }

  return { first, cached, reloaded }
}).pipe(Effect.scoped)
```
**Note:** `Resource.manual` and `Resource.auto` require a `Scope`: the resource lives for as
long as that scope is open, and any scoped values it holds are released when the
scope closes. Run the workflow under `Effect.scoped` or inside an existing scoped
operation.

## Automatic refresh on a schedule

`Resource.auto` does the same as `manual`, but also forks a background fiber that
refreshes the resource according to a [`Schedule`](https://effect.plants.sh/scheduling/). The refresh
loop runs in the resource's scope and stops when that scope closes.

```ts
import { Effect, Resource, Schedule } from "effect"

interface Config {
  readonly featureEnabled: boolean
}

// Load remote config now, then reload it every 5 minutes in the
// background. Readers always see the most recently loaded snapshot.
const makeConfig = (load: Effect.Effect<Config, string>) =>
  Resource.auto(load, Schedule.fixed("5 minutes"))

const program = Effect.gen(function*() {
  const config = yield* makeConfig(Effect.succeed({ featureEnabled: true }))

  // Reads are cheap and never trigger acquisition themselves — they just
  // return whatever the background refresh last loaded.
  const current = yield* Resource.get(config)
  return current
}).pipe(Effect.scoped)
```

This pairs naturally with the service/Layer style: build the `Resource` once in a
scoped layer and expose `get` to the rest of the application.

```ts
import { Context, Effect, Layer, Resource, Schedule } from "effect"

interface Token {
  readonly value: string
}

// A service that keeps a short-lived auth token fresh. The token is
// acquired at startup and re-acquired every 50 minutes; callers just ask
// for the current one.
class Auth extends Context.Service<Auth, {
  readonly token: Effect.Effect<Token>
}>()("app/Auth") {
  // Layer.effect runs construction in the layer's own scope, so the
  // resource's background refresh fiber is torn down when the layer closes.
  static layer = Layer.effect(
    Auth,
    Effect.gen(function*() {
      const resource = yield* Resource.auto(
        // Pretend this calls an identity provider.
        Effect.succeed<Token>({ value: "secret" }),
        Schedule.fixed("50 minutes")
      )
      return Auth.of({ token: Resource.get(resource) })
    })
  )
}
```

Because the resource is created with `Layer.effect` (which runs construction in
the layer's scope), its background refresh fiber is torn down automatically when
the layer's scope closes.

## Handling acquisition failures

A `Resource<A, E>` stores the acquisition `Exit` — including failures. If
acquisition fails, `Resource.get` fails with that error until a later refresh
succeeds.

- `Resource.get` reads the current stored result and **fails** with `E` if the
  last acquisition failed.
- `Resource.refresh` re-runs acquisition. If the new acquisition *succeeds*, it
  replaces the stored value (releasing the previous one's resources). If it
  *fails*, the refresh effect fails — and with automatic refresh, the previously
  stored value is left in place for `get` to keep reading.

```ts
import { Effect, Resource } from "effect"

const program = Effect.gen(function*() {
  let attempt = 0

  // Fails on the first acquisition, succeeds afterwards.
  const resource = yield* Resource.manual(
    Effect.suspend(() =>
      ++attempt === 1 ? Effect.fail("initial load failed" as const) : Effect.succeed("ok")
    )
  )

  // The stored result is a failure, so get fails too.
  const failed = yield* Effect.exit(Resource.get(resource)) // Exit.fail("initial load failed")

  yield* Resource.refresh(resource) // succeeds this time
  const ok = yield* Resource.get(resource) // "ok"

  return { failed, ok }
}).pipe(Effect.scoped)
```
**Tip:** `Resource` keeps exactly one value loaded. If you need to remember results keyed
by an input, use [`Cache`](https://effect.plants.sh/caching/cache/). If you need to share a live resource
across fibers and release it by reference count, use
[`RcRef` / `RcMap`](https://effect.plants.sh/caching/reference-counting/).

## How it works: ScopedRef

A `Resource` is a thin layer over the scoped-ref swapping primitive,
[`ScopedRef`](https://effect.plants.sh/caching/reference-counting/), which is what gives refresh its
atomic *release-then-acquire* semantics. A `ScopedRef<A>` holds a value together
with the `Scope` it was acquired in; replacing the value closes the old scope
(releasing its finalizers) before installing the new one, and updates are
synchronized so concurrent refreshes do not race.

A `Resource<A, E>` is just a `ScopedRef<Exit<A, E>>` plus the original acquisition
effect: `refresh` calls `ScopedRef.set` with `acquire`, and `get` reads the stored
`Exit` and re-runs it (succeeding with `A` or failing with `E`). That is why a
failed acquisition is *stored* — the `Exit` itself records the failure.

```ts
import { Effect, Resource } from "effect"

const program = Effect.gen(function*() {
  const resource = yield* Resource.manual(Effect.succeed(1))

  // The interface exposes the underlying scoped ref and acquire effect.
  resource.scopedRef // ScopedRef<Exit<number, never>>
  resource.acquire   // Effect<number, never>

  return yield* Resource.get(resource) // 1
}).pipe(Effect.scoped)
```

## Reference

Import everything from the core `effect` package:

```ts
import { Resource } from "effect"
```

### Resource

The model type. `Resource<A, E>` is a value loaded into memory that can be
refreshed manually or on a schedule; `A` is the loaded value and `E` is the error
type that `get` can fail with when the last acquisition failed.

```ts
import { Effect, type Exit, Resource, type ScopedRef } from "effect"

// interface Resource<in out A, in out E = never> {
//   readonly scopedRef: ScopedRef.ScopedRef<Exit.Exit<A, E>>
//   readonly acquire: Effect.Effect<A, E>
// }

declare const r: Resource.Resource<string, Error>
r.acquire   // Effect.Effect<string, Error>
r.scopedRef // ScopedRef.ScopedRef<Exit.Exit<string, Error>>
```

### Resource.manual

Creates a resource that you refresh by hand. Creation runs the acquisition effect
once and stores the result; the returned effect requires a `Scope` (plus whatever
`R` the acquisition needs) and never fails — acquisition failures are stored and
surfaced through `get` instead.

```ts
import { Effect, Resource } from "effect"

// manual: (acquire: Effect<A, E, R>) => Effect<Resource<A, E>, never, Scope | R>
const program = Effect.gen(function*() {
  let n = 0
  const resource = yield* Resource.manual(Effect.sync(() => ++n))

  const a = yield* Resource.get(resource) // 1
  yield* Resource.refresh(resource)
  const b = yield* Resource.get(resource) // 2

  return [a, b] // [1, 2]
}).pipe(Effect.scoped)
```

### Resource.auto

Like `manual`, but also forks a background fiber that calls `refresh` repeatedly
according to a [`Schedule`](https://effect.plants.sh/scheduling/). The schedule is the second argument
(`policy`). The fiber runs in the resource's scope and stops when that scope
closes.

```ts
import { Effect, Resource, Schedule } from "effect"

// auto: (acquire: Effect<A, E, R>, policy: Schedule<Out, unknown, E2, R2>)
//   => Effect<Resource<A, E>, never, R | R2 | Scope>
const program = Effect.gen(function*() {
  let token = 0

  // Re-acquire a token every 50 minutes in the background.
  const resource = yield* Resource.auto(
    Effect.sync(() => `token-${++token}`),
    Schedule.fixed("50 minutes")
  )

  return yield* Resource.get(resource) // "token-1"
}).pipe(Effect.scoped)
```

### Resource.get

Reads the value currently stored in the resource. If the last acquisition
succeeded it returns the value; if it failed, the returned effect fails with the
stored error `E`. Reading never triggers a reload on its own.

```ts
import { Effect, Resource } from "effect"

// get: (self: Resource<A, E>) => Effect<A, E>
const program = Effect.gen(function*() {
  const resource = yield* Resource.manual(Effect.succeed("loaded"))
  return yield* Resource.get(resource) // "loaded"
}).pipe(Effect.scoped)
```

### Resource.refresh

Forces a reload now: re-runs the acquisition effect and, on success, atomically
swaps the stored value in, releasing resources held by the previous value. If the
new acquisition fails, the refresh effect fails and the previously stored result
is left in place for `get` to keep reading.

```ts
import { Effect, Resource } from "effect"

// refresh: (self: Resource<A, E>) => Effect<void, E>
const program = Effect.gen(function*() {
  let n = 0
  const resource = yield* Resource.manual(Effect.sync(() => ++n))

  yield* Resource.refresh(resource) // re-runs acquisition (n -> 2)
  return yield* Resource.get(resource) // 2
}).pipe(Effect.scoped)
```

### Resource.isResource

Type guard that returns `true` when the given value is a `Resource`, narrowing it
to `Resource<unknown, unknown>`. Useful at runtime boundaries.

```ts
import { Effect, Resource } from "effect"

const program = Effect.gen(function*() {
  const resource = yield* Resource.manual(Effect.succeed(1))

  Resource.isResource(resource) // => true
  Resource.isResource({}) // => false
  Resource.isResource(null) // => false
}).pipe(Effect.scoped)
```