effect 4.0.7 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/BigDecimal.d.ts.map +1 -1
- package/dist/BigDecimal.js +3 -0
- package/dist/BigDecimal.js.map +1 -1
- package/dist/Channel.d.ts +12 -6
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Channel.js +9 -3
- package/dist/Channel.js.map +1 -1
- package/dist/Config.d.ts +7 -1
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js.map +1 -1
- package/dist/Context.d.ts +18 -1
- package/dist/Context.d.ts.map +1 -1
- package/dist/Context.js +27 -8
- package/dist/Context.js.map +1 -1
- package/dist/Cron.d.ts +81 -11
- package/dist/Cron.d.ts.map +1 -1
- package/dist/Cron.js +101 -26
- package/dist/Cron.js.map +1 -1
- package/dist/Duration.d.ts +78 -0
- package/dist/Duration.d.ts.map +1 -1
- package/dist/Duration.js +123 -0
- package/dist/Duration.js.map +1 -1
- package/dist/Effect.d.ts +164 -7
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +11 -1
- package/dist/Effect.js.map +1 -1
- package/dist/FileSystem.d.ts +59 -4
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js +9 -2
- package/dist/FileSystem.js.map +1 -1
- package/dist/Glob.d.ts +165 -0
- package/dist/Glob.d.ts.map +1 -0
- package/dist/Glob.js +127 -0
- package/dist/Glob.js.map +1 -0
- package/dist/Match.d.ts +86 -0
- package/dist/Match.d.ts.map +1 -1
- package/dist/Match.js +72 -0
- package/dist/Match.js.map +1 -1
- package/dist/Pool.d.ts +51 -0
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +59 -9
- package/dist/Pool.js.map +1 -1
- package/dist/Random.d.ts.map +1 -1
- package/dist/Random.js +3 -3
- package/dist/Random.js.map +1 -1
- package/dist/RcMap.d.ts.map +1 -1
- package/dist/RcMap.js +8 -2
- package/dist/RcMap.js.map +1 -1
- package/dist/Schedule.d.ts +18 -1
- package/dist/Schedule.d.ts.map +1 -1
- package/dist/Schedule.js +7 -2
- package/dist/Schedule.js.map +1 -1
- package/dist/Schema.d.ts +666 -41
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +650 -0
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaGetter.d.ts +6 -1
- package/dist/SchemaGetter.d.ts.map +1 -1
- package/dist/SchemaGetter.js +22 -11
- package/dist/SchemaGetter.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +14 -0
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +16 -0
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +8 -3
- package/dist/SchemaTransformation.d.ts.map +1 -1
- package/dist/SchemaTransformation.js +6 -3
- package/dist/SchemaTransformation.js.map +1 -1
- package/dist/ScopedCache.d.ts.map +1 -1
- package/dist/ScopedCache.js +5 -7
- package/dist/ScopedCache.js.map +1 -1
- package/dist/Semaphore.d.ts +130 -0
- package/dist/Semaphore.d.ts.map +1 -1
- package/dist/Semaphore.js +40 -0
- package/dist/Semaphore.js.map +1 -1
- package/dist/Stream.d.ts +13 -4
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +9 -0
- package/dist/Stream.js.map +1 -1
- package/dist/Terminal.d.ts +18 -1
- package/dist/Terminal.d.ts.map +1 -1
- package/dist/Terminal.js +1 -1
- package/dist/Terminal.js.map +1 -1
- package/dist/ai/AiError.d.ts +43 -116
- package/dist/ai/AiError.d.ts.map +1 -1
- package/dist/ai/AiError.js +53 -72
- package/dist/ai/AiError.js.map +1 -1
- package/dist/ai/Decision.d.ts +196 -15
- package/dist/ai/Decision.d.ts.map +1 -1
- package/dist/ai/Decision.js +130 -0
- package/dist/ai/Decision.js.map +1 -1
- package/dist/ai/DecisionModel.d.ts +54 -13
- package/dist/ai/DecisionModel.d.ts.map +1 -1
- package/dist/ai/DecisionModel.js +123 -12
- package/dist/ai/DecisionModel.js.map +1 -1
- package/dist/ai/McpServer.d.ts +630 -29
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +562 -116
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/McpTest.d.ts +130 -0
- package/dist/ai/McpTest.d.ts.map +1 -0
- package/dist/ai/McpTest.js +237 -0
- package/dist/ai/McpTest.js.map +1 -0
- package/dist/ai/Response.d.ts +1 -25
- package/dist/ai/Response.d.ts.map +1 -1
- package/dist/ai/Response.js +1 -10
- package/dist/ai/Response.js.map +1 -1
- package/dist/ai/Tool.d.ts +19 -1
- package/dist/ai/Tool.d.ts.map +1 -1
- package/dist/ai/Tool.js.map +1 -1
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +5 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/internal/mcpCore.js +17 -12
- package/dist/ai/internal/mcpCore.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js +4 -5
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js +4 -5
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js +4 -5
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js +4 -5
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js +18 -10
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
- package/dist/ai/internal/mcpProtocol.js +13 -0
- package/dist/ai/internal/mcpProtocol.js.map +1 -1
- package/dist/ai/internal/mcpRuntime.js +5 -3
- package/dist/ai/internal/mcpRuntime.js.map +1 -1
- package/dist/ai/internal/mcpStatefulRuntime.js +6 -1
- package/dist/ai/internal/mcpStatefulRuntime.js.map +1 -1
- package/dist/cli/Argument.d.ts +6 -0
- package/dist/cli/Argument.d.ts.map +1 -1
- package/dist/cli/Argument.js +2 -0
- package/dist/cli/Argument.js.map +1 -1
- package/dist/cli/CliOutput.d.ts +65 -1
- package/dist/cli/CliOutput.d.ts.map +1 -1
- package/dist/cli/CliOutput.js +94 -37
- package/dist/cli/CliOutput.js.map +1 -1
- package/dist/cli/Command.d.ts +23 -0
- package/dist/cli/Command.d.ts.map +1 -1
- package/dist/cli/Command.js +8 -0
- package/dist/cli/Command.js.map +1 -1
- package/dist/cli/Flag.d.ts +107 -0
- package/dist/cli/Flag.d.ts.map +1 -1
- package/dist/cli/Flag.js +37 -0
- package/dist/cli/Flag.js.map +1 -1
- package/dist/cli/HelpDoc.d.ts +15 -1
- package/dist/cli/HelpDoc.d.ts.map +1 -1
- package/dist/cli/Param.d.ts +6 -0
- package/dist/cli/Param.d.ts.map +1 -1
- package/dist/cli/Param.js +2 -0
- package/dist/cli/Param.js.map +1 -1
- package/dist/cli/Primitive.d.ts +14 -0
- package/dist/cli/Primitive.d.ts.map +1 -1
- package/dist/cli/Primitive.js +15 -1
- package/dist/cli/Primitive.js.map +1 -1
- package/dist/cli/Prompt.d.ts +1 -0
- package/dist/cli/Prompt.d.ts.map +1 -1
- package/dist/cli/Prompt.js +1 -0
- package/dist/cli/Prompt.js.map +1 -1
- package/dist/cli/internal/help.d.ts.map +1 -1
- package/dist/cli/internal/help.js +17 -10
- package/dist/cli/internal/help.js.map +1 -1
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +90 -28
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/ShardingConfig.d.ts +72 -6
- package/dist/cluster/ShardingConfig.d.ts.map +1 -1
- package/dist/cluster/ShardingConfig.js +4 -0
- package/dist/cluster/ShardingConfig.js.map +1 -1
- package/dist/cluster/SingleRunner.d.ts +3 -3
- package/dist/cluster/SingleRunner.d.ts.map +1 -1
- package/dist/cluster/SingleRunner.js +1 -1
- package/dist/cluster/SqlMessageStorage.d.ts +37 -6
- package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
- package/dist/cluster/SqlMessageStorage.js +34 -7
- package/dist/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/cluster/SqlRunnerStorage.js +23 -8
- package/dist/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/crypto/Aead.d.ts +322 -0
- package/dist/crypto/Aead.d.ts.map +1 -0
- package/dist/crypto/Aead.js +331 -0
- package/dist/crypto/Aead.js.map +1 -0
- package/dist/crypto/Cipher.d.ts +235 -0
- package/dist/crypto/Cipher.d.ts.map +1 -0
- package/dist/crypto/Cipher.js +233 -0
- package/dist/crypto/Cipher.js.map +1 -0
- package/dist/crypto/CryptoError.d.ts +212 -0
- package/dist/crypto/CryptoError.d.ts.map +1 -0
- package/dist/crypto/CryptoError.js +202 -0
- package/dist/crypto/CryptoError.js.map +1 -0
- package/dist/crypto/Digest.d.ts +143 -0
- package/dist/crypto/Digest.d.ts.map +1 -0
- package/dist/crypto/Digest.js +146 -0
- package/dist/crypto/Digest.js.map +1 -0
- package/dist/crypto/Kdf.d.ts +220 -0
- package/dist/crypto/Kdf.d.ts.map +1 -0
- package/dist/crypto/Kdf.js +212 -0
- package/dist/crypto/Kdf.js.map +1 -0
- package/dist/crypto/KeyAgreement.d.ts +323 -0
- package/dist/crypto/KeyAgreement.d.ts.map +1 -0
- package/dist/crypto/KeyAgreement.js +303 -0
- package/dist/crypto/KeyAgreement.js.map +1 -0
- package/dist/crypto/KeyFormat.d.ts +309 -0
- package/dist/crypto/KeyFormat.d.ts.map +1 -0
- package/dist/crypto/KeyFormat.js +556 -0
- package/dist/crypto/KeyFormat.js.map +1 -0
- package/dist/crypto/KeyWrap.d.ts +389 -0
- package/dist/crypto/KeyWrap.d.ts.map +1 -0
- package/dist/crypto/KeyWrap.js +381 -0
- package/dist/crypto/KeyWrap.js.map +1 -0
- package/dist/crypto/Mac.d.ts +277 -0
- package/dist/crypto/Mac.d.ts.map +1 -0
- package/dist/crypto/Mac.js +288 -0
- package/dist/crypto/Mac.js.map +1 -0
- package/dist/crypto/SecureRandom.d.ts +340 -0
- package/dist/crypto/SecureRandom.d.ts.map +1 -0
- package/dist/crypto/SecureRandom.js +257 -0
- package/dist/crypto/SecureRandom.js.map +1 -0
- package/dist/crypto/Signature.d.ts +448 -0
- package/dist/crypto/Signature.d.ts.map +1 -0
- package/dist/crypto/Signature.js +484 -0
- package/dist/crypto/Signature.js.map +1 -0
- package/dist/crypto/WebCrypto.d.ts +61 -0
- package/dist/crypto/WebCrypto.d.ts.map +1 -0
- package/dist/crypto/WebCrypto.js +63 -0
- package/dist/crypto/WebCrypto.js.map +1 -0
- package/dist/crypto/index.d.ts +65 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +66 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/internal/asymmetric.d.ts +2 -0
- package/dist/crypto/internal/asymmetric.d.ts.map +1 -0
- package/dist/crypto/internal/asymmetric.js +210 -0
- package/dist/crypto/internal/asymmetric.js.map +1 -0
- package/dist/crypto/internal/chacha.d.ts +46 -0
- package/dist/crypto/internal/chacha.d.ts.map +1 -0
- package/dist/crypto/internal/chacha.js +885 -0
- package/dist/crypto/internal/chacha.js.map +1 -0
- package/dist/crypto/internal/der.d.ts +6 -0
- package/dist/crypto/internal/der.d.ts.map +1 -0
- package/dist/crypto/internal/der.js +86 -0
- package/dist/crypto/internal/der.js.map +1 -0
- package/dist/crypto/internal/digest.d.ts +2 -0
- package/dist/crypto/internal/digest.d.ts.map +1 -0
- package/dist/crypto/internal/digest.js +15 -0
- package/dist/crypto/internal/digest.js.map +1 -0
- package/dist/crypto/internal/key.d.ts +2 -0
- package/dist/crypto/internal/key.d.ts.map +1 -0
- package/dist/crypto/internal/key.js +170 -0
- package/dist/crypto/internal/key.js.map +1 -0
- package/dist/crypto/internal/md5.d.ts +39 -0
- package/dist/crypto/internal/md5.d.ts.map +1 -0
- package/dist/crypto/internal/md5.js +179 -0
- package/dist/crypto/internal/md5.js.map +1 -0
- package/dist/crypto/internal/webCrypto.d.ts +2 -0
- package/dist/crypto/internal/webCrypto.d.ts.map +1 -0
- package/dist/crypto/internal/webCrypto.js +111 -0
- package/dist/crypto/internal/webCrypto.js.map +1 -0
- package/dist/encoding/Base64Url.d.ts.map +1 -1
- package/dist/encoding/Base64Url.js +3 -2
- package/dist/encoding/Base64Url.js.map +1 -1
- package/dist/encoding/Csv.d.ts +608 -0
- package/dist/encoding/Csv.d.ts.map +1 -0
- package/dist/encoding/Csv.js +718 -0
- package/dist/encoding/Csv.js.map +1 -0
- package/dist/encoding/Hex.d.ts +3 -2
- package/dist/encoding/Hex.d.ts.map +1 -1
- package/dist/encoding/Hex.js +3 -2
- package/dist/encoding/Hex.js.map +1 -1
- package/dist/encoding/SchemaBinary.d.ts.map +1 -1
- package/dist/encoding/SchemaBinary.js +42 -4
- package/dist/encoding/SchemaBinary.js.map +1 -1
- package/dist/encoding/Toml.d.ts +17 -3
- package/dist/encoding/Toml.d.ts.map +1 -1
- package/dist/encoding/Toml.js +104 -16
- package/dist/encoding/Toml.js.map +1 -1
- package/dist/encoding/Yaml.d.ts +8 -1
- package/dist/encoding/Yaml.d.ts.map +1 -1
- package/dist/encoding/Yaml.js +54 -18
- package/dist/encoding/Yaml.js.map +1 -1
- package/dist/encoding/index.d.ts +5 -0
- package/dist/encoding/index.d.ts.map +1 -1
- package/dist/encoding/index.js +5 -0
- package/dist/encoding/index.js.map +1 -1
- package/dist/eventlog/EventJournal.d.ts.map +1 -1
- package/dist/eventlog/EventJournal.js +6 -3
- package/dist/eventlog/EventJournal.js.map +1 -1
- package/dist/eventlog/EventLog.d.ts +119 -4
- package/dist/eventlog/EventLog.d.ts.map +1 -1
- package/dist/eventlog/EventLog.js +200 -12
- package/dist/eventlog/EventLog.js.map +1 -1
- package/dist/eventlog/EventLogEncryption.d.ts +41 -4
- package/dist/eventlog/EventLogEncryption.d.ts.map +1 -1
- package/dist/eventlog/EventLogEncryption.js +83 -64
- package/dist/eventlog/EventLogEncryption.js.map +1 -1
- package/dist/eventlog/EventLogMessage.d.ts +279 -0
- package/dist/eventlog/EventLogMessage.d.ts.map +1 -1
- package/dist/eventlog/EventLogMessage.js +217 -1
- package/dist/eventlog/EventLogMessage.js.map +1 -1
- package/dist/eventlog/EventLogRemote.d.ts +200 -28
- package/dist/eventlog/EventLogRemote.d.ts.map +1 -1
- package/dist/eventlog/EventLogRemote.js +186 -16
- package/dist/eventlog/EventLogRemote.js.map +1 -1
- package/dist/eventlog/EventLogServer.d.ts +3 -0
- package/dist/eventlog/EventLogServer.d.ts.map +1 -1
- package/dist/eventlog/EventLogServer.js +18 -10
- package/dist/eventlog/EventLogServer.js.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.d.ts +326 -5
- package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.js +769 -14
- package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.d.ts +5 -3
- package/dist/eventlog/EventLogSessionAuth.d.ts.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.js +41 -64
- package/dist/eventlog/EventLogSessionAuth.js.map +1 -1
- package/dist/eventlog/EventRow.d.ts +4 -0
- package/dist/eventlog/EventRow.d.ts.map +1 -1
- package/dist/eventlog/EventRow.js +12 -2
- package/dist/eventlog/EventRow.js.map +1 -1
- package/dist/eventlog/SqlEventJournal.js +2 -2
- package/dist/eventlog/SqlEventJournal.js.map +1 -1
- package/dist/eventlog/SqlEventLogServerEncrypted.d.ts +21 -5
- package/dist/eventlog/SqlEventLogServerEncrypted.d.ts.map +1 -1
- package/dist/eventlog/SqlEventLogServerEncrypted.js +1048 -113
- package/dist/eventlog/SqlEventLogServerEncrypted.js.map +1 -1
- package/dist/eventlog/SqlEventLogServerUnencrypted.js +2 -2
- package/dist/eventlog/SqlEventLogServerUnencrypted.js.map +1 -1
- package/dist/eventlog/internal/batches.d.ts +12 -0
- package/dist/eventlog/internal/batches.d.ts.map +1 -0
- package/dist/eventlog/internal/batches.js +26 -0
- package/dist/eventlog/internal/batches.js.map +1 -0
- package/dist/eventlog/internal/compaction.d.ts +38 -0
- package/dist/eventlog/internal/compaction.d.ts.map +1 -0
- package/dist/eventlog/internal/compaction.js +33 -0
- package/dist/eventlog/internal/compaction.js.map +1 -0
- package/dist/eventlog/internal/identityRootSecretDerivation.js +66 -67
- package/dist/eventlog/internal/identityRootSecretDerivation.js.map +1 -1
- package/dist/eventlog/internal/remoteCompaction.d.ts +31 -0
- package/dist/eventlog/internal/remoteCompaction.d.ts.map +1 -0
- package/dist/eventlog/internal/remoteCompaction.js +76 -0
- package/dist/eventlog/internal/remoteCompaction.js.map +1 -0
- package/dist/http/Cookies.d.ts +172 -0
- package/dist/http/Cookies.d.ts.map +1 -1
- package/dist/http/Cookies.js +143 -1
- package/dist/http/Cookies.js.map +1 -1
- package/dist/http/FetchHttpClient.d.ts +26 -2
- package/dist/http/FetchHttpClient.d.ts.map +1 -1
- package/dist/http/FetchHttpClient.js +78 -15
- package/dist/http/FetchHttpClient.js.map +1 -1
- package/dist/http/HttpClient.d.ts +79 -8
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +65 -5
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpClientRequest.d.ts +9 -5
- package/dist/http/HttpClientRequest.d.ts.map +1 -1
- package/dist/http/HttpClientRequest.js +2 -3
- package/dist/http/HttpClientRequest.js.map +1 -1
- package/dist/http/HttpClientResponse.d.ts.map +1 -1
- package/dist/http/HttpClientResponse.js +3 -2
- package/dist/http/HttpClientResponse.js.map +1 -1
- package/dist/http/HttpMethod.d.ts +7 -1
- package/dist/http/HttpMethod.d.ts.map +1 -1
- package/dist/http/HttpMethod.js +3 -8
- package/dist/http/HttpMethod.js.map +1 -1
- package/dist/http/HttpServerRequest.d.ts +5 -2
- package/dist/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/http/HttpServerRequest.js +6 -17
- package/dist/http/HttpServerRequest.js.map +1 -1
- package/dist/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/http/HttpServerResponse.js +3 -2
- package/dist/http/HttpServerResponse.js.map +1 -1
- package/dist/http/HttpTraceContext.d.ts +2 -1
- package/dist/http/HttpTraceContext.d.ts.map +1 -1
- package/dist/http/HttpTraceContext.js +7 -5
- package/dist/http/HttpTraceContext.js.map +1 -1
- package/dist/http/ProblemDetails.d.ts +96 -0
- package/dist/http/ProblemDetails.d.ts.map +1 -0
- package/dist/http/ProblemDetails.js +98 -0
- package/dist/http/ProblemDetails.js.map +1 -0
- package/dist/http/index.d.ts +5 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +5 -0
- package/dist/http/index.js.map +1 -1
- package/dist/http/internal/decompression.js +3 -2
- package/dist/http/internal/decompression.js.map +1 -1
- package/dist/http/internal/urlParams.js +8 -0
- package/dist/http/internal/urlParams.js.map +1 -1
- package/dist/http-api/HttpApiBuilder.js +19 -5
- package/dist/http-api/HttpApiBuilder.js.map +1 -1
- package/dist/http-api/HttpApiClient.d.ts +63 -0
- package/dist/http-api/HttpApiClient.d.ts.map +1 -1
- package/dist/http-api/HttpApiClient.js +51 -0
- package/dist/http-api/HttpApiClient.js.map +1 -1
- package/dist/http-api/HttpApiEndpoint.d.ts.map +1 -1
- package/dist/http-api/HttpApiEndpoint.js +14 -5
- package/dist/http-api/HttpApiEndpoint.js.map +1 -1
- package/dist/http-api/HttpApiError.d.ts +185 -13
- package/dist/http-api/HttpApiError.d.ts.map +1 -1
- package/dist/http-api/HttpApiError.js +128 -0
- package/dist/http-api/HttpApiError.js.map +1 -1
- package/dist/http-api/HttpApiMiddleware.d.ts +64 -17
- package/dist/http-api/HttpApiMiddleware.d.ts.map +1 -1
- package/dist/http-api/HttpApiMiddleware.js +85 -1
- package/dist/http-api/HttpApiMiddleware.js.map +1 -1
- package/dist/http-api/HttpApiSchema.d.ts +76 -14
- package/dist/http-api/HttpApiSchema.d.ts.map +1 -1
- package/dist/http-api/HttpApiSchema.js +53 -0
- package/dist/http-api/HttpApiSchema.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/internal/effect.js +25 -14
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/glob.d.ts +2 -0
- package/dist/internal/glob.d.ts.map +1 -0
- package/dist/internal/glob.js +630 -0
- package/dist/internal/glob.js.map +1 -0
- package/dist/internal/matcher.js +10 -0
- package/dist/internal/matcher.js.map +1 -1
- package/dist/internal/persistence.js +9 -0
- package/dist/internal/persistence.js.map +1 -1
- package/dist/internal/rcRef.js +4 -1
- package/dist/internal/rcRef.js.map +1 -1
- package/dist/internal/schema/toCodeDocument.js +6 -3
- package/dist/internal/schema/toCodeDocument.js.map +1 -1
- package/dist/internal/trie.js +42 -13
- package/dist/internal/trie.js.map +1 -1
- package/dist/internal/ulid.js +41 -0
- package/dist/internal/ulid.js.map +1 -1
- package/dist/internal/uuid.js +52 -8
- package/dist/internal/uuid.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/observability/Otlp.d.ts +15 -4
- package/dist/observability/Otlp.d.ts.map +1 -1
- package/dist/observability/Otlp.js +10 -0
- package/dist/observability/Otlp.js.map +1 -1
- package/dist/observability/OtlpResource.d.ts +7 -0
- package/dist/observability/OtlpResource.d.ts.map +1 -1
- package/dist/observability/OtlpResource.js +11 -1
- package/dist/observability/OtlpResource.js.map +1 -1
- package/dist/persistence/KeyValueStore.d.ts +47 -2
- package/dist/persistence/KeyValueStore.d.ts.map +1 -1
- package/dist/persistence/KeyValueStore.js +129 -18
- package/dist/persistence/KeyValueStore.js.map +1 -1
- package/dist/persistence/PersistedQueue.d.ts +9 -0
- package/dist/persistence/PersistedQueue.d.ts.map +1 -1
- package/dist/persistence/PersistedQueue.js +94 -52
- package/dist/persistence/PersistedQueue.js.map +1 -1
- package/dist/persistence/Persistence.d.ts +10 -4
- package/dist/persistence/Persistence.d.ts.map +1 -1
- package/dist/persistence/Persistence.js +18 -11
- package/dist/persistence/Persistence.js.map +1 -1
- package/dist/process/ChildProcess.d.ts +207 -67
- package/dist/process/ChildProcess.d.ts.map +1 -1
- package/dist/process/ChildProcess.js +56 -158
- package/dist/process/ChildProcess.js.map +1 -1
- package/dist/process/ChildProcessSpawner.d.ts +5 -0
- package/dist/process/ChildProcessSpawner.d.ts.map +1 -1
- package/dist/process/ChildProcessSpawner.js.map +1 -1
- package/dist/process/CommandLine.d.ts +294 -0
- package/dist/process/CommandLine.d.ts.map +1 -0
- package/dist/process/CommandLine.js +481 -0
- package/dist/process/CommandLine.js.map +1 -0
- package/dist/process/index.d.ts +5 -0
- package/dist/process/index.d.ts.map +1 -1
- package/dist/process/index.js +5 -0
- package/dist/process/index.js.map +1 -1
- package/dist/reactivity/Atom.d.ts +2 -1
- package/dist/reactivity/Atom.d.ts.map +1 -1
- package/dist/reactivity/Atom.js +3 -4
- package/dist/reactivity/Atom.js.map +1 -1
- package/dist/reactivity/AtomRegistry.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts +16 -1
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +50 -16
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcMessage.d.ts +10 -1
- package/dist/rpc/RpcMessage.d.ts.map +1 -1
- package/dist/rpc/RpcMessage.js +1 -0
- package/dist/rpc/RpcMessage.js.map +1 -1
- package/dist/rpc/RpcSerialization.d.ts.map +1 -1
- package/dist/rpc/RpcSerialization.js +6 -0
- package/dist/rpc/RpcSerialization.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts +31 -0
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +139 -66
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/schema/Model.d.ts +14 -0
- package/dist/schema/Model.d.ts.map +1 -1
- package/dist/schema/Model.js +18 -3
- package/dist/schema/Model.js.map +1 -1
- package/dist/sql/Migrator.d.ts +0 -19
- package/dist/sql/Migrator.d.ts.map +1 -1
- package/dist/sql/Migrator.js +3 -48
- package/dist/sql/Migrator.js.map +1 -1
- package/dist/sql/MigratorFileSystem.d.ts +21 -0
- package/dist/sql/MigratorFileSystem.d.ts.map +1 -0
- package/dist/sql/MigratorFileSystem.js +57 -0
- package/dist/sql/MigratorFileSystem.js.map +1 -0
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +5 -9
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/sql/Statement.d.ts +20 -6
- package/dist/sql/Statement.d.ts.map +1 -1
- package/dist/sql/Statement.js +0 -13
- package/dist/sql/Statement.js.map +1 -1
- package/dist/sql/index.js +1 -1
- package/dist/testing/index.d.ts +0 -5
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +0 -5
- package/dist/testing/index.js.map +1 -1
- package/dist/workflow/internal/crypto.js +9 -8
- package/dist/workflow/internal/crypto.js.map +1 -1
- package/package.json +3 -1
- package/src/BigDecimal.ts +3 -0
- package/src/Channel.ts +17 -11
- package/src/Config.ts +7 -1
- package/src/Context.ts +34 -10
- package/src/Cron.ts +178 -29
- package/src/Duration.ts +140 -0
- package/src/Effect.ts +914 -85
- package/src/FileSystem.ts +65 -4
- package/src/Glob.ts +205 -0
- package/src/Match.ts +127 -0
- package/src/Pool.ts +73 -15
- package/src/Random.ts +3 -3
- package/src/RcMap.ts +5 -1
- package/src/Schedule.ts +26 -3
- package/src/Schema.ts +1189 -62
- package/src/SchemaGetter.ts +27 -11
- package/src/SchemaRepresentation.ts +19 -0
- package/src/SchemaTransformation.ts +8 -3
- package/src/ScopedCache.ts +5 -9
- package/src/Semaphore.ts +141 -0
- package/src/Stream.ts +15 -6
- package/src/Terminal.ts +19 -1
- package/src/ai/AiError.ts +56 -80
- package/src/ai/Decision.ts +257 -6
- package/src/ai/DecisionModel.ts +171 -28
- package/src/ai/McpServer.ts +1269 -286
- package/src/ai/McpTest.ts +380 -0
- package/src/ai/Response.ts +2 -22
- package/src/ai/Tool.ts +27 -8
- package/src/ai/index.ts +6 -0
- package/src/ai/internal/mcpCore.ts +78 -44
- package/src/ai/internal/mcpProtocol/v2024_11_05.ts +4 -7
- package/src/ai/internal/mcpProtocol/v2025_03_26.ts +4 -7
- package/src/ai/internal/mcpProtocol/v2025_06_18.ts +4 -7
- package/src/ai/internal/mcpProtocol/v2025_11_25.ts +4 -7
- package/src/ai/internal/mcpProtocol/v2026_07_28.ts +15 -10
- package/src/ai/internal/mcpProtocol.ts +29 -0
- package/src/ai/internal/mcpRuntime.ts +9 -5
- package/src/ai/internal/mcpStatefulRuntime.ts +14 -2
- package/src/cli/Argument.ts +6 -0
- package/src/cli/CliOutput.ts +117 -49
- package/src/cli/Command.ts +23 -0
- package/src/cli/Flag.ts +107 -0
- package/src/cli/HelpDoc.ts +18 -1
- package/src/cli/Param.ts +6 -0
- package/src/cli/Primitive.ts +16 -1
- package/src/cli/Prompt.ts +1 -0
- package/src/cli/internal/help.ts +21 -9
- package/src/cluster/Sharding.ts +93 -26
- package/src/cluster/ShardingConfig.ts +41 -3
- package/src/cluster/SingleRunner.ts +3 -3
- package/src/cluster/SqlMessageStorage.ts +49 -17
- package/src/cluster/SqlRunnerStorage.ts +37 -27
- package/src/crypto/Aead.ts +517 -0
- package/src/crypto/Cipher.ts +326 -0
- package/src/crypto/CryptoError.ts +242 -0
- package/src/crypto/Digest.ts +167 -0
- package/src/crypto/Kdf.ts +315 -0
- package/src/crypto/KeyAgreement.ts +489 -0
- package/src/crypto/KeyFormat.ts +712 -0
- package/src/crypto/KeyWrap.ts +639 -0
- package/src/crypto/Mac.ts +386 -0
- package/src/crypto/SecureRandom.ts +459 -0
- package/src/crypto/Signature.ts +673 -0
- package/src/crypto/WebCrypto.ts +64 -0
- package/src/crypto/index.ts +78 -0
- package/src/crypto/internal/asymmetric.ts +329 -0
- package/src/crypto/internal/chacha.ts +1088 -0
- package/src/crypto/internal/der.ts +110 -0
- package/src/crypto/internal/digest.ts +16 -0
- package/src/crypto/internal/key.ts +235 -0
- package/src/crypto/internal/md5.ts +170 -0
- package/src/crypto/internal/webCrypto.ts +150 -0
- package/src/encoding/Base64Url.ts +5 -2
- package/src/encoding/Csv.ts +1298 -0
- package/src/encoding/Hex.ts +3 -2
- package/src/encoding/SchemaBinary.ts +40 -4
- package/src/encoding/Toml.ts +85 -20
- package/src/encoding/Yaml.ts +61 -18
- package/src/encoding/index.ts +6 -0
- package/src/eventlog/EventJournal.ts +4 -3
- package/src/eventlog/EventLog.ts +340 -15
- package/src/eventlog/EventLogEncryption.ts +118 -110
- package/src/eventlog/EventLogMessage.ts +273 -1
- package/src/eventlog/EventLogRemote.ts +367 -23
- package/src/eventlog/EventLogServer.ts +23 -8
- package/src/eventlog/EventLogServerEncrypted.ts +1130 -67
- package/src/eventlog/EventLogSessionAuth.ts +56 -70
- package/src/eventlog/EventRow.ts +12 -3
- package/src/eventlog/SqlEventJournal.ts +2 -2
- package/src/eventlog/SqlEventLogServerEncrypted.ts +1244 -136
- package/src/eventlog/SqlEventLogServerUnencrypted.ts +2 -2
- package/src/eventlog/internal/batches.ts +30 -0
- package/src/eventlog/internal/compaction.ts +64 -0
- package/src/eventlog/internal/identityRootSecretDerivation.ts +93 -123
- package/src/eventlog/internal/remoteCompaction.ts +92 -0
- package/src/http/Cookies.ts +281 -1
- package/src/http/FetchHttpClient.ts +88 -16
- package/src/http/HttpClient.ts +89 -22
- package/src/http/HttpClientRequest.ts +12 -9
- package/src/http/HttpClientResponse.ts +3 -2
- package/src/http/HttpMethod.ts +10 -2
- package/src/http/HttpServerRequest.ts +15 -30
- package/src/http/HttpServerResponse.ts +3 -2
- package/src/http/HttpTraceContext.ts +7 -4
- package/src/http/ProblemDetails.ts +149 -0
- package/src/http/index.ts +6 -0
- package/src/http/internal/decompression.ts +4 -4
- package/src/http/internal/urlParams.ts +8 -0
- package/src/http-api/HttpApiBuilder.ts +24 -12
- package/src/http-api/HttpApiClient.ts +67 -1
- package/src/http-api/HttpApiEndpoint.ts +14 -5
- package/src/http-api/HttpApiError.ts +250 -0
- package/src/http-api/HttpApiMiddleware.ts +95 -1
- package/src/http-api/HttpApiSchema.ts +105 -14
- package/src/index.ts +6 -6
- package/src/internal/effect.ts +34 -18
- package/src/internal/glob.ts +736 -0
- package/src/internal/matcher.ts +17 -0
- package/src/internal/persistence.ts +11 -0
- package/src/internal/rcRef.ts +4 -1
- package/src/internal/schema/toCodeDocument.ts +7 -3
- package/src/internal/trie.ts +43 -14
- package/src/internal/ulid.ts +44 -0
- package/src/internal/uuid.ts +57 -16
- package/src/internal/version.ts +1 -1
- package/src/observability/Otlp.ts +21 -4
- package/src/observability/OtlpResource.ts +9 -1
- package/src/persistence/KeyValueStore.ts +219 -22
- package/src/persistence/PersistedQueue.ts +128 -59
- package/src/persistence/Persistence.ts +20 -13
- package/src/process/ChildProcess.ts +255 -260
- package/src/process/ChildProcessSpawner.ts +5 -0
- package/src/process/CommandLine.ts +630 -0
- package/src/process/index.ts +6 -0
- package/src/reactivity/Atom.ts +5 -5
- package/src/reactivity/AtomRegistry.ts +1 -1
- package/src/rpc/RpcClient.ts +62 -26
- package/src/rpc/RpcMessage.ts +10 -1
- package/src/rpc/RpcSerialization.ts +3 -0
- package/src/rpc/RpcServer.ts +176 -78
- package/src/schema/Model.ts +26 -3
- package/src/sql/Migrator.ts +4 -63
- package/src/sql/MigratorFileSystem.ts +71 -0
- package/src/sql/SqlClient.ts +2 -16
- package/src/sql/Statement.ts +8 -7
- package/src/sql/index.ts +1 -1
- package/src/testing/index.ts +0 -6
- package/src/workflow/internal/crypto.ts +15 -11
- package/dist/Crypto.d.ts +0 -244
- package/dist/Crypto.d.ts.map +0 -1
- package/dist/Crypto.js +0 -139
- package/dist/Crypto.js.map +0 -1
- package/dist/testing/TestCrypto.d.ts +0 -73
- package/dist/testing/TestCrypto.d.ts.map +0 -1
- package/dist/testing/TestCrypto.js +0 -87
- package/dist/testing/TestCrypto.js.map +0 -1
- package/src/Crypto.ts +0 -347
- package/src/testing/TestCrypto.ts +0 -94
package/src/eventlog/EventLog.ts
CHANGED
|
@@ -7,6 +7,45 @@
|
|
|
7
7
|
* committed only after the handler succeeds. This module also contains the
|
|
8
8
|
* layers and helpers needed to assemble that runtime.
|
|
9
9
|
*
|
|
10
|
+
* **Remote compaction**
|
|
11
|
+
*
|
|
12
|
+
* An encrypted remote whose server sets `HelloResponse.compaction` can store a
|
|
13
|
+
* compacted snapshot of its history, so a new device replays the snapshot and
|
|
14
|
+
* a recent tail instead of every write. Clients build the snapshots because
|
|
15
|
+
* only they can decrypt the entries.
|
|
16
|
+
*
|
|
17
|
+
* Only a client with a `remote: true` compactor, on a remote not built with
|
|
18
|
+
* `compaction: false`, calls the compaction RPCs. It polls the status on
|
|
19
|
+
* connect and about hourly. When the server wants compaction and the journal
|
|
20
|
+
* has caught up, it starts a background run after a random delay of a few
|
|
21
|
+
* minutes. The run reads the input, taking entries from the journal where it
|
|
22
|
+
* can and fetching the rest, runs the opted-in compactors and uploads the
|
|
23
|
+
* entries they keep. The server lets one run per store hold a stage and
|
|
24
|
+
* answers the others `Busy`, so devices that start together download the
|
|
25
|
+
* input once. `EventLog.compact` starts a run immediately, for example from
|
|
26
|
+
* a worker holding the identity.
|
|
27
|
+
*
|
|
28
|
+
* An operator can roll back a bad snapshot on the server. The server then
|
|
29
|
+
* re-appends the snapshot's input at the head, so every client, including
|
|
30
|
+
* ones from before remote compaction, receives the dropped entries through
|
|
31
|
+
* `changes` and skips the ones it already holds.
|
|
32
|
+
*
|
|
33
|
+
* Known limitations:
|
|
34
|
+
*
|
|
35
|
+
* - A run holds every kept entry in memory. A device with a large store can
|
|
36
|
+
* opt out with `compaction: false` and leave compaction to a device or
|
|
37
|
+
* worker with more memory.
|
|
38
|
+
* - The library can't check that a compactor keeps the `remote` contract (see
|
|
39
|
+
* `groupCompaction`). The drop-only and idempotence checks catch common
|
|
40
|
+
* mistakes. A snapshot that drops too much can only be undone by a rollback
|
|
41
|
+
* before the server prunes the history.
|
|
42
|
+
* - Changes to a field's meaning between schema versions aren't detected.
|
|
43
|
+
* Strict decoding only catches unknown fields.
|
|
44
|
+
* - A new device still replays the newest day or so of writes, because the
|
|
45
|
+
* server only compacts data older than its lag.
|
|
46
|
+
* - A client that stops partway through a run holds the server's busy claim
|
|
47
|
+
* until its stage expires.
|
|
48
|
+
*
|
|
10
49
|
* @stability unstable
|
|
11
50
|
* @since 4.0.0
|
|
12
51
|
*/
|
|
@@ -14,15 +53,20 @@ import * as Arr from "../Array.ts"
|
|
|
14
53
|
import * as Cause from "../Cause.ts"
|
|
15
54
|
import * as Context from "../Context.ts"
|
|
16
55
|
import * as Effect from "../Effect.ts"
|
|
56
|
+
import * as SchemaBinary from "../encoding/SchemaBinary.ts"
|
|
57
|
+
import * as Equal from "../Equal.ts"
|
|
58
|
+
import * as FiberHandle from "../FiberHandle.ts"
|
|
17
59
|
import * as FiberMap from "../FiberMap.ts"
|
|
18
60
|
import { constant, identity } from "../Function.ts"
|
|
19
61
|
import * as InternalRecord from "../internal/record.ts"
|
|
62
|
+
import * as Uuid from "../internal/uuid.ts"
|
|
20
63
|
import * as Layer from "../Layer.ts"
|
|
21
64
|
import type { Pipeable } from "../Pipeable.ts"
|
|
22
65
|
import { pipeArguments } from "../Pipeable.ts"
|
|
23
66
|
import * as Predicate from "../Predicate.ts"
|
|
24
67
|
import * as PubSub from "../PubSub.ts"
|
|
25
68
|
import * as Queue from "../Queue.ts"
|
|
69
|
+
import * as Random from "../Random.ts"
|
|
26
70
|
import { Reactivity } from "../reactivity/Reactivity.ts"
|
|
27
71
|
import * as ReactivityLayer from "../reactivity/Reactivity.ts"
|
|
28
72
|
import type * as Record from "../Record.ts"
|
|
@@ -33,14 +77,22 @@ import * as Schedule from "../Schedule.ts"
|
|
|
33
77
|
import * as Schema from "../Schema.ts"
|
|
34
78
|
import * as SchemaGetter from "../SchemaGetter.ts"
|
|
35
79
|
import type * as Scope from "../Scope.ts"
|
|
80
|
+
import * as Stream from "../Stream.ts"
|
|
36
81
|
import type { Covariant } from "../Types.ts"
|
|
37
82
|
import type * as Event from "./Event.ts"
|
|
38
83
|
import type * as EventGroup from "./EventGroup.ts"
|
|
39
84
|
import { Entry, EventJournal, type EventJournalError, makeEntryIdUnsafe, type RemoteId } from "./EventJournal.ts"
|
|
40
85
|
import * as EventLogEncryption from "./EventLogEncryption.ts"
|
|
41
|
-
import { StoreId } from "./EventLogMessage.ts"
|
|
42
|
-
import type {
|
|
86
|
+
import { type CompactionInputHeader, EventLogProtocolError, StoreId } from "./EventLogMessage.ts"
|
|
87
|
+
import type {
|
|
88
|
+
CompactionStage,
|
|
89
|
+
EventLogRemote,
|
|
90
|
+
EventLogRemoteCompaction,
|
|
91
|
+
EventLogRemoteError
|
|
92
|
+
} from "./EventLogRemote.ts"
|
|
93
|
+
import { maxBatchEntries } from "./internal/batches.ts"
|
|
43
94
|
import { setAnchor } from "./internal/conflicts.ts"
|
|
95
|
+
import * as RemoteCompaction from "./internal/remoteCompaction.ts"
|
|
44
96
|
|
|
45
97
|
/**
|
|
46
98
|
* Service for writing typed event-log events through registered handlers.
|
|
@@ -87,6 +139,30 @@ export class EventLog extends Context.Service<EventLog, {
|
|
|
87
139
|
>
|
|
88
140
|
readonly entries: Effect.Effect<ReadonlyArray<Entry>, EventJournalError>
|
|
89
141
|
readonly destroy: Effect.Effect<void, EventJournalError>
|
|
142
|
+
/**
|
|
143
|
+
* Runs one remote compaction now, on every registered remote that offers
|
|
144
|
+
* compaction or only on `remoteId`.
|
|
145
|
+
*
|
|
146
|
+
* Unlike the background trigger, it doesn't wait for the journal to catch
|
|
147
|
+
* up, and it works from an empty journal. Remotes built with
|
|
148
|
+
* `compaction: false` are skipped, and nothing runs when no compactor is
|
|
149
|
+
* registered with `remote: true`.
|
|
150
|
+
*
|
|
151
|
+
* `Committed` and `Superseded` mean a snapshot was uploaded, `NoOp` that
|
|
152
|
+
* nothing was dropped, and `NotWanted` and `Busy` come from the server.
|
|
153
|
+
* `Aborted` means nothing was uploaded and the stage was released, because
|
|
154
|
+
* a compactor died, the idempotence check failed, every entry was dropped
|
|
155
|
+
* or the input was pruned during the run.
|
|
156
|
+
*/
|
|
157
|
+
readonly compact: (options?: {
|
|
158
|
+
readonly remoteId?: RemoteId | undefined
|
|
159
|
+
}) => Effect.Effect<
|
|
160
|
+
ReadonlyArray<{
|
|
161
|
+
readonly remoteId: RemoteId
|
|
162
|
+
readonly result: "Committed" | "Superseded" | "NoOp" | "NotWanted" | "Busy" | "Aborted"
|
|
163
|
+
}>,
|
|
164
|
+
EventJournalError | EventLogRemoteError
|
|
165
|
+
>
|
|
90
166
|
}>()("effect/eventlog/EventLog") {}
|
|
91
167
|
|
|
92
168
|
/**
|
|
@@ -107,8 +183,18 @@ export class Registry extends Context.Service<Registry, {
|
|
|
107
183
|
|
|
108
184
|
readonly registerCompaction: (options: {
|
|
109
185
|
readonly events: ReadonlyArray<string>
|
|
186
|
+
/**
|
|
187
|
+
* Also run this compactor over a remote's history to build snapshots. The
|
|
188
|
+
* kept entries must depend only on the set of input entries and compose:
|
|
189
|
+
* `drop(drop(a) ++ b)` keeps the same entries as `drop(a ++ b)`, even when
|
|
190
|
+
* `b` holds entries older than `a`. A call that writes an entry it wasn't
|
|
191
|
+
* given keeps its whole input.
|
|
192
|
+
*/
|
|
193
|
+
readonly remote?: boolean | undefined
|
|
110
194
|
readonly effect: (options: {
|
|
111
195
|
readonly entries: ReadonlyArray<Entry>
|
|
196
|
+
/** True during a remote compaction, which only drops entries. */
|
|
197
|
+
readonly remote?: boolean | undefined
|
|
112
198
|
// Pass an input entry as source to anchor replacements during remote replay.
|
|
113
199
|
// Without it, matching IDs retain their position; new IDs use the group start.
|
|
114
200
|
readonly write: (entry: Entry, source?: Entry) => Effect.Effect<void>
|
|
@@ -117,13 +203,16 @@ export class Registry extends Context.Service<Registry, {
|
|
|
117
203
|
|
|
118
204
|
readonly compactors: ReadonlyMap<string, {
|
|
119
205
|
readonly events: ReadonlySet<string>
|
|
206
|
+
readonly remote: boolean
|
|
120
207
|
readonly effect: (options: {
|
|
121
208
|
readonly entries: ReadonlyArray<Entry>
|
|
209
|
+
readonly remote?: boolean | undefined
|
|
122
210
|
readonly write: (entry: Entry, source?: Entry) => Effect.Effect<void>
|
|
123
211
|
}) => Effect.Effect<void>
|
|
124
212
|
}>
|
|
125
213
|
|
|
126
214
|
readonly registerRemote: (remote: EventLogRemote["Service"]) => Effect.Effect<void, never, Scope.Scope>
|
|
215
|
+
readonly remotes: ReadonlyMap<RemoteId, EventLogRemote["Service"]>
|
|
127
216
|
readonly handleRemote: (handler: (remote: EventLogRemote["Service"]) => Effect.Effect<void>) => Effect.Effect<void>
|
|
128
217
|
|
|
129
218
|
readonly registerReactivity: (keys: Record<string, ReadonlyArray<string>>) => Effect.Effect<void, never, Scope.Scope>
|
|
@@ -145,8 +234,10 @@ export const layerRegistry = Layer.effect(
|
|
|
145
234
|
const handlers = new Map<string, Handlers.Item<any>>()
|
|
146
235
|
const compactors = new Map<string, {
|
|
147
236
|
readonly events: ReadonlySet<string>
|
|
237
|
+
readonly remote: boolean
|
|
148
238
|
readonly effect: (options: {
|
|
149
239
|
readonly entries: ReadonlyArray<Entry>
|
|
240
|
+
readonly remote?: boolean | undefined
|
|
150
241
|
readonly write: (entry: Entry, source?: Entry) => Effect.Effect<void>
|
|
151
242
|
}) => Effect.Effect<void>
|
|
152
243
|
}>()
|
|
@@ -166,6 +257,7 @@ export const layerRegistry = Layer.effect(
|
|
|
166
257
|
const events = new Set(options.events)
|
|
167
258
|
const compactor = {
|
|
168
259
|
events,
|
|
260
|
+
remote: options.remote ?? false,
|
|
169
261
|
effect: options.effect
|
|
170
262
|
}
|
|
171
263
|
for (const event of options.events) {
|
|
@@ -184,6 +276,7 @@ export const layerRegistry = Layer.effect(
|
|
|
184
276
|
return FiberMap.remove(remoteFiberMap, remote.id)
|
|
185
277
|
}
|
|
186
278
|
),
|
|
279
|
+
remotes,
|
|
187
280
|
handleRemote(handler) {
|
|
188
281
|
remoteHandler = handler
|
|
189
282
|
return Effect.forEach(remotes, ([id, remote]) => FiberMap.run(remoteFiberMap, id, handler(remote)), {
|
|
@@ -684,7 +777,8 @@ const registerBatchCompaction = <Events extends Event.Any, R>(
|
|
|
684
777
|
payload: Event.PayloadWithTag<Events, Tag>
|
|
685
778
|
) => Effect.Effect<void, never, Event.PayloadSchemaWithTag<Events, Tag>["EncodingServices"]>
|
|
686
779
|
readonly forward: (entry: Entry) => Effect.Effect<void>
|
|
687
|
-
}) => Effect.Effect<void, never, R
|
|
780
|
+
}) => Effect.Effect<void, never, R>,
|
|
781
|
+
options: { readonly remote?: boolean | undefined } | undefined
|
|
688
782
|
): Layer.Layer<never, never, R | Event.PayloadSchema<Events>["DecodingServices"] | Registry> =>
|
|
689
783
|
Layer.effectDiscard(
|
|
690
784
|
Effect.gen(function*() {
|
|
@@ -693,10 +787,15 @@ const registerBatchCompaction = <Events extends Event.Any, R>(
|
|
|
693
787
|
|
|
694
788
|
yield* registry.registerCompaction({
|
|
695
789
|
events: Object.keys(group.events),
|
|
696
|
-
|
|
790
|
+
remote: options?.remote,
|
|
791
|
+
effect: Effect.fnUntraced(function*({ entries, remote = false, write }): Effect.fn.Return<void> {
|
|
792
|
+
// In a remote compaction, unknown fields make an entry undecodable,
|
|
793
|
+
// and undecodable entries are always kept.
|
|
697
794
|
const isEventTag = (tag: string): tag is Event.Tag<Events> => Object.hasOwn(group.events, tag)
|
|
698
795
|
const decodePayload = <Tag extends Event.Tag<Events>>(tag: Tag, payload: Uint8Array) =>
|
|
699
|
-
Schema.decodeUnknownEffect(
|
|
796
|
+
Schema.decodeUnknownEffect(
|
|
797
|
+
remote ? SchemaBinary.toCodecStrict(group.events[tag].payload) : group.events[tag].payloadSchemaBinary
|
|
798
|
+
)(payload).pipe(
|
|
700
799
|
Effect.updateContext((input) => Context.merge(services, input))
|
|
701
800
|
) as unknown as Effect.Effect<Event.PayloadWithTag<Events, Tag>, Schema.SchemaError>
|
|
702
801
|
const writeFrom = Effect.fnUntraced(function*<Tag extends Event.Tag<Events>>(
|
|
@@ -726,6 +825,7 @@ const registerBatchCompaction = <Events extends Event.Any, R>(
|
|
|
726
825
|
continue
|
|
727
826
|
}
|
|
728
827
|
const payload = yield* Effect.result(decodePayload(entry.event, entry.payload))
|
|
828
|
+
if (remote && Result.isFailure(payload)) yield* forward(entry)
|
|
729
829
|
batch.push({
|
|
730
830
|
entry,
|
|
731
831
|
event: Result.isFailure(payload)
|
|
@@ -794,14 +894,36 @@ export const groupBatchCompaction = <Events extends Event.Any, R>(
|
|
|
794
894
|
payload: Event.PayloadWithTag<Events, Tag>
|
|
795
895
|
) => Effect.Effect<void, never, Event.PayloadSchemaWithTag<Events, Tag>["EncodingServices"]>
|
|
796
896
|
readonly forward: (entry: Entry) => Effect.Effect<void>
|
|
797
|
-
}) => Effect.Effect<void, never, R
|
|
897
|
+
}) => Effect.Effect<void, never, R>,
|
|
898
|
+
options?: {
|
|
899
|
+
/**
|
|
900
|
+
* Also run this compactor over a remote's history to build snapshots.
|
|
901
|
+
*
|
|
902
|
+
* Opting in promises a contract the library can't check. The kept entries
|
|
903
|
+
* depend only on the set of input entries, never on services, the clock
|
|
904
|
+
* or input order, and compaction composes: `drop(drop(a) ++ b)` keeps the
|
|
905
|
+
* same entries as `drop(a ++ b)`, even when `b` holds entries older than
|
|
906
|
+
* `a`.
|
|
907
|
+
*
|
|
908
|
+
* Remote compaction only drops entries. A call that uses `write` keeps its
|
|
909
|
+
* whole input, and entries that fail to decode, including ones with fields
|
|
910
|
+
* the schema doesn't know, are always kept. Before uploading, a run passes
|
|
911
|
+
* the kept entries through the compactors again and uploads nothing if
|
|
912
|
+
* that drops more or a compactor dies.
|
|
913
|
+
*
|
|
914
|
+
* A snapshot that drops too much can be rolled back on the server until
|
|
915
|
+
* the history it replaced is pruned. The module docs cover when runs start
|
|
916
|
+
* and other limitations.
|
|
917
|
+
*/
|
|
918
|
+
readonly remote?: boolean | undefined
|
|
919
|
+
}
|
|
798
920
|
): Layer.Layer<never, never, R | Event.PayloadSchema<Events>["DecodingServices"] | Registry> =>
|
|
799
921
|
registerBatchCompaction(group, ({ entries, writeFrom, forward }) =>
|
|
800
922
|
effect({
|
|
801
923
|
entries,
|
|
802
924
|
write: (tag, payload) => writeFrom(entries[0].entry, tag, payload),
|
|
803
925
|
forward
|
|
804
|
-
}))
|
|
926
|
+
}), options)
|
|
805
927
|
|
|
806
928
|
/**
|
|
807
929
|
* Registers a compaction handler for an event group.
|
|
@@ -848,7 +970,29 @@ export const groupCompaction = <Events extends Event.Any, R>(
|
|
|
848
970
|
payload: Event.PayloadWithTag<Events, Tag>
|
|
849
971
|
) => Effect.Effect<void, never, Event.PayloadSchemaWithTag<Events, Tag>["EncodingServices"]>
|
|
850
972
|
readonly forward: (entry: Entry) => Effect.Effect<void>
|
|
851
|
-
}) => Effect.Effect<void, never, R
|
|
973
|
+
}) => Effect.Effect<void, never, R>,
|
|
974
|
+
options?: {
|
|
975
|
+
/**
|
|
976
|
+
* Also run this compactor over a remote's history to build snapshots.
|
|
977
|
+
*
|
|
978
|
+
* Opting in promises a contract the library can't check. The kept entries
|
|
979
|
+
* depend only on the set of input entries, never on services, the clock
|
|
980
|
+
* or input order, and compaction composes: `drop(drop(a) ++ b)` keeps the
|
|
981
|
+
* same entries as `drop(a ++ b)`, even when `b` holds entries older than
|
|
982
|
+
* `a`.
|
|
983
|
+
*
|
|
984
|
+
* Remote compaction only drops entries. A call that uses `write` keeps its
|
|
985
|
+
* whole input, and entries that fail to decode, including ones with fields
|
|
986
|
+
* the schema doesn't know, are always kept. Before uploading, a run passes
|
|
987
|
+
* the kept entries through the compactors again and uploads nothing if
|
|
988
|
+
* that drops more or a compactor dies.
|
|
989
|
+
*
|
|
990
|
+
* A snapshot that drops too much can be rolled back on the server until
|
|
991
|
+
* the history it replaced is pruned. The module docs cover when runs start
|
|
992
|
+
* and other limitations.
|
|
993
|
+
*/
|
|
994
|
+
readonly remote?: boolean | undefined
|
|
995
|
+
}
|
|
852
996
|
): Layer.Layer<never, never, R | Event.PayloadSchema<Events>["DecodingServices"] | Registry> =>
|
|
853
997
|
registerBatchCompaction(
|
|
854
998
|
group,
|
|
@@ -883,7 +1027,8 @@ export const groupCompaction = <Events extends Event.Any, R>(
|
|
|
883
1027
|
forward
|
|
884
1028
|
})
|
|
885
1029
|
}
|
|
886
|
-
})
|
|
1030
|
+
}),
|
|
1031
|
+
options
|
|
887
1032
|
)
|
|
888
1033
|
|
|
889
1034
|
type ReactivityKeyName = [keyof ReactivityLayer.Keys] extends [never] ? string : keyof ReactivityLayer.Keys
|
|
@@ -1074,6 +1219,20 @@ const remoteRetrySchedule = Schedule.min([
|
|
|
1074
1219
|
Schedule.spaced({ seconds: 10 })
|
|
1075
1220
|
])
|
|
1076
1221
|
|
|
1222
|
+
type CompactionResult = Effect.Success<ReturnType<EventLog["Service"]["compact"]>>[number]["result"]
|
|
1223
|
+
|
|
1224
|
+
// Status is polled on each connect and then hourly, jittered.
|
|
1225
|
+
const compactionPollMillis = 60 * 60 * 1000
|
|
1226
|
+
|
|
1227
|
+
// Spreads out devices that see `wanted` at the same time.
|
|
1228
|
+
const compactionDelayMillis = { min: 60 * 1000, max: 5 * 60 * 1000 }
|
|
1229
|
+
|
|
1230
|
+
// How many input batch headers share one journal lookup and one fetch.
|
|
1231
|
+
const compactionLookupBatches = 16
|
|
1232
|
+
|
|
1233
|
+
const isNotFound = (error: EventLogRemoteError): boolean =>
|
|
1234
|
+
EventLogProtocolError.is(error.cause) && error.cause.code === "NotFound"
|
|
1235
|
+
|
|
1077
1236
|
const make = Effect.gen(function*() {
|
|
1078
1237
|
const storeId = yield* CurrentStoreId
|
|
1079
1238
|
const identity = yield* Identity
|
|
@@ -1097,13 +1256,160 @@ const make = Effect.gen(function*() {
|
|
|
1097
1256
|
const invalidateReactivityEntries = (entries: ReadonlyArray<Entry>) =>
|
|
1098
1257
|
Effect.forEach(entries, (entry) => invalidateEntry(reactivity, registry.reactivityKeys, entry), { discard: true })
|
|
1099
1258
|
|
|
1259
|
+
const hasRemoteCompactor = () => {
|
|
1260
|
+
for (const compactor of registry.compactors.values()) {
|
|
1261
|
+
if (compactor.remote) return true
|
|
1262
|
+
}
|
|
1263
|
+
return false
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// Resolves input headers to entries in input order, skipping ids seen at a
|
|
1267
|
+
// lower input sequence. Only batches with an id the journal lacks are
|
|
1268
|
+
// fetched.
|
|
1269
|
+
const resolveInput = Effect.fnUntraced(function*(
|
|
1270
|
+
compaction: EventLogRemoteCompaction,
|
|
1271
|
+
stage: CompactionStage,
|
|
1272
|
+
headers: ReadonlyArray<CompactionInputHeader>,
|
|
1273
|
+
seen: Set<string>
|
|
1274
|
+
) {
|
|
1275
|
+
const known = yield* journal.entriesById(headers.flatMap((header) => header.entryIds)).pipe(
|
|
1276
|
+
journal.withLock(storeId)
|
|
1277
|
+
)
|
|
1278
|
+
const missing: Array<number> = []
|
|
1279
|
+
let offset = 0
|
|
1280
|
+
for (const header of headers) {
|
|
1281
|
+
for (let i = 0; i < header.entryIds.length; i++) {
|
|
1282
|
+
if (known[offset + i] === undefined) {
|
|
1283
|
+
missing.push(header.sequence)
|
|
1284
|
+
break
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
offset += header.entryIds.length
|
|
1288
|
+
}
|
|
1289
|
+
const fetched = new Map<number, Entry>()
|
|
1290
|
+
if (missing.length > 0) {
|
|
1291
|
+
yield* Stream.runForEach(compaction.fetch(stage, missing), (remoteEntry) =>
|
|
1292
|
+
Effect.sync(() => {
|
|
1293
|
+
fetched.set(remoteEntry.remoteSequence, remoteEntry.entry)
|
|
1294
|
+
}))
|
|
1295
|
+
}
|
|
1296
|
+
const entries: Array<Entry> = []
|
|
1297
|
+
offset = 0
|
|
1298
|
+
for (const header of headers) {
|
|
1299
|
+
for (let i = 0; i < header.entryIds.length; i++) {
|
|
1300
|
+
const entry = known[offset + i] ?? fetched.get(header.sequence + i)
|
|
1301
|
+
if (entry === undefined) {
|
|
1302
|
+
return yield* Effect.die(new Error(`Compaction input sequence ${header.sequence + i} was not fetched`))
|
|
1303
|
+
}
|
|
1304
|
+
if (seen.has(entry.idString)) continue
|
|
1305
|
+
seen.add(entry.idString)
|
|
1306
|
+
entries.push(entry)
|
|
1307
|
+
}
|
|
1308
|
+
offset += header.entryIds.length
|
|
1309
|
+
}
|
|
1310
|
+
return entries
|
|
1311
|
+
})
|
|
1312
|
+
|
|
1313
|
+
const runStage = Effect.fnUntraced(function*(compaction: EventLogRemoteCompaction, stage: CompactionStage) {
|
|
1314
|
+
const seen = new Set<string>()
|
|
1315
|
+
const kept = yield* RemoteCompaction.run({
|
|
1316
|
+
compactors: registry.compactors,
|
|
1317
|
+
entries: compaction.input(stage).pipe(
|
|
1318
|
+
Stream.grouped(compactionLookupBatches),
|
|
1319
|
+
Stream.mapEffect((headers) => resolveInput(compaction, stage, headers, seen)),
|
|
1320
|
+
Stream.flattenIterable
|
|
1321
|
+
),
|
|
1322
|
+
chunkSize: maxBatchEntries
|
|
1323
|
+
})
|
|
1324
|
+
if (kept.length === seen.size) {
|
|
1325
|
+
const result = yield* compaction.commit(stage, { _tag: "NoOp" })
|
|
1326
|
+
return result === "Committed" ? "NoOp" : result
|
|
1327
|
+
}
|
|
1328
|
+
if (kept.length === 0) {
|
|
1329
|
+
yield* Effect.logWarning("Remote compaction dropped every entry, so nothing is uploaded")
|
|
1330
|
+
yield* compaction.abort(stage)
|
|
1331
|
+
return "Aborted"
|
|
1332
|
+
}
|
|
1333
|
+
const { segmentCount } = yield* compaction.upload(stage, kept)
|
|
1334
|
+
const result = yield* compaction.commit(stage, { _tag: "Snapshot", segmentCount })
|
|
1335
|
+
yield* Effect.logDebug(`Remote compaction kept ${kept.length} of ${seen.size} entries: ${result}`)
|
|
1336
|
+
return result
|
|
1337
|
+
})
|
|
1338
|
+
|
|
1339
|
+
// Shared by the background trigger and `compact`. The server's busy claim
|
|
1340
|
+
// keeps runs on a store apart, so the journal lock is held only for id
|
|
1341
|
+
// lookups.
|
|
1342
|
+
const runCompaction = (
|
|
1343
|
+
remote: EventLogRemote["Service"],
|
|
1344
|
+
compaction: EventLogRemoteCompaction
|
|
1345
|
+
): Effect.Effect<CompactionResult, EventJournalError | EventLogRemoteError> =>
|
|
1346
|
+
Effect.gen(function*() {
|
|
1347
|
+
const begin = yield* compaction.begin({ identity, storeId })
|
|
1348
|
+
if (begin._tag !== "Started") return begin._tag
|
|
1349
|
+
const stage: CompactionStage = { identity, storeId, stageId: begin.stageId }
|
|
1350
|
+
return yield* runStage(compaction, stage).pipe(
|
|
1351
|
+
Effect.onError(() => compaction.abort(stage)),
|
|
1352
|
+
Effect.catchTag("IdempotenceError", (error) =>
|
|
1353
|
+
Effect.as(
|
|
1354
|
+
Effect.logError(
|
|
1355
|
+
`A remote compactor dropped ${error.entries.length} more entries from its own output, so nothing is uploaded`
|
|
1356
|
+
),
|
|
1357
|
+
"Aborted" as const
|
|
1358
|
+
)),
|
|
1359
|
+
Effect.catchIf(
|
|
1360
|
+
(error): error is EventLogRemoteError => error._tag === "EventLogRemoteError" && isNotFound(error),
|
|
1361
|
+
(error) =>
|
|
1362
|
+
Effect.as(
|
|
1363
|
+
Effect.logWarning("The compaction input was pruned during the run", error),
|
|
1364
|
+
"Aborted" as const
|
|
1365
|
+
)
|
|
1366
|
+
),
|
|
1367
|
+
Effect.catchDefect((defect) =>
|
|
1368
|
+
Effect.as(Effect.logError("Remote compaction died, so nothing is uploaded", defect), "Aborted" as const)
|
|
1369
|
+
)
|
|
1370
|
+
)
|
|
1371
|
+
}).pipe(
|
|
1372
|
+
Effect.annotateLogs({
|
|
1373
|
+
service: "EventLog",
|
|
1374
|
+
effect: "compact",
|
|
1375
|
+
remoteId: Uuid.stringify(remote.id)
|
|
1376
|
+
})
|
|
1377
|
+
)
|
|
1378
|
+
|
|
1100
1379
|
const runRemote = Effect.fnUntraced(
|
|
1101
1380
|
function*(remote: EventLogRemote["Service"]) {
|
|
1102
|
-
|
|
1103
|
-
|
|
1381
|
+
const compaction = remote.compaction
|
|
1382
|
+
const trigger = yield* FiberHandle.make()
|
|
1383
|
+
|
|
1384
|
+
// Caught up means the journal holds the remote up to the status head.
|
|
1385
|
+
const pollStatus = Effect.fnUntraced(
|
|
1386
|
+
function*(compaction: EventLogRemoteCompaction) {
|
|
1387
|
+
if (!hasRemoteCompactor()) return
|
|
1388
|
+
const status = yield* compaction.status({ identity, storeId })
|
|
1389
|
+
if (!status.wanted || (yield* journal.nextRemoteSequence(remote.id)) <= status.head) return
|
|
1390
|
+
yield* FiberHandle.run(
|
|
1391
|
+
trigger,
|
|
1392
|
+
Random.nextIntBetween(compactionDelayMillis.min, compactionDelayMillis.max).pipe(
|
|
1393
|
+
Effect.flatMap((millis) => Effect.sleep(millis)),
|
|
1394
|
+
Effect.andThen(runCompaction(remote, compaction)),
|
|
1395
|
+
Effect.flatMap((result) => Effect.logDebug(`Remote compaction finished: ${result}`)),
|
|
1396
|
+
Effect.catchCause(Effect.logWarning)
|
|
1397
|
+
),
|
|
1398
|
+
{ onlyIfMissing: true }
|
|
1399
|
+
)
|
|
1400
|
+
},
|
|
1401
|
+
Effect.catchCause(Effect.logWarning),
|
|
1402
|
+
Effect.annotateLogs({
|
|
1403
|
+
service: "EventLog",
|
|
1404
|
+
effect: "runRemote compaction status"
|
|
1405
|
+
})
|
|
1406
|
+
)
|
|
1407
|
+
|
|
1408
|
+
const consume: Effect.Effect<unknown> = Effect.gen(function*() {
|
|
1409
|
+
if (compaction !== undefined) yield* pollStatus(compaction)
|
|
1104
1410
|
const changes = yield* remote.changes({
|
|
1105
1411
|
identity,
|
|
1106
|
-
startSequence,
|
|
1412
|
+
startSequence: yield* journal.nextRemoteSequence(remote.id),
|
|
1107
1413
|
storeId,
|
|
1108
1414
|
knownEntries: journal.entriesById
|
|
1109
1415
|
})
|
|
@@ -1178,9 +1484,16 @@ const make = Effect.gen(function*() {
|
|
|
1178
1484
|
Effect.annotateLogs({
|
|
1179
1485
|
service: "EventLog",
|
|
1180
1486
|
effect: "runRemote consume"
|
|
1181
|
-
})
|
|
1182
|
-
Effect.forkScoped
|
|
1487
|
+
})
|
|
1183
1488
|
)
|
|
1489
|
+
yield* Effect.forkScoped(consume)
|
|
1490
|
+
|
|
1491
|
+
if (compaction !== undefined) {
|
|
1492
|
+
yield* pollStatus(compaction).pipe(
|
|
1493
|
+
Effect.schedule(Schedule.jittered(Schedule.spaced(compactionPollMillis))),
|
|
1494
|
+
Effect.forkScoped
|
|
1495
|
+
)
|
|
1496
|
+
}
|
|
1184
1497
|
|
|
1185
1498
|
const write = journal.withRemoteUncommited(
|
|
1186
1499
|
remote.id,
|
|
@@ -1263,7 +1576,19 @@ const make = Effect.gen(function*() {
|
|
|
1263
1576
|
writeMany: ((options: { readonly events: Arr.NonEmptyReadonlyArray<any> }) =>
|
|
1264
1577
|
writeEvents(options.events)) as EventLog["Service"]["writeMany"],
|
|
1265
1578
|
entries: journal.entries,
|
|
1266
|
-
destroy: journal.destroy
|
|
1579
|
+
destroy: journal.destroy,
|
|
1580
|
+
compact: (options) =>
|
|
1581
|
+
Effect.suspend(() => {
|
|
1582
|
+
if (!hasRemoteCompactor()) {
|
|
1583
|
+
return Effect.succeed([])
|
|
1584
|
+
}
|
|
1585
|
+
const remoteId = options?.remoteId
|
|
1586
|
+
const remotes = Array.from(registry.remotes.values()).filter((remote) =>
|
|
1587
|
+
remote.compaction !== undefined && (remoteId === undefined || Equal.equals(remote.id, remoteId))
|
|
1588
|
+
)
|
|
1589
|
+
return Effect.forEach(remotes, (remote) =>
|
|
1590
|
+
Effect.map(runCompaction(remote, remote.compaction!), (result) => ({ remoteId: remote.id, result })))
|
|
1591
|
+
})
|
|
1267
1592
|
})
|
|
1268
1593
|
})
|
|
1269
1594
|
|