@effect-app/infra 4.0.0-beta.99 → 4.0.1
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/CHANGELOG.md +2901 -0
- package/_check.sh +1 -1
- package/dist/CUPS.d.ts +28 -9
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +35 -14
- package/dist/ClusterCosmos.d.ts +67 -0
- package/dist/ClusterCosmos.d.ts.map +1 -0
- package/dist/ClusterCosmos.js +588 -0
- package/dist/ClusterServiceBus.d.ts +67 -0
- package/dist/ClusterServiceBus.d.ts.map +1 -0
- package/dist/ClusterServiceBus.js +84 -0
- package/dist/{api/ContextProvider.d.ts → ContextProvider.d.ts} +7 -4
- package/dist/ContextProvider.d.ts.map +1 -0
- package/dist/ContextProvider.js +40 -0
- package/dist/Emailer/Sendgrid.d.ts +110 -146
- package/dist/Emailer/Sendgrid.d.ts.map +1 -1
- package/dist/Emailer/Sendgrid.js +24 -19
- package/dist/Emailer/fake.d.ts +1 -1
- package/dist/Emailer/fake.d.ts.map +1 -1
- package/dist/Emailer/fake.js +4 -4
- package/dist/MainFiberSet.d.ts +11 -7
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +22 -6
- package/dist/QueueMaker/errors.d.ts +3 -1
- package/dist/QueueMaker/errors.d.ts.map +1 -1
- package/dist/QueueMaker/errors.js +4 -2
- package/dist/{adapters/SQL → SQL}/Model.d.ts +34 -45
- package/dist/SQL/Model.d.ts.map +1 -0
- package/dist/SQL/Model.js +469 -0
- package/dist/SQL.d.ts.map +1 -0
- package/dist/{adapters/SQL.js → SQL.js} +1 -1
- package/dist/Store/Cosmos/query.d.ts +16 -4
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +240 -44
- package/dist/Store/Cosmos.d.ts +2 -2
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +394 -320
- package/dist/Store/Disk.d.ts +4 -4
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +91 -39
- package/dist/Store/Memory.d.ts +7 -10
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +347 -78
- package/dist/Store/SQL/Pg.d.ts +2 -2
- package/dist/Store/SQL/Pg.d.ts.map +1 -1
- package/dist/Store/SQL/Pg.js +230 -155
- package/dist/Store/SQL/query.d.ts +19 -3
- package/dist/Store/SQL/query.d.ts.map +1 -1
- package/dist/Store/SQL/query.js +308 -14
- package/dist/Store/SQL.d.ts +22 -5
- package/dist/Store/SQL.d.ts.map +1 -1
- package/dist/Store/SQL.js +370 -99
- package/dist/Store/codeFilter.d.ts +5 -5
- package/dist/Store/codeFilter.d.ts.map +1 -1
- package/dist/Store/codeFilter.js +72 -23
- package/dist/Store/index.d.ts +6 -4
- package/dist/Store/index.d.ts.map +1 -1
- package/dist/Store/index.js +9 -6
- package/dist/Store/jsonDocument.d.ts +67 -0
- package/dist/Store/jsonDocument.d.ts.map +1 -0
- package/dist/Store/jsonDocument.js +107 -0
- package/dist/Store/utils.d.ts +21 -2
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +253 -10
- package/dist/WorkflowEngineCosmos.d.ts +30 -0
- package/dist/WorkflowEngineCosmos.d.ts.map +1 -0
- package/dist/WorkflowEngineCosmos.js +542 -0
- package/dist/WorkflowEngineSqlite.d.ts +24 -0
- package/dist/WorkflowEngineSqlite.d.ts.map +1 -0
- package/dist/WorkflowEngineSqlite.js +550 -0
- package/dist/arbs.d.ts +6 -3
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +20 -4
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +5 -0
- package/dist/cosmos-client.d.ts +40 -0
- package/dist/cosmos-client.d.ts.map +1 -0
- package/dist/cosmos-client.js +41 -0
- package/dist/errorReporter.d.ts +6 -4
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +23 -27
- package/dist/fileUtil.d.ts +1 -1
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/fileUtil.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/internal/RequestContextMiddleware.d.ts +5 -0
- package/dist/internal/RequestContextMiddleware.d.ts.map +1 -0
- package/dist/internal/RequestContextMiddleware.js +45 -0
- package/dist/internal/auth.d.ts +53 -0
- package/dist/internal/auth.d.ts.map +1 -0
- package/dist/internal/auth.js +180 -0
- package/dist/internal/events.d.ts +11 -0
- package/dist/internal/events.d.ts.map +1 -0
- package/dist/internal/events.js +49 -0
- package/dist/{api/internal → internal}/health.d.ts +1 -1
- package/dist/internal/health.d.ts.map +1 -0
- package/dist/internal/health.js +5 -0
- package/dist/{api/layerUtils.d.ts → layerUtils.d.ts} +10 -2
- package/dist/layerUtils.d.ts.map +1 -0
- package/dist/layerUtils.js +17 -0
- package/dist/logger/jsonLogger.d.ts +1 -1
- package/dist/logger/jsonLogger.d.ts.map +1 -1
- package/dist/logger/jsonLogger.js +5 -3
- package/dist/logger/logFmtLogger.d.ts +1 -1
- package/dist/logger/logFmtLogger.d.ts.map +1 -1
- package/dist/logger/logFmtLogger.js +3 -3
- package/dist/logger/shared.d.ts +2 -2
- package/dist/logger/shared.d.ts.map +1 -1
- package/dist/logger/shared.js +6 -6
- package/dist/logger.d.ts.map +1 -1
- package/dist/middlewares.d.ts.map +1 -0
- package/dist/{api/middlewares.js → middlewares.js} +1 -1
- package/dist/{adapters/mongo-client.d.ts → mongo-client.d.ts} +2 -1
- package/dist/mongo-client.d.ts.map +1 -0
- package/dist/mongo-client.js +15 -0
- package/dist/otel.d.ts +75 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +84 -0
- package/dist/rateLimit.d.ts +11 -3
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +7 -12
- package/dist/{adapters/redis-client.d.ts → redis-client.d.ts} +4 -1
- package/dist/redis-client.d.ts.map +1 -0
- package/dist/redis-client.js +98 -0
- package/dist/{api/reportError.d.ts → reportError.d.ts} +1 -1
- package/dist/reportError.d.ts.map +1 -0
- package/dist/reportError.js +28 -0
- package/dist/{api/routing → routing}/middleware/RouterMiddleware.d.ts +2 -1
- package/dist/routing/middleware/RouterMiddleware.d.ts.map +1 -0
- package/dist/{api/routing → routing}/middleware/RouterMiddleware.js +1 -1
- package/dist/{api/routing → routing}/middleware/middleware.d.ts +11 -6
- package/dist/routing/middleware/middleware.d.ts.map +1 -0
- package/dist/routing/middleware/middleware.js +152 -0
- package/dist/{api/routing → routing}/middleware.d.ts +0 -1
- package/dist/routing/middleware.d.ts.map +1 -0
- package/dist/{api/routing → routing}/middleware.js +1 -2
- package/dist/routing/schema/jwt.d.ts.map +1 -0
- package/dist/routing/schema/jwt.js +12 -0
- package/dist/routing/tsort.d.ts.map +1 -0
- package/dist/routing/tsort.js +51 -0
- package/dist/{api/routing → routing}/utils.d.ts +3 -3
- package/dist/routing/utils.d.ts.map +1 -0
- package/dist/routing/utils.js +45 -0
- package/dist/routing.d.ts +182 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +257 -0
- package/dist/test.d.ts +2 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +5 -5
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +14 -0
- package/docs/cluster-storage.md +26 -0
- package/docs/workflow-engine.md +262 -0
- package/examples/query.ts +23 -19
- package/package.json +36 -364
- package/src/CUPS.ts +53 -14
- package/src/ClusterCosmos.ts +1170 -0
- package/src/ClusterServiceBus.ts +244 -0
- package/src/{api/ContextProvider.ts → ContextProvider.ts} +10 -7
- package/src/Emailer/Sendgrid.ts +83 -60
- package/src/Emailer/fake.ts +4 -4
- package/src/MainFiberSet.ts +31 -12
- package/src/QueueMaker/errors.ts +3 -1
- package/src/{adapters/SQL → SQL}/Model.ts +48 -47
- package/src/SQL.ts +1 -0
- package/src/Store/Cosmos/query.ts +277 -57
- package/src/Store/Cosmos.ts +597 -512
- package/src/Store/Disk.ts +145 -71
- package/src/Store/Memory.ts +419 -115
- package/src/Store/SQL/Pg.ts +352 -269
- package/src/Store/SQL/query.ts +368 -22
- package/src/Store/SQL.ts +742 -294
- package/src/Store/codeFilter.ts +79 -29
- package/src/Store/index.ts +18 -13
- package/src/Store/jsonDocument.ts +143 -0
- package/src/Store/utils.ts +307 -30
- package/src/WorkflowEngineCosmos.ts +749 -0
- package/src/WorkflowEngineSqlite.ts +813 -0
- package/src/arbs.ts +25 -5
- package/src/cosmos-client.ts +72 -0
- package/src/errorReporter.ts +70 -78
- package/src/fileUtil.ts +1 -1
- package/src/index.ts +2 -1
- package/src/{api/internal → internal}/RequestContextMiddleware.ts +23 -6
- package/src/internal/auth.ts +272 -0
- package/src/{api/internal → internal}/events.ts +18 -9
- package/src/{api/layerUtils.ts → layerUtils.ts} +7 -3
- package/src/logger/jsonLogger.ts +5 -3
- package/src/logger/logFmtLogger.ts +3 -3
- package/src/logger/shared.ts +6 -5
- package/src/middlewares.ts +10 -0
- package/src/{adapters/mongo-client.ts → mongo-client.ts} +3 -1
- package/src/otel.ts +177 -0
- package/src/rateLimit.ts +35 -24
- package/src/{adapters/redis-client.ts → redis-client.ts} +6 -2
- package/src/{api/reportError.ts → reportError.ts} +3 -2
- package/src/{api/routing → routing}/middleware/RouterMiddleware.ts +2 -1
- package/src/{api/routing → routing}/middleware/middleware.ts +75 -50
- package/src/routing/middleware.ts +4 -0
- package/src/{api/routing → routing}/schema/jwt.ts +2 -2
- package/src/{api/routing → routing}/utils.ts +2 -1
- package/src/routing.ts +827 -0
- package/src/test.ts +6 -6
- package/src/vitest.ts +1 -1
- package/test/arbs-magnitude.test.ts +33 -0
- package/test/arbs.test.ts +41 -0
- package/test/auth.test.ts +101 -0
- package/test/cluster-cosmos.test.ts +634 -0
- package/test/cluster-servicebus.test.ts +180 -0
- package/test/cluster-sqlite.test.ts +207 -0
- package/test/contextProvider.test.ts +11 -8
- package/test/controller.test.ts +23 -28
- package/test/cosmos-container-throughput.test.ts +80 -0
- package/test/cosmos-query.test.ts +368 -0
- package/test/dist/arbs-magnitude.test.d.ts.map +1 -0
- package/test/dist/arbs.test.d.ts.map +1 -0
- package/test/dist/auth.test.d.ts.map +1 -0
- package/test/dist/cluster-cosmos.test.d.ts.map +1 -0
- package/test/dist/cluster-servicebus.test.d.ts.map +1 -0
- package/test/dist/cluster-sqlite.test.d.ts.map +1 -0
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/cosmos-container-throughput.test.d.ts.map +1 -0
- package/test/dist/cosmos-query.test.d.ts.map +1 -0
- package/test/dist/fixtures.d.ts +17 -9
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +8 -3
- package/test/dist/json-lower.test.d.ts.map +1 -0
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/rawQuery.test.d.ts.map +1 -1
- package/test/dist/repository-ext.test.d.ts.map +1 -0
- package/test/dist/repository-legacy-document.test.d.ts.map +1 -0
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/router-generator.test.d.ts.map +1 -0
- package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
- package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
- package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
- package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
- package/test/dist/workflow-engine-cosmos.test.d.ts.map +1 -0
- package/test/dist/workflow-engine-sqlite.test.d.ts.map +1 -0
- package/test/fixtures.ts +7 -2
- package/test/json-lower.test.ts +129 -0
- package/test/layerUtils.test.ts +2 -2
- package/test/query.test.ts +1232 -42
- package/test/rawQuery.test.ts +432 -7
- package/test/repository-ext.test.ts +456 -0
- package/test/repository-legacy-document.test.ts +394 -0
- package/test/requires.test.ts +7 -3
- package/test/router-generator.test.ts +187 -0
- package/test/routing-interruptibility.test.ts +66 -0
- package/test/rpc-context-map-streaming.test.ts +265 -0
- package/test/rpc-e2e-invalidation.test.ts +421 -0
- package/test/rpc-multi-middleware.test.ts +17 -11
- package/test/rpc-stream-fullstack.test.ts +307 -0
- package/test/sql-store.test.ts +1202 -47
- package/test/validateSample.test.ts +70 -42
- package/test/workflow-engine-cosmos.test.ts +345 -0
- package/test/workflow-engine-sqlite.test.ts +297 -0
- package/tsconfig.examples.json +1 -1
- package/tsconfig.json +9 -1
- package/tsconfig.src.json +35 -35
- package/tsconfig.test.json +2 -2
- package/dist/Emailer/service.d.ts +0 -55
- package/dist/Emailer/service.d.ts.map +0 -1
- package/dist/Emailer/service.js +0 -6
- package/dist/Emailer.d.ts +0 -2
- package/dist/Emailer.d.ts.map +0 -1
- package/dist/Emailer.js +0 -2
- package/dist/Model/Repository/ext.d.ts +0 -41
- package/dist/Model/Repository/ext.d.ts.map +0 -1
- package/dist/Model/Repository/ext.js +0 -65
- package/dist/Model/Repository/internal/internal.d.ts +0 -59
- package/dist/Model/Repository/internal/internal.d.ts.map +0 -1
- package/dist/Model/Repository/internal/internal.js +0 -320
- package/dist/Model/Repository/legacy.d.ts +0 -19
- package/dist/Model/Repository/legacy.d.ts.map +0 -1
- package/dist/Model/Repository/legacy.js +0 -2
- package/dist/Model/Repository/makeRepo.d.ts +0 -49
- package/dist/Model/Repository/makeRepo.d.ts.map +0 -1
- package/dist/Model/Repository/makeRepo.js +0 -24
- package/dist/Model/Repository/service.d.ts +0 -89
- package/dist/Model/Repository/service.d.ts.map +0 -1
- package/dist/Model/Repository/service.js +0 -2
- package/dist/Model/Repository/validation.d.ts +0 -43
- package/dist/Model/Repository/validation.d.ts.map +0 -1
- package/dist/Model/Repository/validation.js +0 -32
- package/dist/Model/Repository.d.ts +0 -6
- package/dist/Model/Repository.d.ts.map +0 -1
- package/dist/Model/Repository.js +0 -6
- package/dist/Model/dsl.d.ts +0 -32
- package/dist/Model/dsl.d.ts.map +0 -1
- package/dist/Model/dsl.js +0 -44
- package/dist/Model/filter/filterApi.d.ts +0 -30
- package/dist/Model/filter/filterApi.d.ts.map +0 -1
- package/dist/Model/filter/filterApi.js +0 -2
- package/dist/Model/filter/types/errors.d.ts +0 -29
- package/dist/Model/filter/types/errors.d.ts.map +0 -1
- package/dist/Model/filter/types/errors.js +0 -2
- package/dist/Model/filter/types/fields.d.ts +0 -15
- package/dist/Model/filter/types/fields.d.ts.map +0 -1
- package/dist/Model/filter/types/fields.js +0 -2
- package/dist/Model/filter/types/path/common.d.ts +0 -316
- package/dist/Model/filter/types/path/common.d.ts.map +0 -1
- package/dist/Model/filter/types/path/common.js +0 -2
- package/dist/Model/filter/types/path/eager.d.ts +0 -95
- package/dist/Model/filter/types/path/eager.d.ts.map +0 -1
- package/dist/Model/filter/types/path/eager.js +0 -31
- package/dist/Model/filter/types/path/index.d.ts +0 -4
- package/dist/Model/filter/types/path/index.d.ts.map +0 -1
- package/dist/Model/filter/types/path/index.js +0 -3
- package/dist/Model/filter/types/utils.d.ts +0 -79
- package/dist/Model/filter/types/utils.d.ts.map +0 -1
- package/dist/Model/filter/types/utils.js +0 -2
- package/dist/Model/filter/types/validator.d.ts +0 -30
- package/dist/Model/filter/types/validator.d.ts.map +0 -1
- package/dist/Model/filter/types/validator.js +0 -2
- package/dist/Model/filter/types.d.ts +0 -5
- package/dist/Model/filter/types.d.ts.map +0 -1
- package/dist/Model/filter/types.js +0 -7
- package/dist/Model/query/dsl.d.ts +0 -248
- package/dist/Model/query/dsl.d.ts.map +0 -1
- package/dist/Model/query/dsl.js +0 -104
- package/dist/Model/query/new-kid-interpreter.d.ts +0 -28
- package/dist/Model/query/new-kid-interpreter.d.ts.map +0 -1
- package/dist/Model/query/new-kid-interpreter.js +0 -165
- package/dist/Model/query.d.ts +0 -15
- package/dist/Model/query.d.ts.map +0 -1
- package/dist/Model/query.js +0 -3
- package/dist/Model.d.ts +0 -4
- package/dist/Model.d.ts.map +0 -1
- package/dist/Model.js +0 -4
- package/dist/Operations.d.ts +0 -55
- package/dist/Operations.d.ts.map +0 -1
- package/dist/Operations.js +0 -102
- package/dist/OperationsRepo.d.ts +0 -41
- package/dist/OperationsRepo.d.ts.map +0 -1
- package/dist/OperationsRepo.js +0 -14
- package/dist/QueueMaker/SQLQueue.d.ts +0 -14
- package/dist/QueueMaker/SQLQueue.d.ts.map +0 -1
- package/dist/QueueMaker/SQLQueue.js +0 -132
- package/dist/QueueMaker/memQueue.d.ts +0 -11
- package/dist/QueueMaker/memQueue.d.ts.map +0 -1
- package/dist/QueueMaker/memQueue.js +0 -76
- package/dist/QueueMaker/sbqueue.d.ts +0 -12
- package/dist/QueueMaker/sbqueue.d.ts.map +0 -1
- package/dist/QueueMaker/sbqueue.js +0 -91
- package/dist/QueueMaker/service.d.ts +0 -11
- package/dist/QueueMaker/service.d.ts.map +0 -1
- package/dist/QueueMaker/service.js +0 -4
- package/dist/RequestContext.d.ts +0 -68
- package/dist/RequestContext.d.ts.map +0 -1
- package/dist/RequestContext.js +0 -49
- package/dist/RequestFiberSet.d.ts +0 -36
- package/dist/RequestFiberSet.d.ts.map +0 -1
- package/dist/RequestFiberSet.js +0 -78
- package/dist/Store/ContextMapContainer.d.ts +0 -25
- package/dist/Store/ContextMapContainer.d.ts.map +0 -1
- package/dist/Store/ContextMapContainer.js +0 -77
- package/dist/Store/service.d.ts +0 -111
- package/dist/Store/service.d.ts.map +0 -1
- package/dist/Store/service.js +0 -79
- package/dist/Store.d.ts +0 -2
- package/dist/Store.d.ts.map +0 -1
- package/dist/Store.js +0 -2
- package/dist/adapters/SQL/Model.d.ts.map +0 -1
- package/dist/adapters/SQL/Model.js +0 -478
- package/dist/adapters/SQL.d.ts.map +0 -1
- package/dist/adapters/ServiceBus.d.ts +0 -58
- package/dist/adapters/ServiceBus.d.ts.map +0 -1
- package/dist/adapters/ServiceBus.js +0 -99
- package/dist/adapters/cosmos-client.d.ts +0 -14
- package/dist/adapters/cosmos-client.d.ts.map +0 -1
- package/dist/adapters/cosmos-client.js +0 -9
- package/dist/adapters/index.d.ts +0 -2
- package/dist/adapters/index.d.ts.map +0 -1
- package/dist/adapters/index.js +0 -2
- package/dist/adapters/logger.d.ts +0 -9
- package/dist/adapters/logger.d.ts.map +0 -1
- package/dist/adapters/logger.js +0 -3
- package/dist/adapters/memQueue.d.ts +0 -13
- package/dist/adapters/memQueue.d.ts.map +0 -1
- package/dist/adapters/memQueue.js +0 -20
- package/dist/adapters/mongo-client.d.ts.map +0 -1
- package/dist/adapters/mongo-client.js +0 -13
- package/dist/adapters/redis-client.d.ts.map +0 -1
- package/dist/adapters/redis-client.js +0 -94
- package/dist/api/ContextProvider.d.ts.map +0 -1
- package/dist/api/ContextProvider.js +0 -38
- package/dist/api/codec.d.ts.map +0 -1
- package/dist/api/codec.js +0 -5
- package/dist/api/internal/RequestContextMiddleware.d.ts +0 -5
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +0 -1
- package/dist/api/internal/RequestContextMiddleware.js +0 -35
- package/dist/api/internal/auth.d.ts +0 -15
- package/dist/api/internal/auth.d.ts.map +0 -1
- package/dist/api/internal/auth.js +0 -47
- package/dist/api/internal/events.d.ts +0 -9
- package/dist/api/internal/events.d.ts.map +0 -1
- package/dist/api/internal/events.js +0 -42
- package/dist/api/internal/health.d.ts.map +0 -1
- package/dist/api/internal/health.js +0 -5
- package/dist/api/layerUtils.d.ts.map +0 -1
- package/dist/api/layerUtils.js +0 -16
- package/dist/api/middlewares.d.ts.map +0 -1
- package/dist/api/reportError.d.ts.map +0 -1
- package/dist/api/reportError.js +0 -27
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +0 -1
- package/dist/api/routing/middleware/middleware.d.ts.map +0 -1
- package/dist/api/routing/middleware/middleware.js +0 -130
- package/dist/api/routing/middleware.d.ts.map +0 -1
- package/dist/api/routing/schema/jwt.d.ts.map +0 -1
- package/dist/api/routing/schema/jwt.js +0 -12
- package/dist/api/routing/tsort.d.ts.map +0 -1
- package/dist/api/routing/tsort.js +0 -51
- package/dist/api/routing/utils.d.ts.map +0 -1
- package/dist/api/routing/utils.js +0 -44
- package/dist/api/routing.d.ts +0 -134
- package/dist/api/routing.d.ts.map +0 -1
- package/dist/api/routing.js +0 -167
- package/dist/api/setupRequest.d.ts +0 -15
- package/dist/api/setupRequest.d.ts.map +0 -1
- package/dist/api/setupRequest.js +0 -49
- package/dist/api/util.d.ts.map +0 -1
- package/dist/api/util.js +0 -14
- package/eslint.config.mjs +0 -24
- package/src/Emailer/service.ts +0 -52
- package/src/Emailer.ts +0 -1
- package/src/Model/Repository/ext.ts +0 -283
- package/src/Model/Repository/internal/internal.ts +0 -580
- package/src/Model/Repository/legacy.ts +0 -27
- package/src/Model/Repository/makeRepo.ts +0 -139
- package/src/Model/Repository/service.ts +0 -627
- package/src/Model/Repository/validation.ts +0 -31
- package/src/Model/Repository.ts +0 -5
- package/src/Model/dsl.ts +0 -128
- package/src/Model/filter/filterApi.ts +0 -60
- package/src/Model/filter/types/errors.ts +0 -47
- package/src/Model/filter/types/fields.ts +0 -50
- package/src/Model/filter/types/path/common.ts +0 -404
- package/src/Model/filter/types/path/eager.ts +0 -298
- package/src/Model/filter/types/path/index.ts +0 -4
- package/src/Model/filter/types/utils.ts +0 -128
- package/src/Model/filter/types/validator.ts +0 -46
- package/src/Model/filter/types.ts +0 -6
- package/src/Model/query/dsl.ts +0 -2110
- package/src/Model/query/new-kid-interpreter.ts +0 -210
- package/src/Model/query.ts +0 -13
- package/src/Model.ts +0 -3
- package/src/Operations.ts +0 -235
- package/src/OperationsRepo.ts +0 -16
- package/src/QueueMaker/SQLQueue.ts +0 -190
- package/src/QueueMaker/memQueue.ts +0 -130
- package/src/QueueMaker/sbqueue.ts +0 -137
- package/src/QueueMaker/service.ts +0 -17
- package/src/RequestContext.ts +0 -63
- package/src/RequestFiberSet.ts +0 -105
- package/src/Store/ContextMapContainer.ts +0 -116
- package/src/Store/index.test.ts.bak +0 -112
- package/src/Store/service.ts +0 -193
- package/src/Store.ts +0 -1
- package/src/adapters/SQL.ts +0 -1
- package/src/adapters/ServiceBus.ts +0 -209
- package/src/adapters/cosmos-client.ts +0 -16
- package/src/adapters/index.ts +0 -0
- package/src/adapters/logger.ts +0 -3
- package/src/adapters/memQueue.ts +0 -21
- package/src/api/internal/auth.ts +0 -68
- package/src/api/middlewares.ts +0 -10
- package/src/api/routing/middleware.ts +0 -6
- package/src/api/routing.ts +0 -598
- package/src/api/setupRequest.ts +0 -104
- package/test/dist/date-query.test.d.ts.map +0 -1
- package/tsconfig.json.bak +0 -12
- /package/dist/{adapters/SQL.d.ts → SQL.d.ts} +0 -0
- /package/dist/{api/codec.d.ts → codec.d.ts} +0 -0
- /package/dist/{api/middlewares.d.ts → middlewares.d.ts} +0 -0
- /package/dist/{api/routing → routing}/schema/jwt.d.ts +0 -0
- /package/dist/{api/routing → routing}/tsort.d.ts +0 -0
- /package/dist/{api/util.d.ts → util.d.ts} +0 -0
- /package/src/{api/codec.ts → codec.ts} +0 -0
- /package/src/{api/internal → internal}/health.ts +0 -0
- /package/src/{api/routing → routing}/tsort.ts +0 -0
- /package/src/{api/util.ts → util.ts} +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type { ServiceBusMessage, ServiceBusReceiverOptions } from "@azure/service-bus"
|
|
2
|
+
import { assert, describe, it } from "@effect/vitest"
|
|
3
|
+
import { Context, Effect, Layer, Option, Schema, Stream } from "effect"
|
|
4
|
+
import { ClusterSchema, EntityAddress, EntityId, EntityType, Envelope, Message, MessageStorage, Runners, ShardId, Sharding, ShardingConfig, Snowflake } from "effect/cluster"
|
|
5
|
+
import { Headers } from "effect/http"
|
|
6
|
+
import { Rpc } from "effect/rpc"
|
|
7
|
+
import { type ClusterServiceBusClient, layerClientFrom, layerRunners, makeStoragePoller } from "../src/ClusterServiceBus.js"
|
|
8
|
+
|
|
9
|
+
describe("ClusterServiceBus", () => {
|
|
10
|
+
it.effect("wakes storage polling from topic notifications", () =>
|
|
11
|
+
Effect.gen(function*() {
|
|
12
|
+
let processMessage: (() => Promise<void>) | undefined
|
|
13
|
+
let polls = 0
|
|
14
|
+
let receiverClosed = false
|
|
15
|
+
let subscriptionClosed = false
|
|
16
|
+
|
|
17
|
+
const client: ClusterServiceBusClient = {
|
|
18
|
+
createSender() {
|
|
19
|
+
throw new Error("unused")
|
|
20
|
+
},
|
|
21
|
+
createReceiver(topicName: string, subscriptionName: string, options?: ServiceBusReceiverOptions) {
|
|
22
|
+
assert.strictEqual(topicName, "cluster-notifications")
|
|
23
|
+
assert.strictEqual(subscriptionName, "runner-a")
|
|
24
|
+
assert.strictEqual(options?.receiveMode, "receiveAndDelete")
|
|
25
|
+
return {
|
|
26
|
+
subscribe(handlers) {
|
|
27
|
+
processMessage = handlers.processMessage
|
|
28
|
+
return {
|
|
29
|
+
close() {
|
|
30
|
+
subscriptionClosed = true
|
|
31
|
+
return Promise.resolve()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
close() {
|
|
36
|
+
receiverClosed = true
|
|
37
|
+
return Promise.resolve()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
close() {
|
|
42
|
+
return Promise.resolve()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const sharding = Sharding.Sharding.of({
|
|
47
|
+
activeEntityCount: Effect.succeed(0),
|
|
48
|
+
getRegistrationEvents: Stream.empty,
|
|
49
|
+
getShardId: () => ShardId.make("cluster-servicebus", 0),
|
|
50
|
+
getSnowflake: Effect.succeed(Snowflake.Snowflake(1n)),
|
|
51
|
+
hasShardId: () => false,
|
|
52
|
+
isShutdown: Effect.succeed(false),
|
|
53
|
+
makeClient: () => Effect.die("unused"),
|
|
54
|
+
notify: () => Effect.void,
|
|
55
|
+
pollStorage: Effect.sync(() => {
|
|
56
|
+
polls++
|
|
57
|
+
}),
|
|
58
|
+
registerEntity: () => Effect.void,
|
|
59
|
+
registerSingleton: () => Effect.void,
|
|
60
|
+
reset: () => Effect.succeed(false),
|
|
61
|
+
send: () => Effect.void,
|
|
62
|
+
sendOutgoing: () => Effect.void
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
yield* Effect
|
|
66
|
+
.scoped(
|
|
67
|
+
makeStoragePoller({
|
|
68
|
+
topicName: "cluster-notifications",
|
|
69
|
+
subscriptionName: "runner-a"
|
|
70
|
+
})
|
|
71
|
+
.pipe(
|
|
72
|
+
Effect.andThen(
|
|
73
|
+
Effect.gen(function*() {
|
|
74
|
+
if (processMessage === undefined) {
|
|
75
|
+
return yield* Effect.die("missing Service Bus subscription")
|
|
76
|
+
}
|
|
77
|
+
const runProcessMessage = processMessage
|
|
78
|
+
yield* Effect.promise(() => runProcessMessage())
|
|
79
|
+
assert.strictEqual(polls, 1)
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
.pipe(
|
|
85
|
+
Effect.provide(layerClientFrom(client)),
|
|
86
|
+
Effect.provide(Layer.succeed(Sharding.Sharding)(sharding))
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
assert.strictEqual(subscriptionClosed, true)
|
|
90
|
+
assert.strictEqual(receiverClosed, true)
|
|
91
|
+
}))
|
|
92
|
+
|
|
93
|
+
it.effect("publishes persisted storage notifications", () =>
|
|
94
|
+
Effect.gen(function*() {
|
|
95
|
+
const sent: Array<ServiceBusMessage> = []
|
|
96
|
+
let senderClosed = false
|
|
97
|
+
|
|
98
|
+
const client: ClusterServiceBusClient = {
|
|
99
|
+
createSender(topicName) {
|
|
100
|
+
assert.strictEqual(topicName, "cluster-notifications")
|
|
101
|
+
return {
|
|
102
|
+
sendMessages(message) {
|
|
103
|
+
sent.push(message)
|
|
104
|
+
return Promise.resolve()
|
|
105
|
+
},
|
|
106
|
+
close() {
|
|
107
|
+
senderClosed = true
|
|
108
|
+
return Promise.resolve()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
createReceiver() {
|
|
113
|
+
throw new Error("unused")
|
|
114
|
+
},
|
|
115
|
+
close() {
|
|
116
|
+
return Promise.resolve()
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
yield* Effect.scoped(
|
|
121
|
+
Effect
|
|
122
|
+
.gen(function*() {
|
|
123
|
+
const runners = yield* Runners.Runners
|
|
124
|
+
yield* runners.notify({
|
|
125
|
+
address: Option.none(),
|
|
126
|
+
discard: true,
|
|
127
|
+
message: yield* makeOutgoingRequest
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
.pipe(
|
|
131
|
+
Effect.provide(layerRunners({ topicName: "cluster-notifications" })),
|
|
132
|
+
Effect.provide(layerClientFrom(client)),
|
|
133
|
+
Effect.provide(MessageStorage.layerNoop),
|
|
134
|
+
Effect.provide(ShardingConfig.layerDefaults)
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
assert.strictEqual(senderClosed, true)
|
|
139
|
+
assert.strictEqual(sent.length, 1)
|
|
140
|
+
assert.deepStrictEqual(sent[0]?.body, {
|
|
141
|
+
_tag: "EffectClusterStorageNotification",
|
|
142
|
+
envelopeId: "1",
|
|
143
|
+
requestId: "1",
|
|
144
|
+
shardId: "cluster-servicebus:1",
|
|
145
|
+
entityType: "TestEntity",
|
|
146
|
+
entityId: "entity-1"
|
|
147
|
+
})
|
|
148
|
+
assert.strictEqual(sent[0]?.contentType, "application/json")
|
|
149
|
+
assert.strictEqual(sent[0]?.correlationId, "1")
|
|
150
|
+
assert.strictEqual(sent[0]?.messageId, "1")
|
|
151
|
+
assert.strictEqual(sent[0]?.subject, "EffectClusterStorageNotification")
|
|
152
|
+
}))
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const TestRpc = Rpc
|
|
156
|
+
.make("TestRpc", {
|
|
157
|
+
payload: { id: Schema.Number }
|
|
158
|
+
})
|
|
159
|
+
.annotate(ClusterSchema.Persisted, true)
|
|
160
|
+
|
|
161
|
+
const makeOutgoingRequest = Effect.sync(() =>
|
|
162
|
+
new Message.OutgoingRequest({
|
|
163
|
+
annotations: TestRpc.annotations,
|
|
164
|
+
context: Context.empty(),
|
|
165
|
+
envelope: Envelope.makeRequest<typeof TestRpc>({
|
|
166
|
+
address: EntityAddress.make({
|
|
167
|
+
entityId: EntityId.make("entity-1"),
|
|
168
|
+
entityType: EntityType.make("TestEntity"),
|
|
169
|
+
shardId: ShardId.make("cluster-servicebus", 1)
|
|
170
|
+
}),
|
|
171
|
+
headers: Headers.empty,
|
|
172
|
+
payload: { id: 1 },
|
|
173
|
+
requestId: Snowflake.Snowflake(1n),
|
|
174
|
+
tag: TestRpc._tag
|
|
175
|
+
}),
|
|
176
|
+
lastReceivedReply: Option.none(),
|
|
177
|
+
respond: () => Effect.void,
|
|
178
|
+
rpc: TestRpc
|
|
179
|
+
})
|
|
180
|
+
)
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { NodeCrypto } from "@effect/platform-node"
|
|
2
|
+
import { SqliteClient } from "@effect/sql-sqlite-node"
|
|
3
|
+
import { assert, describe, it } from "@effect/vitest"
|
|
4
|
+
import { Context, Duration, Effect, Exit, Fiber, Layer, Option, Schema } from "effect"
|
|
5
|
+
import { ClusterSchema, ClusterWorkflowEngine, RunnerAddress, RunnerHealth, Runners, Sharding, ShardingConfig, SqlMessageStorage, SqlRunnerStorage } from "effect/cluster"
|
|
6
|
+
import { DurableDeferred, Workflow } from "effect/workflow"
|
|
7
|
+
|
|
8
|
+
const testRunId = `${Date.now()}-${process.pid}-${Math.random().toString(16).slice(2)}`
|
|
9
|
+
const runnerPortBase = 10000 + Date.now() % 40000
|
|
10
|
+
|
|
11
|
+
describe("ClusterSqlite Workflow", () => {
|
|
12
|
+
it.live("resumes a running workflow suspended on a durable deferred", () =>
|
|
13
|
+
Effect
|
|
14
|
+
.gen(function*() {
|
|
15
|
+
const sharding = yield* Sharding.Sharding
|
|
16
|
+
const payload = { id: `deferred-${testRunId}` }
|
|
17
|
+
const executionId = yield* SqliteDeferredWorkflow.executionId(payload)
|
|
18
|
+
|
|
19
|
+
const fiber = yield* SqliteDeferredWorkflow.execute(payload).pipe(Effect.forkScoped)
|
|
20
|
+
yield* waitForDeferredWorkflowSuspended(executionId)
|
|
21
|
+
|
|
22
|
+
const token = yield* DurableDeferred.tokenFromPayload(SqliteDeferred, {
|
|
23
|
+
workflow: SqliteDeferredWorkflow,
|
|
24
|
+
payload
|
|
25
|
+
})
|
|
26
|
+
yield* DurableDeferred.done(SqliteDeferred, { token, exit: Exit.succeed("resolved") })
|
|
27
|
+
yield* sharding.pollStorage
|
|
28
|
+
|
|
29
|
+
const value = yield* Fiber.join(fiber).pipe(Effect.timeout(Duration.seconds(15)))
|
|
30
|
+
assert.strictEqual(value, `${payload.id}:resolved`)
|
|
31
|
+
assert.strictEqual(yield* waitForDeferredWorkflowComplete(executionId), `${payload.id}:resolved`)
|
|
32
|
+
})
|
|
33
|
+
.pipe(Effect.provide(clusterWorkflowLayer())), 30000)
|
|
34
|
+
|
|
35
|
+
it.live("progresses through sequential durable deferred steps", () =>
|
|
36
|
+
Effect
|
|
37
|
+
.gen(function*() {
|
|
38
|
+
const log = yield* StepLog
|
|
39
|
+
const sharding = yield* Sharding.Sharding
|
|
40
|
+
const payload = { id: `steps-${testRunId}` }
|
|
41
|
+
const executionId = yield* SequentialDeferredWorkflow.executionId(payload)
|
|
42
|
+
|
|
43
|
+
const fiber = yield* SequentialDeferredWorkflow.execute(payload).pipe(Effect.forkScoped)
|
|
44
|
+
yield* waitForSequentialWorkflowSuspended(executionId)
|
|
45
|
+
|
|
46
|
+
yield* completeStep(SequentialStep1, payload, "one")
|
|
47
|
+
yield* sharding.pollStorage
|
|
48
|
+
yield* waitForStep(log, "step-1")
|
|
49
|
+
|
|
50
|
+
yield* completeStep(SequentialStep2, payload, "two")
|
|
51
|
+
yield* sharding.pollStorage
|
|
52
|
+
yield* waitForStep(log, "step-2")
|
|
53
|
+
|
|
54
|
+
yield* completeStep(SequentialStep3, payload, "three")
|
|
55
|
+
yield* sharding.pollStorage
|
|
56
|
+
|
|
57
|
+
const value = yield* Fiber.join(fiber).pipe(Effect.timeout(Duration.seconds(15)))
|
|
58
|
+
assert.strictEqual(value, "one:two:three")
|
|
59
|
+
assert(log.steps.includes("step-3"))
|
|
60
|
+
})
|
|
61
|
+
.pipe(Effect.provide(clusterWorkflowLayer())), 30000)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
class StepLog extends Context.Service<StepLog, { readonly steps: Array<string> }>()("StepLog") {
|
|
65
|
+
static readonly layer = Layer.effect(StepLog, Effect.sync(() => ({ steps: [] })))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const SqliteDeferred = DurableDeferred.make("ClusterSqlite/Deferred", { success: Schema.String })
|
|
69
|
+
|
|
70
|
+
const SqliteDeferredWorkflow = Workflow
|
|
71
|
+
.make("ClusterSqlite/DeferredWorkflow", {
|
|
72
|
+
payload: { id: Schema.String },
|
|
73
|
+
success: Schema.String,
|
|
74
|
+
idempotencyKey: ({ id }) => id
|
|
75
|
+
})
|
|
76
|
+
.annotate(ClusterSchema.ShardGroup, () => testShardGroup("workflow"))
|
|
77
|
+
|
|
78
|
+
const SqliteDeferredWorkflowLayer = SqliteDeferredWorkflow.toLayer(Effect.fnUntraced(function*({ id }) {
|
|
79
|
+
const value = yield* DurableDeferred.await(SqliteDeferred)
|
|
80
|
+
return `${id}:${value}`
|
|
81
|
+
}))
|
|
82
|
+
|
|
83
|
+
const SequentialStep1 = DurableDeferred.make("ClusterSqlite/SequentialStep1", { success: Schema.String })
|
|
84
|
+
const SequentialStep2 = DurableDeferred.make("ClusterSqlite/SequentialStep2", { success: Schema.String })
|
|
85
|
+
const SequentialStep3 = DurableDeferred.make("ClusterSqlite/SequentialStep3", { success: Schema.String })
|
|
86
|
+
|
|
87
|
+
const SequentialDeferredWorkflow = Workflow
|
|
88
|
+
.make("ClusterSqlite/SequentialDeferredWorkflow", {
|
|
89
|
+
payload: { id: Schema.String },
|
|
90
|
+
success: Schema.String,
|
|
91
|
+
idempotencyKey: ({ id }) => id
|
|
92
|
+
})
|
|
93
|
+
.annotate(ClusterSchema.ShardGroup, () => testShardGroup("workflow"))
|
|
94
|
+
|
|
95
|
+
const SequentialDeferredWorkflowLayer = SequentialDeferredWorkflow.toLayer(Effect.fnUntraced(function*() {
|
|
96
|
+
const log = yield* StepLog
|
|
97
|
+
const step1 = yield* DurableDeferred.await(SequentialStep1)
|
|
98
|
+
log.steps.push("step-1")
|
|
99
|
+
const step2 = yield* DurableDeferred.await(SequentialStep2)
|
|
100
|
+
log.steps.push("step-2")
|
|
101
|
+
const step3 = yield* DurableDeferred.await(SequentialStep3)
|
|
102
|
+
log.steps.push("step-3")
|
|
103
|
+
return `${step1}:${step2}:${step3}`
|
|
104
|
+
}))
|
|
105
|
+
|
|
106
|
+
const clusterWorkflowLayer = () => {
|
|
107
|
+
const prefix = "test_cluster_sqlite"
|
|
108
|
+
const config = ShardingConfig.layer({
|
|
109
|
+
runnerAddress: Option.some(testRunnerAddress(20)),
|
|
110
|
+
shardsPerGroup: 1,
|
|
111
|
+
availableShardGroups: [testShardGroup("workflow")],
|
|
112
|
+
assignedShardGroups: [testShardGroup("workflow")],
|
|
113
|
+
entityTerminationTimeout: 0,
|
|
114
|
+
entityMessagePollInterval: 50,
|
|
115
|
+
entityReplyPollInterval: 50,
|
|
116
|
+
refreshAssignmentsInterval: 0,
|
|
117
|
+
sendRetryInterval: 50
|
|
118
|
+
})
|
|
119
|
+
const storage = Layer
|
|
120
|
+
.merge(
|
|
121
|
+
SqlMessageStorage.layerWith({ prefix }),
|
|
122
|
+
Layer.orDie(SqlRunnerStorage.layerWith({ prefix }))
|
|
123
|
+
)
|
|
124
|
+
.pipe(Layer.provide(SqliteClient.layer({ filename: ":memory:" })))
|
|
125
|
+
|
|
126
|
+
return Layer
|
|
127
|
+
.merge(SqliteDeferredWorkflowLayer, SequentialDeferredWorkflowLayer)
|
|
128
|
+
.pipe(
|
|
129
|
+
Layer.provideMerge(StepLog.layer),
|
|
130
|
+
Layer.provideMerge(
|
|
131
|
+
ClusterWorkflowEngine.layer.pipe(
|
|
132
|
+
Layer.provideMerge(Sharding.layer),
|
|
133
|
+
Layer.provide(Runners.layerNoop),
|
|
134
|
+
Layer.provide(RunnerHealth.layerNoop),
|
|
135
|
+
Layer.provide(storage),
|
|
136
|
+
Layer.provide(config),
|
|
137
|
+
Layer.provide(NodeCrypto.layer)
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const completeStep = <Success extends Schema.Top>(
|
|
144
|
+
deferred: DurableDeferred.DurableDeferred<Success, Schema.Never>,
|
|
145
|
+
payload: { readonly id: string },
|
|
146
|
+
value: Success["Type"]
|
|
147
|
+
) =>
|
|
148
|
+
Effect.gen(function*() {
|
|
149
|
+
const token = yield* DurableDeferred.tokenFromPayload(deferred, {
|
|
150
|
+
workflow: SequentialDeferredWorkflow,
|
|
151
|
+
payload
|
|
152
|
+
})
|
|
153
|
+
yield* DurableDeferred.done(deferred, { token, exit: Exit.succeed(value) })
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
const waitForDeferredWorkflowSuspended = (executionId: string) => waitForSuspended(SqliteDeferredWorkflow, executionId)
|
|
157
|
+
|
|
158
|
+
const waitForSequentialWorkflowSuspended = (executionId: string) =>
|
|
159
|
+
waitForSuspended(SequentialDeferredWorkflow, executionId)
|
|
160
|
+
|
|
161
|
+
const waitForSuspended = <A, E, R>(
|
|
162
|
+
workflow: {
|
|
163
|
+
readonly poll: (
|
|
164
|
+
executionId: string
|
|
165
|
+
) => Effect.Effect<Option.Option<Workflow.Result<A, E>>, never, R>
|
|
166
|
+
},
|
|
167
|
+
executionId: string
|
|
168
|
+
) =>
|
|
169
|
+
Effect.gen(function*() {
|
|
170
|
+
const sharding = yield* Sharding.Sharding
|
|
171
|
+
for (let i = 0; i < 100; i++) {
|
|
172
|
+
yield* sharding.pollStorage
|
|
173
|
+
const polled = yield* workflow.poll(executionId)
|
|
174
|
+
if (Option.isSome(polled) && polled.value._tag === "Suspended") return
|
|
175
|
+
yield* Effect.sleep(Duration.millis(100))
|
|
176
|
+
}
|
|
177
|
+
return yield* Effect.fail(new Error(`Workflow ${executionId} did not suspend`))
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const waitForDeferredWorkflowComplete = (executionId: string) =>
|
|
181
|
+
Effect.gen(function*() {
|
|
182
|
+
const sharding = yield* Sharding.Sharding
|
|
183
|
+
for (let i = 0; i < 100; i++) {
|
|
184
|
+
yield* sharding.pollStorage
|
|
185
|
+
const polled = yield* SqliteDeferredWorkflow.poll(executionId)
|
|
186
|
+
if (Option.isSome(polled) && polled.value._tag === "Complete") {
|
|
187
|
+
const exit = polled.value.exit
|
|
188
|
+
assert(Exit.isSuccess(exit))
|
|
189
|
+
return exit.value
|
|
190
|
+
}
|
|
191
|
+
yield* Effect.sleep(Duration.millis(100))
|
|
192
|
+
}
|
|
193
|
+
return yield* Effect.fail(new Error(`Workflow ${executionId} did not complete`))
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
const waitForStep = (log: StepLog["Service"], step: string) =>
|
|
197
|
+
Effect.gen(function*() {
|
|
198
|
+
for (let i = 0; i < 100; i++) {
|
|
199
|
+
if (log.steps.includes(step)) return
|
|
200
|
+
yield* Effect.sleep(Duration.millis(100))
|
|
201
|
+
}
|
|
202
|
+
return yield* Effect.fail(new Error(`Workflow did not reach ${step}`))
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
const testShardGroup = (label: string) => `cluster-sqlite-${testRunId}-${label}`
|
|
206
|
+
|
|
207
|
+
const testRunnerAddress = (offset: number) => RunnerAddress.make("localhost", runnerPortBase + offset)
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
3
|
import { expectTypeOf, it } from "@effect/vitest"
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import * as Context from "effect-app/Context"
|
|
5
|
+
import * as Effect from "effect-app/Effect"
|
|
6
|
+
import * as Layer from "effect-app/Layer"
|
|
7
|
+
import * as Scope from "effect/Scope"
|
|
8
|
+
import { ContextProvider, mergeContextProviders, MergedContextProvider } from "../src/ContextProvider.js"
|
|
6
9
|
import { CustomError1, Some, SomeElse, SomeService } from "./fixtures.js"
|
|
7
10
|
|
|
8
11
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
@@ -20,7 +23,7 @@ class MyContextProvider extends Context.Service<MyContextProvider>()(
|
|
|
20
23
|
yield* Effect.logInfo("MyContextProviderGen", "this is a generator")
|
|
21
24
|
yield* Effect.succeed("this is a generator")
|
|
22
25
|
|
|
23
|
-
return Some.
|
|
26
|
+
return Some.context({ a: 1 })
|
|
24
27
|
})
|
|
25
28
|
})
|
|
26
29
|
}
|
|
@@ -37,7 +40,7 @@ class MyContextProvider2 extends Context.Service<MyContextProvider2>()(
|
|
|
37
40
|
return Effect.gen(function*() {
|
|
38
41
|
// we test without dependencies, so that we end up with an R of never.
|
|
39
42
|
|
|
40
|
-
return SomeElse.
|
|
43
|
+
return SomeElse.context({ b: 2 })
|
|
41
44
|
})
|
|
42
45
|
})
|
|
43
46
|
}
|
|
@@ -54,7 +57,7 @@ class MyContextProvider2Gen extends Context.Service<MyContextProvider2Gen>()(
|
|
|
54
57
|
return function*() {
|
|
55
58
|
// we test without dependencies, so that we end up with an R of never
|
|
56
59
|
|
|
57
|
-
return SomeElse.
|
|
60
|
+
return SomeElse.context({ b: 2 })
|
|
58
61
|
}
|
|
59
62
|
})
|
|
60
63
|
}
|
|
@@ -77,7 +80,7 @@ class MyContextProviderGen extends Context.Service<MyContextProviderGen>()(
|
|
|
77
80
|
yield* Effect.logInfo("MyContextProviderGen", "this is a generator")
|
|
78
81
|
yield* Effect.succeed("this is a generator")
|
|
79
82
|
|
|
80
|
-
return Some.
|
|
83
|
+
return Some.context({ a: 1 })
|
|
81
84
|
}
|
|
82
85
|
})
|
|
83
86
|
}
|
|
@@ -100,7 +103,7 @@ export const someContextProvider = ContextProvider({
|
|
|
100
103
|
// currently the effectful context provider cannot trigger an error when building the per request context
|
|
101
104
|
// if (Math.random() > 0.5) return yield* new CustomError2()
|
|
102
105
|
|
|
103
|
-
return Some.
|
|
106
|
+
return Some.context({ a: 1 })
|
|
104
107
|
})
|
|
105
108
|
})
|
|
106
109
|
})
|
|
@@ -119,7 +122,7 @@ export const someContextProviderGen = ContextProvider({
|
|
|
119
122
|
// currently the effectful context provider cannot trigger an error when building the per request context
|
|
120
123
|
// if (Math.random() > 0.5) return yield* new CustomError2()
|
|
121
124
|
|
|
122
|
-
return Some.
|
|
125
|
+
return Some.context({ a: 1 })
|
|
123
126
|
}
|
|
124
127
|
})
|
|
125
128
|
})
|
package/test/controller.test.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
|
-
import { type MakeContext, type MakeErrors, makeRouter } from "@effect-app/infra/
|
|
3
|
+
import { type MakeContext, type MakeErrors, makeRouter } from "@effect-app/infra/routing"
|
|
4
4
|
import { expect, expectTypeOf, it } from "@effect/vitest"
|
|
5
|
-
import { Context, Effect, Layer, S, Scope } from "effect-app"
|
|
6
5
|
import { InvalidStateError, makeRpcClient, UnauthorizedError } from "effect-app/client"
|
|
6
|
+
import * as Context from "effect-app/Context"
|
|
7
|
+
import * as Effect from "effect-app/Effect"
|
|
8
|
+
import * as Layer from "effect-app/Layer"
|
|
7
9
|
import { DefaultGenericMiddlewares } from "effect-app/middleware"
|
|
8
10
|
import * as RpcX from "effect-app/rpc"
|
|
9
11
|
import { MiddlewareMaker } from "effect-app/rpc"
|
|
12
|
+
import * as S from "effect-app/Schema"
|
|
10
13
|
import { TypeTestId } from "effect-app/TypeTest"
|
|
11
|
-
import { type RpcSerialization } from "effect/
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
+
import { type RpcSerialization } from "effect/rpc"
|
|
15
|
+
import * as Scope from "effect/Scope"
|
|
16
|
+
import { DefaultGenericMiddlewaresLive, DevModeMiddlewareLive } from "../src/routing/middleware.js"
|
|
17
|
+
import { sort } from "../src/routing/tsort.js"
|
|
14
18
|
import { AllowAnonymous, AllowAnonymousLive, CustomError1, RequestContextMap, RequireRoles, RequireRolesLive, Some, SomeElse, SomeService, Test, TestLive } from "./fixtures.js"
|
|
15
19
|
|
|
16
20
|
class MyContextProvider extends RpcX.RpcMiddleware.Tag<MyContextProvider, {
|
|
@@ -188,13 +192,6 @@ const middlewareQuater = MiddlewareMaker
|
|
|
188
192
|
|
|
189
193
|
expectTypeOf(middleware["Service"]).toEqualTypeOf<typeof middlewareQuater["Service"]>()
|
|
190
194
|
|
|
191
|
-
const middleware2 = MiddlewareMaker
|
|
192
|
-
.Tag()("middleware", RequestContextMap)
|
|
193
|
-
.middleware(MyContextProvider)
|
|
194
|
-
.middleware(RequireRoles, Test)
|
|
195
|
-
.middleware(AllowAnonymous)
|
|
196
|
-
.middleware(...DefaultGenericMiddlewares, BogusMiddleware, MyContextProvider2)
|
|
197
|
-
|
|
198
195
|
export const middleware3 = MiddlewareMaker
|
|
199
196
|
.Tag()("middleware", RequestContextMap)
|
|
200
197
|
.middleware(...genericMiddlewares)
|
|
@@ -202,15 +199,17 @@ export const middleware3 = MiddlewareMaker
|
|
|
202
199
|
.middleware(Test)
|
|
203
200
|
.middleware(BogusMiddleware)
|
|
204
201
|
|
|
205
|
-
export const { TaggedRequestFor } = makeRpcClient(
|
|
202
|
+
export const { TaggedRequestFor } = makeRpcClient(middleware)
|
|
206
203
|
const Req = TaggedRequestFor("Something")
|
|
204
|
+
const Command = Req.Command
|
|
205
|
+
const Query = Req.Query
|
|
207
206
|
|
|
208
|
-
export class Eff extends
|
|
209
|
-
export class Gen extends
|
|
207
|
+
export class Eff extends Command<Eff>()("Eff", {}, { success: S.Void }) {}
|
|
208
|
+
export class Gen extends Command<Gen>()("Gen", {}) {}
|
|
210
209
|
|
|
211
210
|
expectTypeOf(Eff.error).toEqualTypeOf<typeof Gen.error>()
|
|
212
211
|
|
|
213
|
-
export class DoSomething extends
|
|
212
|
+
export class DoSomething extends Command<DoSomething>()("DoSomething", {
|
|
214
213
|
id: S.String
|
|
215
214
|
}, { success: S.Void }) {}
|
|
216
215
|
|
|
@@ -228,11 +227,11 @@ export class DoSomething extends Req<DoSomething>()("DoSomething", {
|
|
|
228
227
|
// )
|
|
229
228
|
// )
|
|
230
229
|
|
|
231
|
-
export class GetSomething extends
|
|
230
|
+
export class GetSomething extends Query<GetSomething>()("GetSomething", {
|
|
232
231
|
id: S.String
|
|
233
|
-
}, { success: S.String }) {}
|
|
232
|
+
}, { success: S.String, error: UnauthorizedError }) {}
|
|
234
233
|
|
|
235
|
-
export class GetSomething2 extends
|
|
234
|
+
export class GetSomething2 extends Query<GetSomething2>()("GetSomething2", {
|
|
236
235
|
id: S.String
|
|
237
236
|
}, { success: S.FiniteFromString }) {}
|
|
238
237
|
|
|
@@ -254,7 +253,7 @@ export class SomethingService extends Context.Service<SomethingService>()(
|
|
|
254
253
|
static Default = Layer.effect(this, this.make)
|
|
255
254
|
}
|
|
256
255
|
|
|
257
|
-
declare const
|
|
256
|
+
declare const _a: {
|
|
258
257
|
(opt: { a: 1 }): void
|
|
259
258
|
(opt: { a: 2 }): void
|
|
260
259
|
(opt: { b: 3 }): void
|
|
@@ -285,13 +284,9 @@ export class SomethingService2 extends Context.Service<SomethingService2>()(
|
|
|
285
284
|
static Default = Layer.effect(this, this.make)
|
|
286
285
|
}
|
|
287
286
|
|
|
288
|
-
export const { Router, matchAll } = makeRouter(
|
|
289
|
-
middleware
|
|
290
|
-
)
|
|
287
|
+
export const { Router, matchAll } = makeRouter(middleware.Default)
|
|
291
288
|
|
|
292
|
-
export const r2 = makeRouter(
|
|
293
|
-
Object.assign(middleware2, { Default: middleware2.layer.pipe(Layer.provide([...MiddlewaresLive])) })
|
|
294
|
-
)
|
|
289
|
+
export const r2 = makeRouter(middleware.Default)
|
|
295
290
|
|
|
296
291
|
const router = Router(Something)({
|
|
297
292
|
dependencies: [
|
|
@@ -349,7 +344,7 @@ const router = Router(Something)({
|
|
|
349
344
|
}
|
|
350
345
|
},
|
|
351
346
|
GetSomething2: {
|
|
352
|
-
raw: Some.use(() => Effect.succeed("12"))
|
|
347
|
+
raw: () => Some.use(() => Effect.succeed("12"))
|
|
353
348
|
}
|
|
354
349
|
})
|
|
355
350
|
}
|
|
@@ -414,7 +409,7 @@ const router2 = r2.Router(Something)({
|
|
|
414
409
|
}
|
|
415
410
|
},
|
|
416
411
|
GetSomething2: {
|
|
417
|
-
raw: Some.use(() => Effect.succeed("12"))
|
|
412
|
+
raw: () => Some.use(() => Effect.succeed("12"))
|
|
418
413
|
}
|
|
419
414
|
})
|
|
420
415
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, expect, it } from "@effect/vitest"
|
|
2
|
+
import { type ContainerDb, createContainerIfNotExists } from "../src/cosmos-client.js"
|
|
3
|
+
|
|
4
|
+
const body = { id: "prefix-Orders", partitionKey: { paths: ["/_partitionKey"], version: 2 } }
|
|
5
|
+
|
|
6
|
+
const fakeDb = (opts: {
|
|
7
|
+
readonly read: () => Promise<unknown>
|
|
8
|
+
readonly sharedOffer: boolean
|
|
9
|
+
readonly offerError?: unknown
|
|
10
|
+
}) => {
|
|
11
|
+
const calls = { created: [] as Array<unknown>, offerReads: 0 }
|
|
12
|
+
const db: ContainerDb = {
|
|
13
|
+
container: () => ({ read: opts.read }),
|
|
14
|
+
containers: {
|
|
15
|
+
createIfNotExists: (req) => {
|
|
16
|
+
calls.created.push(req)
|
|
17
|
+
return Promise.resolve({})
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
readOffer: () => {
|
|
21
|
+
calls.offerReads++
|
|
22
|
+
if (opts.offerError !== undefined) return Promise.reject(opts.offerError)
|
|
23
|
+
return Promise.resolve({ resource: opts.sharedOffer ? { id: "offer" } : undefined })
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { calls, db }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const existing = () => Promise.resolve({})
|
|
30
|
+
const missing = () => Promise.reject({ code: 404 })
|
|
31
|
+
|
|
32
|
+
describe("createContainerIfNotExists", () => {
|
|
33
|
+
it("keeps the Cosmos default when no autoscale max is configured", async () => {
|
|
34
|
+
const { calls, db } = fakeDb({ read: missing, sharedOffer: false })
|
|
35
|
+
await createContainerIfNotExists(db, body)
|
|
36
|
+
expect(calls.created).toEqual([body])
|
|
37
|
+
expect(calls.offerReads).toBe(0)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it("creates a missing container with autoscale in a database without shared throughput", async () => {
|
|
41
|
+
const { calls, db } = fakeDb({ read: missing, sharedOffer: false })
|
|
42
|
+
await createContainerIfNotExists(db, body, { autoscaleMaxThroughput: 1000 })
|
|
43
|
+
expect(calls.created).toEqual([{ ...body, maxThroughput: 1000 }])
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it("lets a missing container share the database throughput when the database has an offer", async () => {
|
|
47
|
+
const { calls, db } = fakeDb({ read: missing, sharedOffer: true })
|
|
48
|
+
await createContainerIfNotExists(db, body, { autoscaleMaxThroughput: 1000 })
|
|
49
|
+
expect(calls.created).toEqual([body])
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it("leaves existing containers untouched", async () => {
|
|
53
|
+
const { calls, db } = fakeDb({ read: existing, sharedOffer: false })
|
|
54
|
+
await createContainerIfNotExists(db, body, { autoscaleMaxThroughput: 1000 })
|
|
55
|
+
expect(calls.created).toEqual([])
|
|
56
|
+
expect(calls.offerReads).toBe(0)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it("propagates container read errors other than not found", async () => {
|
|
60
|
+
const { calls, db } = fakeDb({ read: () => Promise.reject({ code: 403 }), sharedOffer: false })
|
|
61
|
+
await expect(createContainerIfNotExists(db, body, { autoscaleMaxThroughput: 1000 })).rejects.toEqual({
|
|
62
|
+
code: 403
|
|
63
|
+
})
|
|
64
|
+
expect(calls.created).toEqual([])
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it("creates without throughput when offer reads are rejected as serverless", async () => {
|
|
68
|
+
const { calls, db } = fakeDb({
|
|
69
|
+
read: missing,
|
|
70
|
+
sharedOffer: false,
|
|
71
|
+
offerError: {
|
|
72
|
+
code: 400,
|
|
73
|
+
message: "Reading or replacing offers is not supported for serverless accounts."
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
await createContainerIfNotExists(db, body, { autoscaleMaxThroughput: 1000 })
|
|
77
|
+
expect(calls.created).toEqual([body])
|
|
78
|
+
expect(calls.offerReads).toBe(1)
|
|
79
|
+
})
|
|
80
|
+
})
|