Skip to content

Commit

Permalink
Consistency between batching and fiber state (#1706)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikearnaldi authored Nov 29, 2023
1 parent 3b0768c commit 8a1e98c
Show file tree
Hide file tree
Showing 14 changed files with 424 additions and 609 deletions.
9 changes: 9 additions & 0 deletions .changeset/honest-readers-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"effect": patch
---

Improve consistency between request batching and fiber environment.

In prior releases request batching required operators that act on fiber context such as `Effect.locally` to be aware of batching in order to avoid bugs where the effect executed post batching would lose the fiber environment (context, refs, and flags).

This change restructure how batching internally works, inside the fiber we now slice up the stack and restore the exact context that was destroyed, by rewriting the internals of forEach batching is now transparent to any other function that deals with fiber state.
29 changes: 6 additions & 23 deletions docs/modules/Effect.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ Added in v2.0.0
- [requests & batching](#requests--batching)
- [blocked](#blocked)
- [cacheRequestResult](#cacherequestresult)
- [flatMapStep](#flatmapstep)
- [request](#request)
- [runRequestBlock](#runrequestblock)
- [step](#step)
Expand Down Expand Up @@ -4121,10 +4120,10 @@ Added in v2.0.0
**Signature**

```ts
export interface Blocked<out R, out E, out A> extends Effect<R, E, A> {
export interface Blocked<out E, out A> extends Effect<never, E, A> {
readonly _op: "Blocked"
readonly i0: RequestBlock<R>
readonly i1: Effect<R, E, A>
readonly i0: RequestBlock
readonly i1: Effect<never, E, A>
}
```

Expand Down Expand Up @@ -4615,10 +4614,7 @@ Added in v2.0.0
**Signature**
```ts
export declare const blocked: <R, E, A>(
blockedRequests: RequestBlock<R>,
_continue: Effect<R, E, A>
) => Blocked<R, E, A>
export declare const blocked: <E, A>(blockedRequests: RequestBlock, _continue: Effect<never, E, A>) => Blocked<E, A>
```
Added in v2.0.0
Expand All @@ -4636,19 +4632,6 @@ export declare const cacheRequestResult: <A extends Request.Request<any, any>>(
Added in v2.0.0
## flatMapStep
**Signature**
```ts
export declare const flatMapStep: <R, E, A, R1, E1, B>(
self: Effect<R, E, A>,
f: (step: Exit.Exit<E, A> | Blocked<R, E, A>) => Effect<R1, E1, B>
) => Effect<R | R1, E1, B>
```
Added in v2.0.0
## request
**Signature**
Expand All @@ -4674,7 +4657,7 @@ Added in v2.0.0
**Signature**
```ts
export declare const runRequestBlock: <R>(blockedRequests: RequestBlock<R>) => Blocked<R, never, void>
export declare const runRequestBlock: <R>(blockedRequests: RequestBlock) => Effect<R, never, void>
```
Added in v2.0.0
Expand All @@ -4684,7 +4667,7 @@ Added in v2.0.0
**Signature**
```ts
export declare const step: <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, Exit.Exit<E, A> | Blocked<R, E, A>>
export declare const step: <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, Exit.Exit<E, A> | Blocked<E, A>>
```
Added in v2.0.0
Expand Down
76 changes: 22 additions & 54 deletions docs/modules/RequestBlock.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ Added in v2.0.0
- [Reducer (interface)](#reducer-interface)
- [Seq (interface)](#seq-interface)
- [Single (interface)](#single-interface)
- [utils](#utils)
- [locally](#locally)
- [mapInputContext](#mapinputcontext)

---

Expand All @@ -40,7 +37,7 @@ Added in v2.0.0
**Signature**

```ts
export declare const empty: RequestBlock<never>
export declare const empty: RequestBlock
```
Added in v2.0.0
Expand All @@ -50,10 +47,10 @@ Added in v2.0.0
**Signature**
```ts
export declare const mapRequestResolvers: <R, A, R2>(
self: RequestBlock<R>,
f: (dataSource: RequestResolver.RequestResolver<A, R>) => RequestResolver.RequestResolver<A, R2>
) => RequestBlock<R | R2>
export declare const mapRequestResolvers: <A>(
self: RequestBlock,
f: (dataSource: RequestResolver.RequestResolver<A, never>) => RequestResolver.RequestResolver<A, never>
) => RequestBlock
```
Added in v2.0.0
Expand All @@ -63,7 +60,7 @@ Added in v2.0.0
**Signature**
```ts
export declare const parallel: <R, R2>(self: RequestBlock<R>, that: RequestBlock<R2>) => RequestBlock<R | R2>
export declare const parallel: (self: RequestBlock, that: RequestBlock) => RequestBlock
```
Added in v2.0.0
Expand All @@ -73,7 +70,7 @@ Added in v2.0.0
**Signature**
```ts
export declare const reduce: <R, Z>(self: RequestBlock<R>, reducer: RequestBlock.Reducer<R, Z>) => Z
export declare const reduce: <Z>(self: RequestBlock, reducer: RequestBlock.Reducer<Z>) => Z
```
Added in v2.0.0
Expand All @@ -83,7 +80,7 @@ Added in v2.0.0
**Signature**
```ts
export declare const sequential: <R, R2>(self: RequestBlock<R>, that: RequestBlock<R2>) => RequestBlock<R | R2>
export declare const sequential: (self: RequestBlock, that: RequestBlock) => RequestBlock
```
Added in v2.0.0
Expand All @@ -93,10 +90,10 @@ Added in v2.0.0
**Signature**
```ts
export declare const single: <R, A>(
dataSource: RequestResolver.RequestResolver<A, R>,
export declare const single: <A>(
dataSource: RequestResolver.RequestResolver<A, never>,
blockedRequest: Request.Entry<A>
) => RequestBlock<R>
) => RequestBlock
```
Added in v2.0.0
Expand All @@ -120,10 +117,10 @@ Added in v2.0.0
**Signature**

```ts
export interface Par<out R> {
export interface Par {
readonly _tag: "Par"
readonly left: RequestBlock<R>
readonly right: RequestBlock<R>
readonly left: RequestBlock
readonly right: RequestBlock
}
```

Expand All @@ -140,7 +137,7 @@ preserving ordering guarantees.
**Signature**

```ts
export type RequestBlock<R> = Empty | Par<R> | Seq<R> | Single<R>
export type RequestBlock = Empty | Par | Seq | Single
```
Added in v2.0.0
Expand All @@ -154,10 +151,10 @@ Added in v2.0.0
**Signature**
```ts
export interface Reducer<in R, in out Z> {
export interface Reducer<in out Z> {
emptyCase(): Z
parCase(left: Z, right: Z): Z
singleCase(dataSource: RequestResolver.RequestResolver<unknown, R>, blockedRequest: Request.Entry<unknown>): Z
singleCase(dataSource: RequestResolver.RequestResolver<unknown, never>, blockedRequest: Request.Entry<unknown>): Z
seqCase(left: Z, right: Z): Z
}
```
Expand All @@ -169,10 +166,10 @@ Added in v2.0.0
**Signature**

```ts
export interface Seq<out R> {
export interface Seq {
readonly _tag: "Seq"
readonly left: RequestBlock<R>
readonly right: RequestBlock<R>
readonly left: RequestBlock
readonly right: RequestBlock
}
```

Expand All @@ -183,40 +180,11 @@ Added in v2.0.0
**Signature**

```ts
export interface Single<out R> {
export interface Single {
readonly _tag: "Single"
readonly dataSource: RequestResolver.RequestResolver<unknown, R>
readonly dataSource: RequestResolver.RequestResolver<unknown, never>
readonly blockedRequest: Request.Entry<unknown>
}
```

Added in v2.0.0

# utils

## locally

Provides each data source with a fiber ref value.

**Signature**

```ts
export declare const locally: <R, A>(self: RequestBlock<R>, ref: FiberRef<A>, value: A) => RequestBlock<R>
```
Added in v2.0.0
## mapInputContext
Provides each data source with part of its required environment.
**Signature**
```ts
export declare const mapInputContext: <R0, R>(
self: RequestBlock<R>,
f: (context: Context.Context<R0>) => Context.Context<R>
) => RequestBlock<R0>
```
Added in v2.0.0
21 changes: 6 additions & 15 deletions src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ export interface EffectTypeLambda extends TypeLambda {
* @since 2.0.0
* @category models
*/
export interface Blocked<out R, out E, out A> extends Effect<R, E, A> {
export interface Blocked<out E, out A> extends Effect<never, E, A> {
readonly _op: "Blocked"
readonly i0: RequestBlock<R>
readonly i1: Effect<R, E, A>
readonly i0: RequestBlock
readonly i1: Effect<never, E, A>
}

/**
Expand Down Expand Up @@ -4880,29 +4880,20 @@ export const ap: {
* @category requests & batching
* @since 2.0.0
*/
export const blocked: <R, E, A>(blockedRequests: RequestBlock<R>, _continue: Effect<R, E, A>) => Blocked<R, E, A> =
export const blocked: <E, A>(blockedRequests: RequestBlock, _continue: Effect<never, E, A>) => Blocked<E, A> =
core.blocked

/**
* @category requests & batching
* @since 2.0.0
*/
export const runRequestBlock: <R>(blockedRequests: RequestBlock<R>) => Blocked<R, never, void> = core.runRequestBlock
export const runRequestBlock: <R>(blockedRequests: RequestBlock) => Effect<R, never, void> = core.runRequestBlock

/**
* @category requests & batching
* @since 2.0.0
*/
export const step: <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, Exit.Exit<E, A> | Blocked<R, E, A>> = core.step

/**
* @category requests & batching
* @since 2.0.0
*/
export const flatMapStep: <R, E, A, R1, E1, B>(
self: Effect<R, E, A>,
f: (step: Exit.Exit<E, A> | Blocked<R, E, A>) => Effect<R1, E1, B>
) => Effect<R | R1, E1, B> = core.flatMapStep
export const step: <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, Exit.Exit<E, A> | Blocked<E, A>> = core.step

/**
* @since 2.0.0
Expand Down
Loading

0 comments on commit 8a1e98c

Please sign in to comment.