Skip to content

Commit

Permalink
add Runtime.updateFiberRefs/setFiberRef/deleteFiberRef (Effect-TS#2149)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored Feb 15, 2024
1 parent b46b869 commit ff8046f
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .changeset/tidy-tips-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"effect": patch
---

add Runtime.updateFiberRefs/setFiberRef/deleteFiberRef

This change allows you to update fiber ref values inside a Runtime object.

Example:

```ts
import { Effect, FiberRef, Runtime } from "effect";

const ref = FiberRef.unsafeMake(0);

const updatedRuntime = Runtime.defaultRuntime.pipe(Runtime.setFiberRef(ref, 1));

// returns 1
const result = Runtime.runSync(updatedRuntime)(FiberRef.get(ref));
```
51 changes: 51 additions & 0 deletions packages/effect/src/Runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type * as Effect from "./Effect.js"
import type * as Exit from "./Exit.js"
import type * as Fiber from "./Fiber.js"
import type * as FiberId from "./FiberId.js"
import type * as FiberRef from "./FiberRef.js"
import type * as FiberRefs from "./FiberRefs.js"
import type { Inspectable } from "./Inspectable.js"
import * as internal from "./internal/runtime.js"
Expand Down Expand Up @@ -277,3 +278,53 @@ export const provideService: {
<I, S>(tag: Context.Tag<I, S>, service: S): <R>(self: Runtime<R>) => Runtime<I | R>
<R, I, S>(self: Runtime<R>, tag: Context.Tag<I, S>, service: S): Runtime<R | I>
} = internal.provideService

/**
* @since 2.0.0
* @category fiber refs
*/
export const updateFiberRefs: {
(f: (fiberRefs: FiberRefs.FiberRefs) => FiberRefs.FiberRefs): <R>(self: Runtime<R>) => Runtime<R>
<R>(self: Runtime<R>, f: (fiberRefs: FiberRefs.FiberRefs) => FiberRefs.FiberRefs): Runtime<R>
} = internal.updateFiberRefs

/**
* @since 2.0.0
* @category fiber refs
* @example
* import { Effect, FiberRef, Runtime } from "effect"
*
* const ref = FiberRef.unsafeMake(0)
*
* const updatedRuntime = Runtime.defaultRuntime.pipe(
* Runtime.setFiberRef(ref, 1)
* )
*
* // returns 1
* const result = Runtime.runSync(updatedRuntime)(FiberRef.get(ref))
*/
export const setFiberRef: {
<A>(fiberRef: FiberRef.FiberRef<A>, value: A): <R>(self: Runtime<R>) => Runtime<R>
<R, A>(self: Runtime<R>, fiberRef: FiberRef.FiberRef<A>, value: A): Runtime<R>
} = internal.setFiberRef

/**
* @since 2.0.0
* @category fiber refs
* @example
* import { Effect, FiberRef, Runtime } from "effect"
*
* const ref = FiberRef.unsafeMake(0)
*
* const updatedRuntime = Runtime.defaultRuntime.pipe(
* Runtime.setFiberRef(ref, 1),
* Runtime.deleteFiberRef(ref)
* )
*
* // returns 0
* const result = Runtime.runSync(updatedRuntime)(FiberRef.get(ref))
*/
export const deleteFiberRef: {
<A>(fiberRef: FiberRef.FiberRef<A>): <R>(self: Runtime<R>) => Runtime<R>
<R, A>(self: Runtime<R>, fiberRef: FiberRef.FiberRef<A>): Runtime<R>
} = internal.deleteFiberRef
41 changes: 41 additions & 0 deletions packages/effect/src/internal/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,47 @@ export const provideService: {
updateContext(self, Context.add(tag, service))
)

/** @internal */
export const updateFiberRefs: {
(f: (fiberRefs: FiberRefs.FiberRefs) => FiberRefs.FiberRefs): <R>(self: Runtime.Runtime<R>) => Runtime.Runtime<R>
<R>(self: Runtime.Runtime<R>, f: (fiberRefs: FiberRefs.FiberRefs) => FiberRefs.FiberRefs): Runtime.Runtime<R>
} = dual(
2,
<R>(self: Runtime.Runtime<R>, f: (fiberRefs: FiberRefs.FiberRefs) => FiberRefs.FiberRefs): Runtime.Runtime<R> =>
make({
context: self.context,
runtimeFlags: self.runtimeFlags,
fiberRefs: f(self.fiberRefs)
})
)

/** @internal */
export const setFiberRef: {
<A>(fiberRef: FiberRef.FiberRef<A>, value: A): <R>(self: Runtime.Runtime<R>) => Runtime.Runtime<R>
<R, A>(self: Runtime.Runtime<R>, fiberRef: FiberRef.FiberRef<A>, value: A): Runtime.Runtime<R>
} = dual(
3,
<R, A>(self: Runtime.Runtime<R>, fiberRef: FiberRef.FiberRef<A>, value: A): Runtime.Runtime<R> =>
updateFiberRefs(
self,
FiberRefs.updateAs({
fiberId: FiberId.none,
fiberRef,
value
})
)
)

/** @internal */
export const deleteFiberRef: {
<A>(fiberRef: FiberRef.FiberRef<A>): <R>(self: Runtime.Runtime<R>) => Runtime.Runtime<R>
<R, A>(self: Runtime.Runtime<R>, fiberRef: FiberRef.FiberRef<A>): Runtime.Runtime<R>
} = dual(
2,
<R, A>(self: Runtime.Runtime<R>, fiberRef: FiberRef.FiberRef<A>): Runtime.Runtime<R> =>
updateFiberRefs(self, FiberRefs.delete(fiberRef))
)

/** @internal */
export const unsafeRunEffect = unsafeRunCallback(defaultRuntime)

Expand Down
30 changes: 30 additions & 0 deletions packages/effect/test/Runtime.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Effect, FiberRef, Layer, Runtime } from "effect"
import { assert, describe } from "vitest"
import * as it from "./utils/extend.js"

describe("Runtime", () => {
it.effect("setFiberRef", () =>
Effect.gen(function*(_) {
const ref = FiberRef.unsafeMake(0)
const runtime = Runtime.defaultRuntime.pipe(
Runtime.setFiberRef(ref, 1)
)
let result = Runtime.runSync(runtime)(FiberRef.get(ref))
assert.strictEqual(result, 1)

result = yield* _(FiberRef.get(ref), Effect.provide(runtime))
assert.strictEqual(result, 1)
}))

it.scoped("deleteFiberRef", () =>
Effect.gen(function*(_) {
const ref = FiberRef.unsafeMake({ value: 0 })
const runtime = yield* _(Layer.toRuntime(Layer.effectDiscard(FiberRef.set(ref, { value: 1 }))))

let result = Runtime.runSync(runtime)(FiberRef.get(ref))
assert.deepStrictEqual(result, { value: 1 })

result = Runtime.runSync(Runtime.deleteFiberRef(runtime, ref))(FiberRef.get(ref))
assert.deepStrictEqual(result, { value: 0 })
}))
})

0 comments on commit ff8046f

Please sign in to comment.