Skip to content

Commit

Permalink
Schema: add BatchingAnnotation (#2234)
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti authored Mar 1, 2024
1 parent aa66d87 commit 465be79
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 4 deletions.
14 changes: 14 additions & 0 deletions .changeset/orange-baboons-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"@effect/schema": patch
---

add `BatchingAnnotation`, default value: `false`

Example:

```ts
const schema = S.struct({
a: S.string,
b: S.number,
}).pipe(S.batching(true /* boolean | "inherit" | undefined */));
```
25 changes: 24 additions & 1 deletion packages/schema/src/AST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ export type ConcurrencyAnnotation = Concurrency | undefined
*/
export const ConcurrencyAnnotationId = Symbol.for("@effect/schema/annotation/Concurrency")

/**
* @category annotations
* @since 1.0.0
*/
export type BatchingAnnotation = boolean | "inherit" | undefined

/**
* @category annotations
* @since 1.0.0
*/
export const BatchingAnnotationId = Symbol.for("@effect/schema/annotation/Batching")

/**
* @category annotations
* @since 1.0.0
Expand Down Expand Up @@ -246,11 +258,22 @@ export const getDocumentationAnnotation = getAnnotation<DocumentationAnnotation>
DocumentationAnnotationId
)

/** @internal */
/**
* @category annotations
* @since 1.0.0
*/
export const getConcurrencyAnnotation = getAnnotation<ConcurrencyAnnotation>(
ConcurrencyAnnotationId
)

/**
* @category annotations
* @since 1.0.0
*/
export const getBatchingAnnotation = getAnnotation<BatchingAnnotation>(
BatchingAnnotationId
)

// -------------------------------------------------------------------------------------
// model
// -------------------------------------------------------------------------------------
Expand Down
12 changes: 9 additions & 3 deletions packages/schema/src/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ const goMemo = (ast: AST.AST, isDecoding: boolean): Parser => {
const getConcurrency = (ast: AST.AST): Concurrency | undefined =>
Option.getOrUndefined(AST.getConcurrencyAnnotation(ast))

const getBatching = (ast: AST.AST): boolean | "inherit" | undefined =>
Option.getOrUndefined(AST.getBatchingAnnotation(ast))

const go = (ast: AST.AST, isDecoding: boolean): Parser => {
switch (ast._tag) {
case "Refinement": {
Expand Down Expand Up @@ -473,6 +476,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
}
const expectedAST = AST.createUnion(ast.elements.map((_, i) => AST.createLiteral(i)))
const concurrency = getConcurrency(ast)
const batching = getBatching(ast)
return (input: unknown, options) => {
if (!Array.isArray(input)) {
return Either.left(InternalParser.type(ast, input))
Expand Down Expand Up @@ -679,7 +683,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
output: Array.from(output)
}
return Effect.flatMap(
Effect.forEach(cqueue, (f) => f(state), { concurrency, discard: true }),
Effect.forEach(cqueue, (f) => f(state), { concurrency, batching, discard: true }),
() => computeResult(state)
)
})
Expand Down Expand Up @@ -715,6 +719,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
)
const expected = goMemo(expectedAST, isDecoding)
const concurrency = getConcurrency(ast)
const batching = getBatching(ast)
return (input: unknown, options) => {
if (!Predicate.isRecord(input)) {
return Either.left(InternalParser.type(ast, input))
Expand Down Expand Up @@ -898,7 +903,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
output: Object.assign({}, output)
}
return Effect.flatMap(
Effect.forEach(cqueue, (f) => f(state), { concurrency, discard: true }),
Effect.forEach(cqueue, (f) => f(state), { concurrency, batching, discard: true }),
() => computeResult(state)
)
})
Expand All @@ -915,6 +920,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
map.set(ast.types[i], goMemo(ast.types[i], isDecoding))
}
const concurrency = getConcurrency(ast) ?? 1
const batching = getBatching(ast)
return (input, options) => {
const es: Array<[number, ParseResult.Type | ParseResult.TypeLiteral | ParseResult.Member]> = []
let stepKey = 0
Expand Down Expand Up @@ -1028,7 +1034,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
return Effect.suspend(() => {
const state: State = { es: Array.from(es) }
return Effect.flatMap(
Effect.forEach(cqueue, (f) => f(state), { concurrency, discard: true }),
Effect.forEach(cqueue, (f) => f(state), { concurrency, batching, discard: true }),
() => {
if ("finalResult" in state) {
return state.finalResult
Expand Down
9 changes: 9 additions & 0 deletions packages/schema/src/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1891,6 +1891,7 @@ const toAnnotations = (
move("pretty", hooks.PrettyHookId)
move("equivalence", hooks.EquivalenceHookId)
move("concurrency", AST.ConcurrencyAnnotationId)
move("batching", AST.BatchingAnnotationId)

return out
}
Expand All @@ -1906,6 +1907,7 @@ export interface DocAnnotations extends AST.Annotations {
readonly default?: AST.DefaultAnnotation
readonly documentation?: AST.DocumentationAnnotation
readonly concurrency?: AST.ConcurrencyAnnotation
readonly batching?: AST.BatchingAnnotation
}

/**
Expand Down Expand Up @@ -2009,6 +2011,13 @@ export const concurrency =
(concurrency: AST.ConcurrencyAnnotation) => <A, I, R>(self: Schema<A, I, R>): Schema<A, I, R> =>
make(AST.setAnnotation(self.ast, AST.ConcurrencyAnnotationId, concurrency))

/**
* @category annotations
* @since 1.0.0
*/
export const batching = (batching: AST.BatchingAnnotation) => <A, I, R>(self: Schema<A, I, R>): Schema<A, I, R> =>
make(AST.setAnnotation(self.ast, AST.BatchingAnnotationId, batching))

type Rename<A, M> = {
[
K in keyof A as K extends keyof M ? M[K] extends PropertyKey ? M[K]
Expand Down
7 changes: 7 additions & 0 deletions packages/schema/test/Schema/annotations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ describe("Schema > annotations", () => {
})
})

it("batching", () => {
const schema = S.struct({ a: S.string }).pipe(S.batching("inherit"))
expect(schema.ast.annotations).toEqual({
[AST.BatchingAnnotationId]: "inherit"
})
})

it("message as annotation options", async () => {
const schema =
// initial schema, a string
Expand Down

0 comments on commit 465be79

Please sign in to comment.