From 8ea4f44c4347bc727f93e193d2efcd9aea959c58 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Tue, 30 Jul 2024 11:27:57 +0200 Subject: [PATCH] add Concurrency Annotation docs (#3381) --- packages/schema/README.md | 90 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/packages/schema/README.md b/packages/schema/README.md index 6e7fc96081..633f847192 100644 --- a/packages/schema/README.md +++ b/packages/schema/README.md @@ -4827,9 +4827,9 @@ console.log(decode("3")) // { _id: 'BigDecimal', value: '1', scale: 0 } ## Annotations One of the fundamental requirements in the design of `@effect/schema` is that it is extensible and customizable. Customizations are achieved through "annotations". Each node contained in the AST of `@effect/schema/AST` contains an `annotations: Record` field that can be used to attach additional information to the schema. -You can manage these annotations using the `annotations` method. +You can manage these annotations using the `annotations` method ot the `Schema.annotations` API. -Let's see some examples: +**Example of Using Annotations** ```ts import { Schema } from "@effect/schema" @@ -4863,9 +4863,91 @@ const Password = }) ``` -The example shows some built-in combinators to add meta information, but users can easily add their own meta information by defining a custom annotation. +This example demonstrates the use of built-in annotations to add metadata like error messages, identifiers, and descriptions to enhance the schema's functionality and documentation. -Here's an example of how to add a `deprecated` annotation: +### Built-in Annotations + +The following table provides an overview of common built-in annotations and their uses: + +| Annotation | Description | +| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `identifier` | Assigns a unique identifier to the schema, ideal for TypeScript identifiers and code generation purposes. Commonly used in tools like [TreeFormatter](#customizing-the-output) to clarify output. Examples include `"Person"`, `"Product"`. | +| `title` | Sets a short, descriptive title for the schema, similar to a JSON Schema title. Useful for documentation or UI headings. It is also used by [TreeFormatter](#customizing-the-output) to enhance readability of error messages. | +| `description` | Provides a detailed explanation about the schema's purpose, akin to a JSON Schema description. Used by [TreeFormatter](#customizing-the-output) to provide more detailed error messages. | +| `documentation` | Extends detailed documentation for the schema, beneficial for developers or automated documentation generation. | +| `examples` | Lists examples of valid schema values, akin to the examples attribute in JSON Schema, useful for documentation and validation testing. | +| `default` | Defines a default value for the schema, similar to the default attribute in JSON Schema, to ensure schemas are pre-populated where applicable. | +| `message` | Customizes the error message for validation failures, improving clarity in outputs from tools like [TreeFormatter](#customizing-the-output) and [ArrayFormatter](#arrayformatter) during decoding or validation errors. | +| `jsonSchema` | Specifies annotations that affect the generation of [JSON Schema](#generating-json-schemas) documents, customizing how schemas are represented. | +| `arbitrary` | Configures settings for generating [Arbitrary](#generating-arbitraries) test data. | +| `pretty` | Configures settings for generating [Pretty](#generating-pretty-printers) output. | +| `equivalence` | Configures settings for evaluating data [Equivalence](#generating-equivalences). | +| `concurrency` | Controls concurrency behavior, ensuring schemas perform optimally under concurrent operations. Refer to [Concurrency Annotation](#concurrency-annotation) for detailed usage. | +| `batching` | Manages settings for batching operations to enhance performance when operations can be grouped. | +| `parseIssueTitle` | Provides a custom title for parsing issues, enhancing error descriptions in outputs from [TreeFormatter](#customizing-the-output). See [ParseIssueTitle Annotation](#parseissuetitle-annotation) for more information. | +| `parseOptions` | Allows overriding of parsing options at the schema level, offering granular control over parsing behaviors. See [Customizing Parsing Behavior at the Schema Level](#customizing-parsing-behavior-at-the-schema-level) for application details. | + +### Concurrency Annotation + +For complex schemas like `Struct`, `Array`, or `Union` that contain multiple nested schemas, the `concurrency` annotation provides a way to manage how validations are executed concurrently: + +```ts +import { Schema } from "@effect/schema" +import type { Duration } from "effect" +import { Effect } from "effect" + +// Simulates an async task +const item = (id: number, duration: Duration.DurationInput) => + Schema.String.pipe( + Schema.filterEffect(() => + Effect.gen(function* () { + yield* Effect.sleep(duration) + console.log(`Task ${id} done`) + return true + }) + ) + ) +``` + +**Sequential Execution** + +```ts +const Sequential = Schema.Tuple( + item(1, "30 millis"), + item(2, "10 millis"), + item(3, "20 millis") +) + +Effect.runPromise(Schema.decode(Sequential)(["a", "b", "c"])) +/* +Output +Task 1 done +Task 2 done +Task 3 done +*/ +``` + +**Concurrent Execution** + +```ts +const Concurrent = Sequential.annotations({ + concurrency: "unbounded" +}) + +Effect.runPromise(Schema.decode(Concurrent)(["a", "b", "c"])) +/* +Output +Task 2 done +Task 3 done +Task 1 done +*/ +``` + +This configuration allows developers to specify whether validations within a schema should be processed sequentially or concurrently, offering flexibility based on the performance needs and the dependencies between validations. + +### Custom Annotations + +You can also define your own custom annotations for specific needs. Here's how you can create a `deprecated` annotation: ```ts import { AST, Schema } from "@effect/schema"