Skip to content

Commit b1163b2

Browse files
authoredFeb 14, 2024
add RequestResolver.aroundRequests api (#2145)
1 parent c568645 commit b1163b2

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed
 

‎.changeset/early-games-enjoy.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
"effect": patch
3+
---
4+
5+
add RequestResolver.aroundRequests api
6+
7+
This can be used to run side effects that introspect the requests being
8+
executed.
9+
10+
Example:
11+
12+
```ts
13+
import { Effect, Request, RequestResolver } from "effect";
14+
15+
interface GetUserById extends Request.Request<unknown> {
16+
readonly id: number;
17+
}
18+
19+
declare const resolver: RequestResolver.RequestResolver<GetUserById>;
20+
21+
RequestResolver.aroundRequests(
22+
resolver,
23+
(requests) => Effect.log(`got ${requests.length} requests`),
24+
(requests, _) => Effect.log(`finised running ${requests.length} requests`),
25+
);
26+
```

‎packages/effect/src/RequestResolver.ts

+37
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,43 @@ export const around: {
160160
): RequestResolver<A, R | R2 | R3>
161161
} = internal.around
162162

163+
/**
164+
* A data source aspect that executes requests between two effects, `before`
165+
* and `after`, where the result of `before` can be used by `after`.
166+
*
167+
* The `before` and `after` effects are provided with the requests being executed.
168+
*
169+
* @since 2.0.0
170+
* @category combinators
171+
* @example
172+
* import { Effect, Request, RequestResolver } from "effect"
173+
*
174+
* interface GetUserById extends Request.Request<unknown> {
175+
* readonly id: number
176+
* }
177+
*
178+
* const resolver = RequestResolver.fromFunction(
179+
* (request: GetUserById) => ({ id: request.id, name: "John" })
180+
* )
181+
*
182+
* RequestResolver.aroundRequests(
183+
* resolver,
184+
* (requests) => Effect.log(`got ${requests.length} requests`),
185+
* (requests, _) => Effect.log(`finised running ${requests.length} requests`)
186+
* )
187+
*/
188+
export const aroundRequests: {
189+
<A, R2, A2, R3, _>(
190+
before: (requests: ReadonlyArray<Types.NoInfer<A>>) => Effect.Effect<A2, never, R2>,
191+
after: (requests: ReadonlyArray<Types.NoInfer<A>>, _: A2) => Effect.Effect<_, never, R3>
192+
): <R>(self: RequestResolver<A, R>) => RequestResolver<A, R2 | R3 | R>
193+
<R, A, R2, A2, R3, _>(
194+
self: RequestResolver<A, R>,
195+
before: (requests: ReadonlyArray<Types.NoInfer<A>>) => Effect.Effect<A2, never, R2>,
196+
after: (requests: ReadonlyArray<Types.NoInfer<A>>, _: A2) => Effect.Effect<_, never, R3>
197+
): RequestResolver<A, R | R2 | R3>
198+
} = internal.aroundRequests
199+
163200
/**
164201
* Returns a data source that executes at most `n` requests in parallel.
165202
*

‎packages/effect/src/internal/dataSource.ts

+27
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { dual, pipe } from "../Function.js"
77
import * as RA from "../ReadonlyArray.js"
88
import type * as Request from "../Request.js"
99
import type * as RequestResolver from "../RequestResolver.js"
10+
import type { NoInfer } from "../Types.js"
1011
import * as core from "./core.js"
1112
import { invokeWithInterrupt, zipWithOptions } from "./fiberRuntime.js"
1213
import { complete } from "./request.js"
@@ -71,6 +72,32 @@ export const around = dual<
7172
Chunk.make("Around", self, before, after)
7273
))
7374

75+
/** @internal */
76+
export const aroundRequests = dual<
77+
<A, R2, A2, R3, _>(
78+
before: (requests: ReadonlyArray<NoInfer<A>>) => Effect.Effect<A2, never, R2>,
79+
after: (requests: ReadonlyArray<NoInfer<A>>, _: A2) => Effect.Effect<_, never, R3>
80+
) => <R>(
81+
self: RequestResolver.RequestResolver<A, R>
82+
) => RequestResolver.RequestResolver<A, R | R2 | R3>,
83+
<R, A, R2, A2, R3, _>(
84+
self: RequestResolver.RequestResolver<A, R>,
85+
before: (requests: ReadonlyArray<NoInfer<A>>) => Effect.Effect<A2, never, R2>,
86+
after: (requests: ReadonlyArray<NoInfer<A>>, _: A2) => Effect.Effect<_, never, R3>
87+
) => RequestResolver.RequestResolver<A, R | R2 | R3>
88+
>(3, (self, before, after) =>
89+
new core.RequestResolverImpl(
90+
(requests) => {
91+
const flatRequests = requests.flatMap((chunk) => chunk.map((entry) => entry.request))
92+
return core.acquireUseRelease(
93+
before(flatRequests),
94+
() => self.runAll(requests),
95+
(a2) => after(flatRequests, a2)
96+
)
97+
},
98+
Chunk.make("AroundRequests", self, before, after)
99+
))
100+
74101
/** @internal */
75102
export const batchN = dual<
76103
(n: number) => <R, A>(

0 commit comments

Comments
 (0)
Please sign in to comment.