velocious 1.0.430 → 1.0.432
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/bin/velocious.js +48 -0
- package/build/application.js +229 -0
- package/build/authorization/ability.js +329 -0
- package/build/authorization/base-resource.js +143 -0
- package/build/background-jobs/client.js +50 -0
- package/build/background-jobs/cron-expression.js +277 -0
- package/build/background-jobs/forked-runner-child.js +86 -0
- package/build/background-jobs/job-record.js +13 -0
- package/build/background-jobs/job-registry.js +92 -0
- package/build/background-jobs/job-runner.js +107 -0
- package/build/background-jobs/job.js +77 -0
- package/build/background-jobs/json-socket.js +78 -0
- package/build/background-jobs/main.js +926 -0
- package/build/background-jobs/normalize-error.js +26 -0
- package/build/background-jobs/scheduler.js +274 -0
- package/build/background-jobs/socket-request.js +68 -0
- package/build/background-jobs/status-reporter.js +101 -0
- package/build/background-jobs/store.js +994 -0
- package/build/background-jobs/types.js +70 -0
- package/build/background-jobs/web/authorization.js +89 -0
- package/build/background-jobs/web/controller.js +280 -0
- package/build/background-jobs/web/index.js +57 -0
- package/build/background-jobs/web/path-matcher.js +74 -0
- package/build/background-jobs/web/registry.js +49 -0
- package/build/background-jobs/worker.js +683 -0
- package/build/beacon/client.js +330 -0
- package/build/beacon/in-process-broker.js +71 -0
- package/build/beacon/in-process-client.js +139 -0
- package/build/beacon/server.js +148 -0
- package/build/beacon/types.js +55 -0
- package/build/bin/velocious.js +39 -34
- package/build/cli/base-command.js +67 -0
- package/build/cli/browser-cli.js +45 -0
- package/build/cli/commands/background-jobs-main.js +7 -0
- package/build/cli/commands/background-jobs-runner.js +7 -0
- package/build/cli/commands/background-jobs-worker.js +7 -0
- package/build/cli/commands/beacon.js +7 -0
- package/build/cli/commands/console.js +12 -0
- package/build/cli/commands/db/base-command.js +82 -0
- package/build/cli/commands/db/create.js +64 -0
- package/build/cli/commands/db/drop.js +75 -0
- package/build/cli/commands/db/migrate.js +17 -0
- package/build/cli/commands/db/reset.js +22 -0
- package/build/cli/commands/db/rollback.js +15 -0
- package/build/cli/commands/db/schema/dump.js +12 -0
- package/build/cli/commands/db/schema/load.js +12 -0
- package/build/cli/commands/db/seed.js +12 -0
- package/build/cli/commands/db/tenants/check.js +38 -0
- package/build/cli/commands/db/tenants/create.js +33 -0
- package/build/cli/commands/db/tenants/migrate.js +49 -0
- package/build/cli/commands/destroy/migration.js +7 -0
- package/build/cli/commands/generate/base-models.js +7 -0
- package/build/cli/commands/generate/frontend-models.js +12 -0
- package/build/cli/commands/generate/migration.js +7 -0
- package/build/cli/commands/generate/model.js +7 -0
- package/build/cli/commands/init.js +11 -0
- package/build/cli/commands/routes.js +7 -0
- package/build/cli/commands/run-script.js +12 -0
- package/build/cli/commands/runner.js +12 -0
- package/build/cli/commands/server.js +7 -0
- package/build/cli/commands/test.js +9 -0
- package/build/cli/index.js +152 -0
- package/build/cli/tenant-database-command-helper.js +198 -0
- package/build/cli/use-browser-cli.js +30 -0
- package/build/configuration-resolver.js +65 -0
- package/build/configuration-types.js +429 -0
- package/build/configuration.js +2590 -0
- package/build/controller.js +421 -0
- package/build/current-configuration.js +31 -0
- package/build/current.js +80 -0
- package/build/database/annotations-async-hooks.js +47 -0
- package/build/database/annotations.js +40 -0
- package/build/database/drivers/base-column.js +182 -0
- package/build/database/drivers/base-columns-index.js +81 -0
- package/build/database/drivers/base-foreign-key.js +104 -0
- package/build/database/drivers/base-table.js +156 -0
- package/build/database/drivers/base.js +1609 -0
- package/build/database/drivers/mssql/column.js +74 -0
- package/build/database/drivers/mssql/columns-index.js +6 -0
- package/build/database/drivers/mssql/connect-connection.js +16 -0
- package/build/database/drivers/mssql/foreign-key.js +12 -0
- package/build/database/drivers/mssql/index.js +590 -0
- package/build/database/drivers/mssql/options.js +79 -0
- package/build/database/drivers/mssql/query-parser.js +6 -0
- package/build/database/drivers/mssql/sql/alter-table.js +4 -0
- package/build/database/drivers/mssql/sql/create-database.js +36 -0
- package/build/database/drivers/mssql/sql/create-index.js +4 -0
- package/build/database/drivers/mssql/sql/create-table.js +4 -0
- package/build/database/drivers/mssql/sql/delete.js +19 -0
- package/build/database/drivers/mssql/sql/drop-database.js +36 -0
- package/build/database/drivers/mssql/sql/drop-table.js +4 -0
- package/build/database/drivers/mssql/sql/insert.js +4 -0
- package/build/database/drivers/mssql/sql/update.js +31 -0
- package/build/database/drivers/mssql/sql/upsert.js +23 -0
- package/build/database/drivers/mssql/structure-sql.js +120 -0
- package/build/database/drivers/mssql/table.js +145 -0
- package/build/database/drivers/mysql/column.js +112 -0
- package/build/database/drivers/mysql/columns-index.js +22 -0
- package/build/database/drivers/mysql/foreign-key.js +12 -0
- package/build/database/drivers/mysql/index.js +473 -0
- package/build/database/drivers/mysql/options.js +34 -0
- package/build/database/drivers/mysql/query-parser.js +6 -0
- package/build/database/drivers/mysql/query.js +37 -0
- package/build/database/drivers/mysql/sql/alter-table.js +6 -0
- package/build/database/drivers/mysql/sql/create-database.js +39 -0
- package/build/database/drivers/mysql/sql/create-index.js +6 -0
- package/build/database/drivers/mysql/sql/create-table.js +6 -0
- package/build/database/drivers/mysql/sql/delete.js +21 -0
- package/build/database/drivers/mysql/sql/drop-database.js +6 -0
- package/build/database/drivers/mysql/sql/drop-table.js +6 -0
- package/build/database/drivers/mysql/sql/insert.js +6 -0
- package/build/database/drivers/mysql/sql/update.js +33 -0
- package/build/database/drivers/mysql/sql/upsert.js +13 -0
- package/build/database/drivers/mysql/structure-sql.js +93 -0
- package/build/database/drivers/mysql/table.js +121 -0
- package/build/database/drivers/pgsql/column.js +90 -0
- package/build/database/drivers/pgsql/columns-index.js +6 -0
- package/build/database/drivers/pgsql/foreign-key.js +12 -0
- package/build/database/drivers/pgsql/index.js +441 -0
- package/build/database/drivers/pgsql/options.js +32 -0
- package/build/database/drivers/pgsql/query-parser.js +6 -0
- package/build/database/drivers/pgsql/sql/alter-table.js +6 -0
- package/build/database/drivers/pgsql/sql/create-database.js +38 -0
- package/build/database/drivers/pgsql/sql/create-index.js +6 -0
- package/build/database/drivers/pgsql/sql/create-table.js +6 -0
- package/build/database/drivers/pgsql/sql/delete.js +21 -0
- package/build/database/drivers/pgsql/sql/drop-database.js +6 -0
- package/build/database/drivers/pgsql/sql/drop-table.js +6 -0
- package/build/database/drivers/pgsql/sql/insert.js +6 -0
- package/build/database/drivers/pgsql/sql/update.js +33 -0
- package/build/database/drivers/pgsql/sql/upsert.js +14 -0
- package/build/database/drivers/pgsql/structure-sql.js +126 -0
- package/build/database/drivers/pgsql/table.js +135 -0
- package/build/database/drivers/sqlite/base.js +509 -0
- package/build/database/drivers/sqlite/column.js +75 -0
- package/build/database/drivers/sqlite/columns-index.js +30 -0
- package/build/database/drivers/sqlite/connection-sql-js.js +46 -0
- package/build/database/drivers/sqlite/foreign-key.js +24 -0
- package/build/database/drivers/sqlite/index.js +394 -0
- package/build/database/drivers/sqlite/index.native.js +72 -0
- package/build/database/drivers/sqlite/index.web.js +99 -0
- package/build/database/drivers/sqlite/options.js +32 -0
- package/build/database/drivers/sqlite/query-parser.js +6 -0
- package/build/database/drivers/sqlite/query.js +35 -0
- package/build/database/drivers/sqlite/query.native.js +35 -0
- package/build/database/drivers/sqlite/query.web.js +49 -0
- package/build/database/drivers/sqlite/sql/alter-table.js +187 -0
- package/build/database/drivers/sqlite/sql/create-index.js +6 -0
- package/build/database/drivers/sqlite/sql/create-table.js +6 -0
- package/build/database/drivers/sqlite/sql/delete.js +26 -0
- package/build/database/drivers/sqlite/sql/drop-table.js +6 -0
- package/build/database/drivers/sqlite/sql/insert.js +6 -0
- package/build/database/drivers/sqlite/sql/update.js +33 -0
- package/build/database/drivers/sqlite/sql/upsert.js +14 -0
- package/build/database/drivers/sqlite/structure-sql.js +56 -0
- package/build/database/drivers/sqlite/table-rebuilder.js +96 -0
- package/build/database/drivers/sqlite/table.js +131 -0
- package/build/database/drivers/structure-sql/utils.js +35 -0
- package/build/database/handler.js +13 -0
- package/build/database/initializer-from-require-context.js +101 -0
- package/build/database/migration/index.js +438 -0
- package/build/database/migrator/files-finder.js +55 -0
- package/build/database/migrator/types.js +31 -0
- package/build/database/migrator.js +557 -0
- package/build/database/pool/async-tracked-multi-connection.js +1164 -0
- package/build/database/pool/base-methods-forward.js +52 -0
- package/build/database/pool/base.js +380 -0
- package/build/database/pool/single-multi-use.js +118 -0
- package/build/database/query/alter-table-base.js +104 -0
- package/build/database/query/base.js +49 -0
- package/build/database/query/create-database-base.js +42 -0
- package/build/database/query/create-index-base.js +117 -0
- package/build/database/query/create-table-base.js +205 -0
- package/build/database/query/delete-base.js +19 -0
- package/build/database/query/drop-database-base.js +38 -0
- package/build/database/query/drop-table-base.js +58 -0
- package/build/database/query/from-base.js +36 -0
- package/build/database/query/from-plain.js +16 -0
- package/build/database/query/from-table.js +18 -0
- package/build/database/query/index.js +533 -0
- package/build/database/query/insert-base.js +172 -0
- package/build/database/query/join-base.js +43 -0
- package/build/database/query/join-object.js +167 -0
- package/build/database/query/join-plain.js +18 -0
- package/build/database/query/join-tracker.js +93 -0
- package/build/database/query/model-class-query.js +1577 -0
- package/build/database/query/order-base.js +33 -0
- package/build/database/query/order-column.js +77 -0
- package/build/database/query/order-plain.js +28 -0
- package/build/database/query/preloader/belongs-to.js +267 -0
- package/build/database/query/preloader/ensure-model-class-initialized.js +18 -0
- package/build/database/query/preloader/has-many.js +316 -0
- package/build/database/query/preloader/has-one.js +123 -0
- package/build/database/query/preloader/selection.js +152 -0
- package/build/database/query/preloader.js +201 -0
- package/build/database/query/query-data.js +305 -0
- package/build/database/query/select-base.js +30 -0
- package/build/database/query/select-plain.js +18 -0
- package/build/database/query/select-table-and-column.js +28 -0
- package/build/database/query/update-base.js +41 -0
- package/build/database/query/upsert-base.js +103 -0
- package/build/database/query/where-base.js +38 -0
- package/build/database/query/where-combinator.js +31 -0
- package/build/database/query/where-hash.js +77 -0
- package/build/database/query/where-model-class-hash.js +505 -0
- package/build/database/query/where-not.js +23 -0
- package/build/database/query/where-plain.js +20 -0
- package/build/database/query/with-count.js +219 -0
- package/build/database/query-parser/base-query-parser.js +40 -0
- package/build/database/query-parser/from-parser.js +49 -0
- package/build/database/query-parser/group-parser.js +55 -0
- package/build/database/query-parser/joins-parser.js +37 -0
- package/build/database/query-parser/limit-parser.js +77 -0
- package/build/database/query-parser/options.js +94 -0
- package/build/database/query-parser/order-parser.js +45 -0
- package/build/database/query-parser/select-parser.js +67 -0
- package/build/database/query-parser/where-parser.js +46 -0
- package/build/database/record/acts-as-list.js +374 -0
- package/build/database/record/attachments/download.js +49 -0
- package/build/database/record/attachments/handle.js +188 -0
- package/build/database/record/attachments/normalize-input.js +213 -0
- package/build/database/record/attachments/storage-drivers/filesystem.js +114 -0
- package/build/database/record/attachments/storage-drivers/native.js +146 -0
- package/build/database/record/attachments/storage-drivers/s3.js +245 -0
- package/build/database/record/attachments/store.js +591 -0
- package/build/database/record/index.js +4094 -0
- package/build/database/record/instance-relationships/base.js +289 -0
- package/build/database/record/instance-relationships/belongs-to.js +84 -0
- package/build/database/record/instance-relationships/has-many.js +284 -0
- package/build/database/record/instance-relationships/has-one.js +117 -0
- package/build/database/record/record-not-found-error.js +3 -0
- package/build/database/record/relationships/base.js +195 -0
- package/build/database/record/relationships/belongs-to.js +57 -0
- package/build/database/record/relationships/has-many.js +46 -0
- package/build/database/record/relationships/has-one.js +46 -0
- package/build/database/record/state-machine.js +278 -0
- package/build/database/record/user-module.js +43 -0
- package/build/database/record/validators/base.js +27 -0
- package/build/database/record/validators/format.js +50 -0
- package/build/database/record/validators/presence.js +24 -0
- package/build/database/record/validators/uniqueness.js +124 -0
- package/build/database/table-data/index.js +241 -0
- package/build/database/table-data/table-column.js +416 -0
- package/build/database/table-data/table-foreign-key.js +69 -0
- package/build/database/table-data/table-index.js +46 -0
- package/build/database/table-data/table-reference.js +13 -0
- package/build/database/use-database.js +48 -0
- package/build/environment-handlers/base.js +561 -0
- package/build/environment-handlers/browser.js +338 -0
- package/build/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
- package/build/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
- package/build/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
- package/build/environment-handlers/node/cli/commands/beacon.js +21 -0
- package/build/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
- package/build/environment-handlers/node/cli/commands/console.js +149 -0
- package/build/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
- package/build/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
- package/build/environment-handlers/node/cli/commands/db/seed.js +79 -0
- package/build/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
- package/build/environment-handlers/node/cli/commands/generate/base-models.js +396 -0
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
- package/build/environment-handlers/node/cli/commands/generate/migration.js +45 -0
- package/build/environment-handlers/node/cli/commands/generate/model.js +45 -0
- package/build/environment-handlers/node/cli/commands/init.js +68 -0
- package/build/environment-handlers/node/cli/commands/routes.js +63 -0
- package/build/environment-handlers/node/cli/commands/run-script.js +85 -0
- package/build/environment-handlers/node/cli/commands/runner.js +84 -0
- package/build/environment-handlers/node/cli/commands/server.js +151 -0
- package/build/environment-handlers/node/cli/commands/test.js +118 -0
- package/build/environment-handlers/node.js +887 -0
- package/build/error-logger.js +30 -0
- package/build/frontend-model-controller.js +3491 -0
- package/build/frontend-model-resource/base-resource.js +935 -0
- package/build/frontend-models/base.js +4004 -0
- package/build/frontend-models/clear-pending-debounced-callback.js +16 -0
- package/build/frontend-models/event-hook-models.js +49 -0
- package/build/frontend-models/model-registry.js +28 -0
- package/build/frontend-models/outgoing-event-buffer.js +51 -0
- package/build/frontend-models/preloader.js +169 -0
- package/build/frontend-models/query.js +2245 -0
- package/build/frontend-models/resource-config-validation.js +56 -0
- package/build/frontend-models/resource-definition.js +399 -0
- package/build/frontend-models/transport-serialization.js +369 -0
- package/build/frontend-models/use-created-event.js +21 -0
- package/build/frontend-models/use-destroyed-event.js +148 -0
- package/build/frontend-models/use-model-class-event.js +164 -0
- package/build/frontend-models/use-updated-event.js +152 -0
- package/build/frontend-models/websocket-channel.js +494 -0
- package/build/frontend-models/websocket-publishers.js +224 -0
- package/build/http-client/header.js +17 -0
- package/build/http-client/index.js +139 -0
- package/build/http-client/request.js +94 -0
- package/build/http-client/response.js +151 -0
- package/build/http-client/websocket-client.js +27 -0
- package/build/http-server/client/index.js +507 -0
- package/build/http-server/client/params-to-object.js +152 -0
- package/build/http-server/client/request-buffer/form-data-part.js +139 -0
- package/build/http-server/client/request-buffer/header.js +19 -0
- package/build/http-server/client/request-buffer/index.js +535 -0
- package/build/http-server/client/request-parser.js +195 -0
- package/build/http-server/client/request-runner.js +321 -0
- package/build/http-server/client/request-timing.js +171 -0
- package/build/http-server/client/request.js +114 -0
- package/build/http-server/client/response.js +251 -0
- package/build/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
- package/build/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
- package/build/http-server/client/uploaded-file/uploaded-file.js +36 -0
- package/build/http-server/client/websocket-request.js +147 -0
- package/build/http-server/client/websocket-session.js +1755 -0
- package/build/http-server/cookie.js +245 -0
- package/build/http-server/development-reloader.js +240 -0
- package/build/http-server/index.js +561 -0
- package/build/http-server/remote-address.js +77 -0
- package/build/http-server/server-client.js +222 -0
- package/build/http-server/server-lock.js +178 -0
- package/build/http-server/websocket-channel-subscribers.js +110 -0
- package/build/http-server/websocket-channel.js +137 -0
- package/build/http-server/websocket-connection.js +118 -0
- package/build/http-server/websocket-event-log-store.js +433 -0
- package/build/http-server/websocket-events-host.js +170 -0
- package/build/http-server/websocket-events.js +50 -0
- package/build/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
- package/build/http-server/worker-handler/in-process.js +155 -0
- package/build/http-server/worker-handler/index.js +370 -0
- package/build/http-server/worker-handler/worker-script.js +6 -0
- package/build/http-server/worker-handler/worker-thread.js +286 -0
- package/build/index.js +1 -2
- package/build/initializer.js +39 -0
- package/build/jobs/mail-delivery.js +22 -0
- package/build/logger/base-logger.js +34 -0
- package/build/logger/console-logger.js +28 -0
- package/build/logger/file-logger.js +36 -0
- package/build/logger/outputs/array-output.js +50 -0
- package/build/logger/outputs/console-output.js +32 -0
- package/build/logger/outputs/file-output.js +55 -0
- package/build/logger/outputs/stdout-output.js +64 -0
- package/build/logger.js +507 -0
- package/build/mailer/backends/smtp.js +197 -0
- package/build/mailer/base.js +337 -0
- package/build/mailer/delivery.js +70 -0
- package/build/mailer/index.js +24 -0
- package/build/mailer.js +15 -0
- package/build/plugins/sqljs-wasm-route-controller.js +70 -0
- package/build/plugins/sqljs-wasm-route.js +71 -0
- package/build/record-payload-values.js +83 -0
- package/build/routes/app-routes.js +17 -0
- package/build/routes/base-route.js +133 -0
- package/build/routes/basic-route.js +109 -0
- package/build/routes/built-in/debug/controller.js +12 -0
- package/build/routes/built-in/errors/controller.js +7 -0
- package/build/routes/get-route.js +75 -0
- package/build/routes/hooks/frontend-model-command-route-hook.js +100 -0
- package/build/routes/index.js +50 -0
- package/build/routes/namespace-route.js +51 -0
- package/build/routes/plugin-routes.js +141 -0
- package/build/routes/post-route.js +74 -0
- package/build/routes/resolver.js +535 -0
- package/build/routes/resource-route.js +154 -0
- package/build/routes/root-route.js +11 -0
- package/build/src/authorization/ability.d.ts +24 -23
- package/build/src/authorization/ability.d.ts.map +1 -1
- package/build/src/authorization/ability.js +14 -13
- package/build/src/authorization/base-resource.d.ts +20 -26
- package/build/src/authorization/base-resource.d.ts.map +1 -1
- package/build/src/authorization/base-resource.js +13 -11
- package/build/src/configuration-types.d.ts +21 -2
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +8 -2
- package/build/src/database/query/where-combinator.d.ts.map +1 -1
- package/build/src/database/query/where-combinator.js +1 -2
- package/build/src/database/record/acts-as-list.js +2 -2
- package/build/src/database/record/attachments/store.d.ts +1 -1
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +2 -2
- package/build/src/database/record/index.d.ts +82 -20
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +126 -13
- package/build/src/database/record/relationships/base.d.ts +2 -2
- package/build/src/database/record/relationships/base.d.ts.map +1 -1
- package/build/src/database/record/relationships/base.js +3 -3
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts +4 -2
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +59 -36
- package/build/src/frontend-model-controller.d.ts +6 -6
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +4 -4
- package/build/src/frontend-model-resource/base-resource.d.ts +18 -17
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +22 -10
- package/build/src/frontend-models/base.d.ts +19 -12
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +79 -48
- package/build/src/frontend-models/preloader.d.ts +6 -6
- package/build/src/frontend-models/preloader.d.ts.map +1 -1
- package/build/src/frontend-models/preloader.js +5 -5
- package/build/src/frontend-models/query.d.ts.map +1 -1
- package/build/src/frontend-models/query.js +1 -4
- package/build/src/utils/ransack.d.ts.map +1 -1
- package/build/src/utils/ransack.js +1 -2
- package/build/templates/configuration.js +61 -0
- package/build/templates/generate-migration.js +11 -0
- package/build/templates/generate-model.js +6 -0
- package/build/templates/routes.js +11 -0
- package/build/testing/base-expect.js +17 -0
- package/build/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
- package/build/testing/browser-test-app.js +32 -0
- package/build/testing/expect-to-change.js +55 -0
- package/build/testing/expect-utils.js +269 -0
- package/build/testing/expect.js +763 -0
- package/build/testing/request-client.js +90 -0
- package/build/testing/test-files-finder.js +364 -0
- package/build/testing/test-filter-parser.js +198 -0
- package/build/testing/test-runner.js +1168 -0
- package/build/testing/test-suite-splitter.js +177 -0
- package/build/testing/test.js +370 -0
- package/build/utils/backtrace-cleaner-node.js +87 -0
- package/build/utils/backtrace-cleaner.js +266 -0
- package/build/utils/ensure-error.js +15 -0
- package/build/utils/event-emitter.js +8 -0
- package/build/utils/file-exists.js +18 -0
- package/build/utils/format-value.js +101 -0
- package/build/utils/model-scope.js +56 -0
- package/build/utils/nest-callbacks.js +22 -0
- package/build/utils/plain-object.js +14 -0
- package/build/utils/ransack.js +859 -0
- package/build/utils/rest-args-error.js +14 -0
- package/build/utils/singularize-model-name.js +18 -0
- package/build/utils/split-sql-statements.js +88 -0
- package/build/utils/to-import-specifier.js +53 -0
- package/build/utils/with-tracked-stack-async-hooks.js +103 -0
- package/build/utils/with-tracked-stack.js +38 -0
- package/build/velocious-error.js +34 -0
- package/index.js +1 -0
- package/package.json +10 -4
- package/scripts/clean-build.js +8 -0
- package/scripts/ensure-bin-executable.js +13 -0
- package/scripts/run-tests.js +37 -0
- package/scripts/test-browser.js +486 -0
- package/src/application.js +229 -0
- package/src/authorization/ability.js +329 -0
- package/src/authorization/base-resource.js +143 -0
- package/src/background-jobs/client.js +50 -0
- package/src/background-jobs/cron-expression.js +277 -0
- package/src/background-jobs/forked-runner-child.js +86 -0
- package/src/background-jobs/job-record.js +13 -0
- package/src/background-jobs/job-registry.js +92 -0
- package/src/background-jobs/job-runner.js +107 -0
- package/src/background-jobs/job.js +77 -0
- package/src/background-jobs/json-socket.js +78 -0
- package/src/background-jobs/main.js +926 -0
- package/src/background-jobs/normalize-error.js +26 -0
- package/src/background-jobs/scheduler.js +274 -0
- package/src/background-jobs/socket-request.js +68 -0
- package/src/background-jobs/status-reporter.js +101 -0
- package/src/background-jobs/store.js +994 -0
- package/src/background-jobs/types.js +70 -0
- package/src/background-jobs/web/authorization.js +89 -0
- package/src/background-jobs/web/controller.js +280 -0
- package/src/background-jobs/web/index.js +57 -0
- package/src/background-jobs/web/path-matcher.js +74 -0
- package/src/background-jobs/web/registry.js +49 -0
- package/src/background-jobs/worker.js +683 -0
- package/src/beacon/client.js +330 -0
- package/src/beacon/in-process-broker.js +71 -0
- package/src/beacon/in-process-client.js +139 -0
- package/src/beacon/server.js +148 -0
- package/src/beacon/types.js +55 -0
- package/src/cli/base-command.js +67 -0
- package/src/cli/browser-cli.js +45 -0
- package/src/cli/commands/background-jobs-main.js +7 -0
- package/src/cli/commands/background-jobs-runner.js +7 -0
- package/src/cli/commands/background-jobs-worker.js +7 -0
- package/src/cli/commands/beacon.js +7 -0
- package/src/cli/commands/console.js +12 -0
- package/src/cli/commands/db/base-command.js +82 -0
- package/src/cli/commands/db/create.js +64 -0
- package/src/cli/commands/db/drop.js +75 -0
- package/src/cli/commands/db/migrate.js +17 -0
- package/src/cli/commands/db/reset.js +22 -0
- package/src/cli/commands/db/rollback.js +15 -0
- package/src/cli/commands/db/schema/dump.js +12 -0
- package/src/cli/commands/db/schema/load.js +12 -0
- package/src/cli/commands/db/seed.js +12 -0
- package/src/cli/commands/db/tenants/check.js +38 -0
- package/src/cli/commands/db/tenants/create.js +33 -0
- package/src/cli/commands/db/tenants/migrate.js +49 -0
- package/src/cli/commands/destroy/migration.js +7 -0
- package/src/cli/commands/generate/base-models.js +7 -0
- package/src/cli/commands/generate/frontend-models.js +12 -0
- package/src/cli/commands/generate/migration.js +7 -0
- package/src/cli/commands/generate/model.js +7 -0
- package/src/cli/commands/init.js +11 -0
- package/src/cli/commands/routes.js +7 -0
- package/src/cli/commands/run-script.js +12 -0
- package/src/cli/commands/runner.js +12 -0
- package/src/cli/commands/server.js +7 -0
- package/src/cli/commands/test.js +9 -0
- package/src/cli/index.js +152 -0
- package/src/cli/tenant-database-command-helper.js +198 -0
- package/src/cli/use-browser-cli.js +30 -0
- package/src/configuration-resolver.js +65 -0
- package/src/configuration-types.js +429 -0
- package/src/configuration.js +2590 -0
- package/src/controller.js +421 -0
- package/src/current-configuration.js +31 -0
- package/src/current.js +80 -0
- package/src/database/annotations-async-hooks.js +47 -0
- package/src/database/annotations.js +40 -0
- package/src/database/drivers/base-column.js +182 -0
- package/src/database/drivers/base-columns-index.js +81 -0
- package/src/database/drivers/base-foreign-key.js +104 -0
- package/src/database/drivers/base-table.js +156 -0
- package/src/database/drivers/base.js +1609 -0
- package/src/database/drivers/mssql/column.js +74 -0
- package/src/database/drivers/mssql/columns-index.js +6 -0
- package/src/database/drivers/mssql/connect-connection.js +16 -0
- package/src/database/drivers/mssql/foreign-key.js +12 -0
- package/src/database/drivers/mssql/index.js +590 -0
- package/src/database/drivers/mssql/options.js +79 -0
- package/src/database/drivers/mssql/query-parser.js +6 -0
- package/src/database/drivers/mssql/sql/alter-table.js +4 -0
- package/src/database/drivers/mssql/sql/create-database.js +36 -0
- package/src/database/drivers/mssql/sql/create-index.js +4 -0
- package/src/database/drivers/mssql/sql/create-table.js +4 -0
- package/src/database/drivers/mssql/sql/delete.js +19 -0
- package/src/database/drivers/mssql/sql/drop-database.js +36 -0
- package/src/database/drivers/mssql/sql/drop-table.js +4 -0
- package/src/database/drivers/mssql/sql/insert.js +4 -0
- package/src/database/drivers/mssql/sql/update.js +31 -0
- package/src/database/drivers/mssql/sql/upsert.js +23 -0
- package/src/database/drivers/mssql/structure-sql.js +120 -0
- package/src/database/drivers/mssql/table.js +145 -0
- package/src/database/drivers/mysql/column.js +112 -0
- package/src/database/drivers/mysql/columns-index.js +22 -0
- package/src/database/drivers/mysql/foreign-key.js +12 -0
- package/src/database/drivers/mysql/index.js +473 -0
- package/src/database/drivers/mysql/options.js +34 -0
- package/src/database/drivers/mysql/query-parser.js +6 -0
- package/src/database/drivers/mysql/query.js +37 -0
- package/src/database/drivers/mysql/sql/alter-table.js +6 -0
- package/src/database/drivers/mysql/sql/create-database.js +39 -0
- package/src/database/drivers/mysql/sql/create-index.js +6 -0
- package/src/database/drivers/mysql/sql/create-table.js +6 -0
- package/src/database/drivers/mysql/sql/delete.js +21 -0
- package/src/database/drivers/mysql/sql/drop-database.js +6 -0
- package/src/database/drivers/mysql/sql/drop-table.js +6 -0
- package/src/database/drivers/mysql/sql/insert.js +6 -0
- package/src/database/drivers/mysql/sql/update.js +33 -0
- package/src/database/drivers/mysql/sql/upsert.js +13 -0
- package/src/database/drivers/mysql/structure-sql.js +93 -0
- package/src/database/drivers/mysql/table.js +121 -0
- package/src/database/drivers/pgsql/column.js +90 -0
- package/src/database/drivers/pgsql/columns-index.js +6 -0
- package/src/database/drivers/pgsql/foreign-key.js +12 -0
- package/src/database/drivers/pgsql/index.js +441 -0
- package/src/database/drivers/pgsql/options.js +32 -0
- package/src/database/drivers/pgsql/query-parser.js +6 -0
- package/src/database/drivers/pgsql/sql/alter-table.js +6 -0
- package/src/database/drivers/pgsql/sql/create-database.js +38 -0
- package/src/database/drivers/pgsql/sql/create-index.js +6 -0
- package/src/database/drivers/pgsql/sql/create-table.js +6 -0
- package/src/database/drivers/pgsql/sql/delete.js +21 -0
- package/src/database/drivers/pgsql/sql/drop-database.js +6 -0
- package/src/database/drivers/pgsql/sql/drop-table.js +6 -0
- package/src/database/drivers/pgsql/sql/insert.js +6 -0
- package/src/database/drivers/pgsql/sql/update.js +33 -0
- package/src/database/drivers/pgsql/sql/upsert.js +14 -0
- package/src/database/drivers/pgsql/structure-sql.js +126 -0
- package/src/database/drivers/pgsql/table.js +135 -0
- package/src/database/drivers/sqlite/base.js +509 -0
- package/src/database/drivers/sqlite/column.js +75 -0
- package/src/database/drivers/sqlite/columns-index.js +30 -0
- package/src/database/drivers/sqlite/connection-sql-js.js +46 -0
- package/src/database/drivers/sqlite/foreign-key.js +24 -0
- package/src/database/drivers/sqlite/index.js +394 -0
- package/src/database/drivers/sqlite/index.native.js +72 -0
- package/src/database/drivers/sqlite/index.web.js +99 -0
- package/src/database/drivers/sqlite/options.js +32 -0
- package/src/database/drivers/sqlite/query-parser.js +6 -0
- package/src/database/drivers/sqlite/query.js +35 -0
- package/src/database/drivers/sqlite/query.native.js +35 -0
- package/src/database/drivers/sqlite/query.web.js +49 -0
- package/src/database/drivers/sqlite/sql/alter-table.js +187 -0
- package/src/database/drivers/sqlite/sql/create-index.js +6 -0
- package/src/database/drivers/sqlite/sql/create-table.js +6 -0
- package/src/database/drivers/sqlite/sql/delete.js +26 -0
- package/src/database/drivers/sqlite/sql/drop-table.js +6 -0
- package/src/database/drivers/sqlite/sql/insert.js +6 -0
- package/src/database/drivers/sqlite/sql/update.js +33 -0
- package/src/database/drivers/sqlite/sql/upsert.js +14 -0
- package/src/database/drivers/sqlite/structure-sql.js +56 -0
- package/src/database/drivers/sqlite/table-rebuilder.js +96 -0
- package/src/database/drivers/sqlite/table.js +131 -0
- package/src/database/drivers/structure-sql/utils.js +35 -0
- package/src/database/handler.js +13 -0
- package/src/database/initializer-from-require-context.js +101 -0
- package/src/database/migration/index.js +438 -0
- package/src/database/migrator/files-finder.js +55 -0
- package/src/database/migrator/types.js +31 -0
- package/src/database/migrator.js +557 -0
- package/src/database/pool/async-tracked-multi-connection.js +1164 -0
- package/src/database/pool/base-methods-forward.js +52 -0
- package/src/database/pool/base.js +380 -0
- package/src/database/pool/single-multi-use.js +118 -0
- package/src/database/query/alter-table-base.js +104 -0
- package/src/database/query/base.js +49 -0
- package/src/database/query/create-database-base.js +42 -0
- package/src/database/query/create-index-base.js +117 -0
- package/src/database/query/create-table-base.js +205 -0
- package/src/database/query/delete-base.js +19 -0
- package/src/database/query/drop-database-base.js +38 -0
- package/src/database/query/drop-table-base.js +58 -0
- package/src/database/query/from-base.js +36 -0
- package/src/database/query/from-plain.js +16 -0
- package/src/database/query/from-table.js +18 -0
- package/src/database/query/index.js +533 -0
- package/src/database/query/insert-base.js +172 -0
- package/src/database/query/join-base.js +43 -0
- package/src/database/query/join-object.js +167 -0
- package/src/database/query/join-plain.js +18 -0
- package/src/database/query/join-tracker.js +93 -0
- package/src/database/query/model-class-query.js +1577 -0
- package/src/database/query/order-base.js +33 -0
- package/src/database/query/order-column.js +77 -0
- package/src/database/query/order-plain.js +28 -0
- package/src/database/query/preloader/belongs-to.js +267 -0
- package/src/database/query/preloader/ensure-model-class-initialized.js +18 -0
- package/src/database/query/preloader/has-many.js +316 -0
- package/src/database/query/preloader/has-one.js +123 -0
- package/src/database/query/preloader/selection.js +152 -0
- package/src/database/query/preloader.js +201 -0
- package/src/database/query/query-data.js +305 -0
- package/src/database/query/select-base.js +30 -0
- package/src/database/query/select-plain.js +18 -0
- package/src/database/query/select-table-and-column.js +28 -0
- package/src/database/query/update-base.js +41 -0
- package/src/database/query/upsert-base.js +103 -0
- package/src/database/query/where-base.js +38 -0
- package/src/database/query/where-combinator.js +31 -0
- package/src/database/query/where-hash.js +77 -0
- package/src/database/query/where-model-class-hash.js +505 -0
- package/src/database/query/where-not.js +23 -0
- package/src/database/query/where-plain.js +20 -0
- package/src/database/query/with-count.js +219 -0
- package/src/database/query-parser/base-query-parser.js +40 -0
- package/src/database/query-parser/from-parser.js +49 -0
- package/src/database/query-parser/group-parser.js +55 -0
- package/src/database/query-parser/joins-parser.js +37 -0
- package/src/database/query-parser/limit-parser.js +77 -0
- package/src/database/query-parser/options.js +94 -0
- package/src/database/query-parser/order-parser.js +45 -0
- package/src/database/query-parser/select-parser.js +67 -0
- package/src/database/query-parser/where-parser.js +46 -0
- package/src/database/record/acts-as-list.js +374 -0
- package/src/database/record/attachments/download.js +49 -0
- package/src/database/record/attachments/handle.js +188 -0
- package/src/database/record/attachments/normalize-input.js +213 -0
- package/src/database/record/attachments/storage-drivers/filesystem.js +114 -0
- package/src/database/record/attachments/storage-drivers/native.js +146 -0
- package/src/database/record/attachments/storage-drivers/s3.js +245 -0
- package/src/database/record/attachments/store.js +591 -0
- package/src/database/record/index.js +4094 -0
- package/src/database/record/instance-relationships/base.js +289 -0
- package/src/database/record/instance-relationships/belongs-to.js +84 -0
- package/src/database/record/instance-relationships/has-many.js +284 -0
- package/src/database/record/instance-relationships/has-one.js +117 -0
- package/src/database/record/record-not-found-error.js +3 -0
- package/src/database/record/relationships/base.js +195 -0
- package/src/database/record/relationships/belongs-to.js +57 -0
- package/src/database/record/relationships/has-many.js +46 -0
- package/src/database/record/relationships/has-one.js +46 -0
- package/src/database/record/state-machine.js +278 -0
- package/src/database/record/user-module.js +43 -0
- package/src/database/record/validators/base.js +27 -0
- package/src/database/record/validators/format.js +50 -0
- package/src/database/record/validators/presence.js +24 -0
- package/src/database/record/validators/uniqueness.js +124 -0
- package/src/database/table-data/index.js +241 -0
- package/src/database/table-data/table-column.js +416 -0
- package/src/database/table-data/table-foreign-key.js +69 -0
- package/src/database/table-data/table-index.js +46 -0
- package/src/database/table-data/table-reference.js +13 -0
- package/src/database/use-database.js +48 -0
- package/src/environment-handlers/base.js +561 -0
- package/src/environment-handlers/browser.js +338 -0
- package/src/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
- package/src/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
- package/src/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
- package/src/environment-handlers/node/cli/commands/beacon.js +21 -0
- package/src/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
- package/src/environment-handlers/node/cli/commands/console.js +149 -0
- package/src/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
- package/src/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
- package/src/environment-handlers/node/cli/commands/db/seed.js +79 -0
- package/src/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
- package/src/environment-handlers/node/cli/commands/generate/base-models.js +396 -0
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
- package/src/environment-handlers/node/cli/commands/generate/migration.js +45 -0
- package/src/environment-handlers/node/cli/commands/generate/model.js +45 -0
- package/src/environment-handlers/node/cli/commands/init.js +68 -0
- package/src/environment-handlers/node/cli/commands/routes.js +63 -0
- package/src/environment-handlers/node/cli/commands/run-script.js +85 -0
- package/src/environment-handlers/node/cli/commands/runner.js +84 -0
- package/src/environment-handlers/node/cli/commands/server.js +151 -0
- package/src/environment-handlers/node/cli/commands/test.js +118 -0
- package/src/environment-handlers/node.js +887 -0
- package/src/error-logger.js +30 -0
- package/src/frontend-model-controller.js +3491 -0
- package/src/frontend-model-resource/base-resource.js +935 -0
- package/src/frontend-models/base.js +4004 -0
- package/src/frontend-models/clear-pending-debounced-callback.js +16 -0
- package/src/frontend-models/event-hook-models.js +49 -0
- package/src/frontend-models/model-registry.js +28 -0
- package/src/frontend-models/outgoing-event-buffer.js +51 -0
- package/src/frontend-models/preloader.js +169 -0
- package/src/frontend-models/query.js +2245 -0
- package/src/frontend-models/resource-config-validation.js +56 -0
- package/src/frontend-models/resource-definition.js +399 -0
- package/src/frontend-models/transport-serialization.js +369 -0
- package/src/frontend-models/use-created-event.js +21 -0
- package/src/frontend-models/use-destroyed-event.js +148 -0
- package/src/frontend-models/use-model-class-event.js +164 -0
- package/src/frontend-models/use-updated-event.js +152 -0
- package/src/frontend-models/websocket-channel.js +494 -0
- package/src/frontend-models/websocket-publishers.js +224 -0
- package/src/http-client/header.js +17 -0
- package/src/http-client/index.js +139 -0
- package/src/http-client/request.js +94 -0
- package/src/http-client/response.js +151 -0
- package/src/http-client/websocket-client.js +27 -0
- package/src/http-server/client/index.js +507 -0
- package/src/http-server/client/params-to-object.js +152 -0
- package/src/http-server/client/request-buffer/form-data-part.js +139 -0
- package/src/http-server/client/request-buffer/header.js +19 -0
- package/src/http-server/client/request-buffer/index.js +535 -0
- package/src/http-server/client/request-parser.js +195 -0
- package/src/http-server/client/request-runner.js +321 -0
- package/src/http-server/client/request-timing.js +171 -0
- package/src/http-server/client/request.js +114 -0
- package/src/http-server/client/response.js +251 -0
- package/src/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
- package/src/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
- package/src/http-server/client/uploaded-file/uploaded-file.js +36 -0
- package/src/http-server/client/websocket-request.js +147 -0
- package/src/http-server/client/websocket-session.js +1755 -0
- package/src/http-server/cookie.js +245 -0
- package/src/http-server/development-reloader.js +240 -0
- package/src/http-server/index.js +561 -0
- package/src/http-server/remote-address.js +77 -0
- package/src/http-server/server-client.js +222 -0
- package/src/http-server/server-lock.js +178 -0
- package/src/http-server/websocket-channel-subscribers.js +110 -0
- package/src/http-server/websocket-channel.js +137 -0
- package/src/http-server/websocket-connection.js +118 -0
- package/src/http-server/websocket-event-log-store.js +433 -0
- package/src/http-server/websocket-events-host.js +170 -0
- package/src/http-server/websocket-events.js +50 -0
- package/src/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
- package/src/http-server/worker-handler/in-process.js +155 -0
- package/src/http-server/worker-handler/index.js +370 -0
- package/src/http-server/worker-handler/worker-script.js +6 -0
- package/src/http-server/worker-handler/worker-thread.js +286 -0
- package/src/initializer.js +39 -0
- package/src/jobs/.gitkeep +1 -0
- package/src/jobs/mail-delivery.js +22 -0
- package/src/logger/base-logger.js +34 -0
- package/src/logger/console-logger.js +28 -0
- package/src/logger/file-logger.js +36 -0
- package/src/logger/outputs/array-output.js +50 -0
- package/src/logger/outputs/console-output.js +32 -0
- package/src/logger/outputs/file-output.js +55 -0
- package/src/logger/outputs/stdout-output.js +64 -0
- package/src/logger.js +507 -0
- package/src/mailer/backends/smtp.js +197 -0
- package/src/mailer/base.js +337 -0
- package/src/mailer/delivery.js +70 -0
- package/src/mailer/index.js +24 -0
- package/src/mailer.js +15 -0
- package/src/plugins/sqljs-wasm-route-controller.js +70 -0
- package/src/plugins/sqljs-wasm-route.js +71 -0
- package/src/record-payload-values.js +83 -0
- package/src/routes/app-routes.js +17 -0
- package/src/routes/base-route.js +133 -0
- package/src/routes/basic-route.js +109 -0
- package/src/routes/built-in/debug/controller.js +12 -0
- package/src/routes/built-in/errors/controller.js +7 -0
- package/src/routes/built-in/errors/not-found.ejs +1 -0
- package/src/routes/get-route.js +75 -0
- package/src/routes/hooks/frontend-model-command-route-hook.js +100 -0
- package/src/routes/index.js +50 -0
- package/src/routes/namespace-route.js +51 -0
- package/src/routes/plugin-routes.js +141 -0
- package/src/routes/post-route.js +74 -0
- package/src/routes/resolver.js +535 -0
- package/src/routes/resource-route.js +154 -0
- package/src/routes/root-route.js +11 -0
- package/src/templates/configuration.js +61 -0
- package/src/templates/generate-migration.js +11 -0
- package/src/templates/generate-model.js +6 -0
- package/src/templates/routes.js +11 -0
- package/src/testing/base-expect.js +17 -0
- package/src/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
- package/src/testing/browser-test-app.js +32 -0
- package/src/testing/expect-to-change.js +55 -0
- package/src/testing/expect-utils.js +269 -0
- package/src/testing/expect.js +763 -0
- package/src/testing/request-client.js +90 -0
- package/src/testing/test-files-finder.js +364 -0
- package/src/testing/test-filter-parser.js +198 -0
- package/src/testing/test-runner.js +1168 -0
- package/src/testing/test-suite-splitter.js +177 -0
- package/src/testing/test.js +370 -0
- package/src/types/external-modules.d.ts +57 -0
- package/src/utils/backtrace-cleaner-node.js +87 -0
- package/src/utils/backtrace-cleaner.js +266 -0
- package/src/utils/ensure-error.js +15 -0
- package/src/utils/event-emitter.js +8 -0
- package/src/utils/file-exists.js +18 -0
- package/src/utils/format-value.js +101 -0
- package/src/utils/model-scope.js +56 -0
- package/src/utils/nest-callbacks.js +22 -0
- package/src/utils/plain-object.js +14 -0
- package/src/utils/ransack.js +859 -0
- package/src/utils/rest-args-error.js +14 -0
- package/src/utils/singularize-model-name.js +18 -0
- package/src/utils/split-sql-statements.js +88 -0
- package/src/utils/to-import-specifier.js +53 -0
- package/src/utils/with-tracked-stack-async-hooks.js +103 -0
- package/src/utils/with-tracked-stack.js +38 -0
- package/src/velocious-error.js +34 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,926 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import net from "net"
|
|
4
|
+
import JsonSocket from "./json-socket.js"
|
|
5
|
+
import BackgroundJobsScheduler from "./scheduler.js"
|
|
6
|
+
import BackgroundJobsStore from "./store.js"
|
|
7
|
+
import Logger from "../logger.js"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Channel used by `background-jobs-main` to coordinate dispatch wake-ups
|
|
11
|
+
* across processes via Beacon. Workers do NOT subscribe to this channel
|
|
12
|
+
* — they already receive job-handoff messages on their JsonSocket to
|
|
13
|
+
* main; this channel exists so cross-process enqueues (or future
|
|
14
|
+
* multi-main deployments) can poke an idle main to drain.
|
|
15
|
+
*/
|
|
16
|
+
const DISPATCH_CHANNEL = "velocious-background-jobs-dispatch"
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* `setTimeout` is implemented with 32-bit signed delays on Node; passing
|
|
20
|
+
* anything larger silently clamps to 1ms and fires immediately. Cap the
|
|
21
|
+
* scheduled-job timer here and re-arm when it expires.
|
|
22
|
+
*/
|
|
23
|
+
const MAX_TIMER_MS = 2_147_483_647 // ~24.8 days
|
|
24
|
+
/**
|
|
25
|
+
* WorkerExecutionModeCapability type.
|
|
26
|
+
* @typedef {object} WorkerExecutionModeCapability
|
|
27
|
+
* @property {import("./types.js").BackgroundJobExecutionMode} executionMode - Execution mode.
|
|
28
|
+
* @property {(worker: JsonSocket) => boolean} accepts - Whether the worker accepts this mode.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Worker execution mode capabilities.
|
|
32
|
+
@type {WorkerExecutionModeCapability[]} */
|
|
33
|
+
const WORKER_EXECUTION_MODE_CAPABILITIES = [
|
|
34
|
+
{executionMode: "inline", accepts: (worker) => worker.acceptsInlineJobs !== false},
|
|
35
|
+
{executionMode: "forked", accepts: (worker) => worker.acceptsForkedJobs !== false},
|
|
36
|
+
{executionMode: "spawned", accepts: (worker) => worker.acceptsSpawnedJobs !== false}
|
|
37
|
+
]
|
|
38
|
+
const WORKER_EXECUTION_MODE_CAPABILITIES_BY_MODE = new Map(
|
|
39
|
+
WORKER_EXECUTION_MODE_CAPABILITIES.map((capability) => [capability.executionMode, capability])
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
export default class BackgroundJobsMain {
|
|
43
|
+
/**
|
|
44
|
+
* Runs constructor.
|
|
45
|
+
* @param {object} args - Options.
|
|
46
|
+
* @param {import("../configuration.js").default} args.configuration - Configuration.
|
|
47
|
+
* @param {string} [args.host] - Hostname.
|
|
48
|
+
* @param {number} [args.port] - Port.
|
|
49
|
+
*/
|
|
50
|
+
constructor({configuration, host, port}) {
|
|
51
|
+
this.configuration = configuration
|
|
52
|
+
const config = configuration.getBackgroundJobsConfig()
|
|
53
|
+
this.host = host || config.host
|
|
54
|
+
this.port = typeof port === "number" ? port : config.port
|
|
55
|
+
this.dispatchStrategy = config.dispatchStrategy
|
|
56
|
+
this.pollIntervalMs = config.pollIntervalMs
|
|
57
|
+
this.store = new BackgroundJobsStore({configuration, databaseIdentifier: config.databaseIdentifier})
|
|
58
|
+
this.logger = new Logger(this)
|
|
59
|
+
/**
|
|
60
|
+
* Narrows the runtime value to the documented type.
|
|
61
|
+
@type {Set<JsonSocket>} */
|
|
62
|
+
this.workers = new Set()
|
|
63
|
+
/**
|
|
64
|
+
* Narrows the runtime value to the documented type.
|
|
65
|
+
@type {Set<JsonSocket>} */
|
|
66
|
+
this.readyWorkers = new Set()
|
|
67
|
+
/**
|
|
68
|
+
* Narrows the runtime value to the documented type.
|
|
69
|
+
@type {net.Server | undefined} */
|
|
70
|
+
this.server = undefined
|
|
71
|
+
/**
|
|
72
|
+
* Narrows the runtime value to the documented type.
|
|
73
|
+
@type {NodeJS.Timeout | undefined} */
|
|
74
|
+
this._pollTimer = undefined
|
|
75
|
+
/**
|
|
76
|
+
* Narrows the runtime value to the documented type.
|
|
77
|
+
@type {NodeJS.Timeout | undefined} */
|
|
78
|
+
this._scheduledTimer = undefined
|
|
79
|
+
/**
|
|
80
|
+
* Narrows the runtime value to the documented type.
|
|
81
|
+
@type {NodeJS.Timeout | undefined} */
|
|
82
|
+
this._errorRetryTimer = undefined
|
|
83
|
+
/**
|
|
84
|
+
* Narrows the runtime value to the documented type.
|
|
85
|
+
@type {NodeJS.Timeout | undefined} */
|
|
86
|
+
this._orphanTimer = undefined
|
|
87
|
+
/**
|
|
88
|
+
* Narrows the runtime value to the documented type.
|
|
89
|
+
@type {BackgroundJobsScheduler | undefined} */
|
|
90
|
+
this.scheduler = undefined
|
|
91
|
+
this._draining = false
|
|
92
|
+
this._redrainQueued = false
|
|
93
|
+
this._stopped = false
|
|
94
|
+
/**
|
|
95
|
+
* Narrows the runtime value to the documented type.
|
|
96
|
+
@type {(() => void) | undefined} */
|
|
97
|
+
this._unsubscribeBeacon = undefined
|
|
98
|
+
/**
|
|
99
|
+
* Narrows the runtime value to the documented type.
|
|
100
|
+
@type {((...args: Array<?>) => void) | undefined} */
|
|
101
|
+
this._beaconConnectHandler = undefined
|
|
102
|
+
/**
|
|
103
|
+
* Narrows the runtime value to the documented type.
|
|
104
|
+
@type {import("../beacon/client.js").default | import("../beacon/in-process-client.js").default | undefined} */
|
|
105
|
+
this._beaconClient = undefined
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Runs start.
|
|
110
|
+
* @returns {Promise<void>} - Resolves when listening.
|
|
111
|
+
*/
|
|
112
|
+
async start() {
|
|
113
|
+
this._stopped = false
|
|
114
|
+
this.configuration.setCurrent()
|
|
115
|
+
await this.configuration.initialize({type: "background-jobs-main"})
|
|
116
|
+
await this.configuration.connectBeacon({peerType: "background-jobs-main"})
|
|
117
|
+
await this.store.ensureReady()
|
|
118
|
+
const server = net.createServer((socket) => this._handleConnection(socket))
|
|
119
|
+
this.server = server
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
await new Promise((resolve, reject) => {
|
|
123
|
+
server.once("error", reject)
|
|
124
|
+
server.listen(this.port, this.host, () => resolve(undefined))
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const address = server.address()
|
|
128
|
+
if (address && typeof address === "object") {
|
|
129
|
+
this.port = address.port
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this._setupDispatchTriggers()
|
|
133
|
+
|
|
134
|
+
this._orphanTimer = setInterval(() => {
|
|
135
|
+
void this._sweepOrphans()
|
|
136
|
+
}, 60000)
|
|
137
|
+
|
|
138
|
+
this.scheduler = new BackgroundJobsScheduler({
|
|
139
|
+
configuration: this.configuration,
|
|
140
|
+
enqueueJob: async ({args, jobClass, options}) => {
|
|
141
|
+
await this.store.enqueue({
|
|
142
|
+
jobName: jobClass.jobName(),
|
|
143
|
+
args,
|
|
144
|
+
options
|
|
145
|
+
})
|
|
146
|
+
this._notifyEnqueued()
|
|
147
|
+
await this._drain()
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
await this.scheduler.start()
|
|
151
|
+
|
|
152
|
+
// Startup catch-up: drain anything that was waiting before this
|
|
153
|
+
// process came up. In beacon mode this is also the safety net for
|
|
154
|
+
// races between attaching the connect listener and the initial
|
|
155
|
+
// connect firing (the listener could miss the very first connect,
|
|
156
|
+
// but this drain covers it).
|
|
157
|
+
await this._drain()
|
|
158
|
+
} catch (error) {
|
|
159
|
+
await this.stop()
|
|
160
|
+
throw error
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Runs stop.
|
|
166
|
+
* @returns {Promise<void>} - Resolves when closed.
|
|
167
|
+
*/
|
|
168
|
+
async stop() {
|
|
169
|
+
this._stopped = true
|
|
170
|
+
|
|
171
|
+
this._closeWorkers()
|
|
172
|
+
this._clearTimers()
|
|
173
|
+
this._disconnectBeaconHandlers()
|
|
174
|
+
this.scheduler?.stop()
|
|
175
|
+
|
|
176
|
+
await this._stopBeaconAndServer()
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Runs close workers.
|
|
181
|
+
@returns {void} */
|
|
182
|
+
_closeWorkers() {
|
|
183
|
+
for (const worker of this.workers) {
|
|
184
|
+
worker.close()
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Runs clear timers.
|
|
190
|
+
@returns {void} */
|
|
191
|
+
_clearTimers() {
|
|
192
|
+
if (this._pollTimer) clearInterval(this._pollTimer)
|
|
193
|
+
if (this._scheduledTimer) clearTimeout(this._scheduledTimer)
|
|
194
|
+
if (this._errorRetryTimer) clearTimeout(this._errorRetryTimer)
|
|
195
|
+
if (this._orphanTimer) clearInterval(this._orphanTimer)
|
|
196
|
+
this._pollTimer = undefined
|
|
197
|
+
this._scheduledTimer = undefined
|
|
198
|
+
this._errorRetryTimer = undefined
|
|
199
|
+
this._orphanTimer = undefined
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Runs disconnect beacon handlers.
|
|
204
|
+
@returns {void} */
|
|
205
|
+
_disconnectBeaconHandlers() {
|
|
206
|
+
if (this._unsubscribeBeacon) {
|
|
207
|
+
this._unsubscribeBeacon()
|
|
208
|
+
this._unsubscribeBeacon = undefined
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (this._beaconClient && this._beaconConnectHandler) {
|
|
212
|
+
this._beaconClient.off("connect", this._beaconConnectHandler)
|
|
213
|
+
}
|
|
214
|
+
this._beaconConnectHandler = undefined
|
|
215
|
+
this._beaconClient = undefined
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Runs stop beacon and server.
|
|
220
|
+
@returns {Promise<void>} */
|
|
221
|
+
async _stopBeaconAndServer() {
|
|
222
|
+
try {
|
|
223
|
+
await this.configuration.disconnectBeacon()
|
|
224
|
+
} finally {
|
|
225
|
+
await this._closeServerAndDatabaseConnections()
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Runs close server and database connections.
|
|
231
|
+
@returns {Promise<void>} */
|
|
232
|
+
async _closeServerAndDatabaseConnections() {
|
|
233
|
+
try {
|
|
234
|
+
await this._closeServer()
|
|
235
|
+
} finally {
|
|
236
|
+
await this.configuration.closeDatabaseConnections()
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Runs close server.
|
|
242
|
+
@returns {Promise<void>} */
|
|
243
|
+
async _closeServer() {
|
|
244
|
+
if (!this.server) return
|
|
245
|
+
|
|
246
|
+
const {server} = this
|
|
247
|
+
this.server = undefined
|
|
248
|
+
await new Promise((resolve) => server.close(() => resolve(undefined)))
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Runs get port.
|
|
253
|
+
* @returns {number} - Bound port.
|
|
254
|
+
*/
|
|
255
|
+
getPort() {
|
|
256
|
+
return this.port
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Wires up the dispatch-triggering signal sources for the configured
|
|
261
|
+
* strategy. In `"beacon"` mode (default) this means subscribing to the
|
|
262
|
+
* `velocious-background-jobs-dispatch` channel for cross-process
|
|
263
|
+
* wake-ups, listening for Beacon (re)connects to catch up on missed
|
|
264
|
+
* work, and relying on direct in-process calls from `_handleEnqueue`,
|
|
265
|
+
* `_handleJobComplete`/`Failed`, worker hello/ready, and the
|
|
266
|
+
* scheduled-job `setTimeout`. In `"polling"` mode we restore the
|
|
267
|
+
* legacy fixed-interval poll for users who want the previous behavior.
|
|
268
|
+
* @returns {void}
|
|
269
|
+
*/
|
|
270
|
+
_setupDispatchTriggers() {
|
|
271
|
+
if (this.dispatchStrategy === "polling") {
|
|
272
|
+
this._pollTimer = setInterval(() => {
|
|
273
|
+
void this._drain()
|
|
274
|
+
}, this.pollIntervalMs)
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const beaconClient = this.configuration.getBeaconClient()
|
|
279
|
+
if (!beaconClient) return
|
|
280
|
+
|
|
281
|
+
this._beaconClient = beaconClient
|
|
282
|
+
|
|
283
|
+
this._unsubscribeBeacon = beaconClient.onBroadcast((message) => {
|
|
284
|
+
if (message?.channel !== DISPATCH_CHANNEL) return
|
|
285
|
+
void this._drain()
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
// Drain on every (re)connect to catch up on jobs enqueued while the
|
|
289
|
+
// bus was unreachable. The DB is the durable log; Beacon is just the
|
|
290
|
+
// wake-up signal.
|
|
291
|
+
this._beaconConnectHandler = () => {
|
|
292
|
+
void this._drain()
|
|
293
|
+
}
|
|
294
|
+
beaconClient.on("connect", this._beaconConnectHandler)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Publishes a dispatch wake-up on the Beacon channel. No-op in polling
|
|
299
|
+
* mode or when Beacon is not connected; in those cases the direct
|
|
300
|
+
* in-process `_drain()` call in the enqueue/handle paths is sufficient
|
|
301
|
+
* (there are no other processes to notify).
|
|
302
|
+
* @returns {void}
|
|
303
|
+
*/
|
|
304
|
+
_notifyEnqueued() {
|
|
305
|
+
if (this.dispatchStrategy === "polling") return
|
|
306
|
+
|
|
307
|
+
const beaconClient = this.configuration.getBeaconClient()
|
|
308
|
+
if (!beaconClient || !beaconClient.isConnected()) return
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
beaconClient.publish({
|
|
312
|
+
channel: DISPATCH_CHANNEL,
|
|
313
|
+
broadcastParams: {},
|
|
314
|
+
body: {action: "wake"}
|
|
315
|
+
})
|
|
316
|
+
} catch (error) {
|
|
317
|
+
this.logger.warn(() => ["Failed to publish background jobs wake broadcast:", error])
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Runs handle connection.
|
|
323
|
+
* @param {import("net").Socket} socket - Socket.
|
|
324
|
+
* @returns {void}
|
|
325
|
+
*/
|
|
326
|
+
_handleConnection(socket) {
|
|
327
|
+
const jsonSocket = new JsonSocket(socket)
|
|
328
|
+
/**
|
|
329
|
+
* Role.
|
|
330
|
+
@type {import("./types.js").BackgroundJobSocketRole | null} */
|
|
331
|
+
let role = null
|
|
332
|
+
|
|
333
|
+
const cleanup = () => {
|
|
334
|
+
if (role === "worker") {
|
|
335
|
+
this.workers.delete(jsonSocket)
|
|
336
|
+
this.readyWorkers.delete(jsonSocket)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
jsonSocket.on("close", cleanup)
|
|
341
|
+
jsonSocket.on("error", (error) => {
|
|
342
|
+
this.logger.warn(() => ["Background jobs connection error:", error])
|
|
343
|
+
cleanup()
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
jsonSocket.on("message", (message) => {
|
|
347
|
+
role = this._handleSocketMessage({jsonSocket, message, role})
|
|
348
|
+
})
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Runs handle socket message.
|
|
353
|
+
* @param {object} args - Options.
|
|
354
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
355
|
+
* @param {import("./types.js").BackgroundJobSocketMessage} args.message - Socket message.
|
|
356
|
+
* @param {import("./types.js").BackgroundJobSocketRole | null} args.role - Current socket role.
|
|
357
|
+
* @returns {import("./types.js").BackgroundJobSocketRole | null} - Updated socket role.
|
|
358
|
+
*/
|
|
359
|
+
_handleSocketMessage({jsonSocket, message, role}) {
|
|
360
|
+
if (!role) return this._handleRolelessSocketMessage({jsonSocket, message})
|
|
361
|
+
if (role === "client") this._handleClientSocketMessage({jsonSocket, message})
|
|
362
|
+
if (role === "worker") this._handleWorkerSocketMessage({jsonSocket, message})
|
|
363
|
+
if (role === "reporter") this._handleReporterSocketMessage({jsonSocket, message})
|
|
364
|
+
|
|
365
|
+
return role
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Runs handle roleless socket message.
|
|
370
|
+
* @param {object} args - Options.
|
|
371
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
372
|
+
* @param {import("./types.js").BackgroundJobSocketMessage} args.message - Socket message.
|
|
373
|
+
* @returns {import("./types.js").BackgroundJobSocketRole | null} - New socket role.
|
|
374
|
+
*/
|
|
375
|
+
_handleRolelessSocketMessage({jsonSocket, message}) {
|
|
376
|
+
if (message?.type !== "hello") return null
|
|
377
|
+
|
|
378
|
+
if (message.role === "worker") {
|
|
379
|
+
jsonSocket.workerId = message.workerId
|
|
380
|
+
this.workers.add(jsonSocket)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return message.role
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Runs handle client socket message.
|
|
388
|
+
* @param {object} args - Options.
|
|
389
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
390
|
+
* @param {import("./types.js").BackgroundJobSocketMessage} args.message - Socket message.
|
|
391
|
+
* @returns {void}
|
|
392
|
+
*/
|
|
393
|
+
_handleClientSocketMessage({jsonSocket, message}) {
|
|
394
|
+
if (message?.type === "enqueue") {
|
|
395
|
+
this._handleEnqueue({jsonSocket, message})
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Runs handle worker socket message.
|
|
401
|
+
* @param {object} args - Options.
|
|
402
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
403
|
+
* @param {import("./types.js").BackgroundJobSocketMessage} args.message - Socket message.
|
|
404
|
+
* @returns {void}
|
|
405
|
+
*/
|
|
406
|
+
_handleWorkerSocketMessage({jsonSocket, message}) {
|
|
407
|
+
if (message?.type === "ready") {
|
|
408
|
+
this._handleWorkerReady({jsonSocket, message})
|
|
409
|
+
return
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (message?.type === "draining") {
|
|
413
|
+
this._handleWorkerDraining({jsonSocket})
|
|
414
|
+
return
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
this._handleReporterSocketMessage({jsonSocket, message})
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Runs handle reporter socket message.
|
|
422
|
+
* @param {object} args - Options.
|
|
423
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
424
|
+
* @param {import("./types.js").BackgroundJobSocketMessage} args.message - Socket message.
|
|
425
|
+
* @returns {void}
|
|
426
|
+
*/
|
|
427
|
+
_handleReporterSocketMessage({jsonSocket, message}) {
|
|
428
|
+
if (message?.type === "job-complete") {
|
|
429
|
+
this._handleJobComplete({jsonSocket, message})
|
|
430
|
+
return
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (message?.type === "job-failed") {
|
|
434
|
+
this._handleJobFailed({jsonSocket, message})
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Runs handle worker ready.
|
|
440
|
+
* @param {object} args - Options.
|
|
441
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
442
|
+
* @param {import("./types.js").BackgroundJobReadyMessage} args.message - Ready message.
|
|
443
|
+
* @returns {void}
|
|
444
|
+
*/
|
|
445
|
+
_handleWorkerReady({jsonSocket, message}) {
|
|
446
|
+
jsonSocket.acceptsSpawnedJobs = message.acceptsSpawned !== false && message.acceptsForked !== false
|
|
447
|
+
jsonSocket.acceptsForkedJobs = message.acceptsForked !== false
|
|
448
|
+
jsonSocket.acceptsInlineJobs = message.acceptsInline !== false
|
|
449
|
+
this.readyWorkers.add(jsonSocket)
|
|
450
|
+
void this._drain()
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Runs handle worker draining.
|
|
455
|
+
* @param {object} args - Options.
|
|
456
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
457
|
+
* @returns {void}
|
|
458
|
+
*/
|
|
459
|
+
_handleWorkerDraining({jsonSocket}) {
|
|
460
|
+
// The worker is shutting down gracefully. Stop dispatching new jobs
|
|
461
|
+
// to it but keep the connection in `workers` so any in-flight job
|
|
462
|
+
// it's still draining can report its result.
|
|
463
|
+
this.readyWorkers.delete(jsonSocket)
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Runs handle enqueue.
|
|
468
|
+
* @param {object} args - Options.
|
|
469
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
470
|
+
* @param {import("./types.js").BackgroundJobEnqueueMessage} args.message - Message.
|
|
471
|
+
* @returns {Promise<void>} - Resolves when handled.
|
|
472
|
+
*/
|
|
473
|
+
async _handleEnqueue({jsonSocket, message}) {
|
|
474
|
+
try {
|
|
475
|
+
const jobId = await this.store.enqueue({
|
|
476
|
+
jobName: message.jobName,
|
|
477
|
+
args: message.args || [],
|
|
478
|
+
options: message.options || {}
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
jsonSocket.send({type: "enqueued", jobId})
|
|
482
|
+
this._notifyEnqueued()
|
|
483
|
+
await this._drain()
|
|
484
|
+
} catch (error) {
|
|
485
|
+
this.logger.error(() => ["Failed to enqueue background job:", error])
|
|
486
|
+
jsonSocket.send({type: "enqueue-error", error: "Failed to enqueue job"})
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Runs handle job complete.
|
|
492
|
+
* @param {object} args - Options.
|
|
493
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
494
|
+
* @param {import("./types.js").BackgroundJobCompleteMessage} args.message - Message.
|
|
495
|
+
* @returns {Promise<void>} - Resolves when handled.
|
|
496
|
+
*/
|
|
497
|
+
async _handleJobComplete({jsonSocket, message}) {
|
|
498
|
+
try {
|
|
499
|
+
await this.store.markCompleted({
|
|
500
|
+
jobId: message.jobId,
|
|
501
|
+
workerId: message.workerId,
|
|
502
|
+
handedOffAtMs: message.handedOffAtMs
|
|
503
|
+
})
|
|
504
|
+
jsonSocket.send({type: "job-updated", jobId: message.jobId})
|
|
505
|
+
} catch (error) {
|
|
506
|
+
this.logger.error(() => ["Failed to update job completion:", error])
|
|
507
|
+
jsonSocket.send({type: "job-update-error", jobId: message.jobId, error: "Failed to update job"})
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Runs handle job failed.
|
|
513
|
+
* @param {object} args - Options.
|
|
514
|
+
* @param {JsonSocket} args.jsonSocket - JSON socket.
|
|
515
|
+
* @param {import("./types.js").BackgroundJobFailedMessage} args.message - Message.
|
|
516
|
+
* @returns {Promise<void>} - Resolves when handled.
|
|
517
|
+
*/
|
|
518
|
+
async _handleJobFailed({jsonSocket, message}) {
|
|
519
|
+
try {
|
|
520
|
+
const failedJob = await this.store.markFailed({
|
|
521
|
+
jobId: message.jobId,
|
|
522
|
+
error: message.error,
|
|
523
|
+
workerId: message.workerId,
|
|
524
|
+
handedOffAtMs: message.handedOffAtMs
|
|
525
|
+
})
|
|
526
|
+
|
|
527
|
+
if (failedJob) {
|
|
528
|
+
this._emitBackgroundJobFailed({
|
|
529
|
+
error: message.error,
|
|
530
|
+
handedOffAtMs: message.handedOffAtMs,
|
|
531
|
+
job: failedJob,
|
|
532
|
+
workerId: message.workerId
|
|
533
|
+
})
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
jsonSocket.send({type: "job-updated", jobId: message.jobId})
|
|
537
|
+
// A failed job may have been re-queued (with backoff) for retry —
|
|
538
|
+
// poke the dispatcher so the retry timer is armed.
|
|
539
|
+
this._notifyEnqueued()
|
|
540
|
+
await this._drain()
|
|
541
|
+
} catch (error) {
|
|
542
|
+
this.logger.error(() => ["Failed to update job failure:", error])
|
|
543
|
+
jsonSocket.send({type: "job-update-error", jobId: message.jobId, error: "Failed to update job"})
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Runs emit background job failed.
|
|
549
|
+
* @param {{error: ?, handedOffAtMs?: number, job: import("./types.js").BackgroundJobRow, workerId?: string}} args - Failure event data.
|
|
550
|
+
* @returns {void}
|
|
551
|
+
*/
|
|
552
|
+
_emitBackgroundJobFailed({error, handedOffAtMs, job, workerId}) {
|
|
553
|
+
const normalizedError = this._normalizeFailureError(error)
|
|
554
|
+
const payload = {
|
|
555
|
+
context: {
|
|
556
|
+
attempts: job.attempts,
|
|
557
|
+
handedOffAtMs,
|
|
558
|
+
jobArgs: job.args,
|
|
559
|
+
jobId: job.id,
|
|
560
|
+
jobName: job.jobName,
|
|
561
|
+
maxRetries: job.maxRetries,
|
|
562
|
+
stage: "background-job-failed",
|
|
563
|
+
status: job.status,
|
|
564
|
+
terminal: job.status === "failed" || job.status === "orphaned",
|
|
565
|
+
willRetry: job.status === "queued",
|
|
566
|
+
workerId
|
|
567
|
+
},
|
|
568
|
+
error: normalizedError
|
|
569
|
+
}
|
|
570
|
+
const errorEvents = this.configuration.getErrorEvents()
|
|
571
|
+
|
|
572
|
+
errorEvents.emit("background-job-failed", payload)
|
|
573
|
+
errorEvents.emit("all-error", {...payload, errorType: "background-job-failed"})
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Runs normalize failure error.
|
|
578
|
+
* @param {?} error - Reported failure value.
|
|
579
|
+
* @returns {Error} Normalized error.
|
|
580
|
+
*/
|
|
581
|
+
_normalizeFailureError(error) {
|
|
582
|
+
if (error instanceof Error) return error
|
|
583
|
+
|
|
584
|
+
return this._errorFromUnknownFailure(error)
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Runs error from unknown failure.
|
|
589
|
+
* @param {?} error - Reported failure value.
|
|
590
|
+
* @returns {Error} Normalized error.
|
|
591
|
+
*/
|
|
592
|
+
_errorFromUnknownFailure(error) {
|
|
593
|
+
const message = this._messageFromUnknownFailure(error)
|
|
594
|
+
const normalizedError = new Error(message)
|
|
595
|
+
|
|
596
|
+
this._copyStringFailureStack({error, normalizedError})
|
|
597
|
+
|
|
598
|
+
return normalizedError
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Runs message from unknown failure.
|
|
603
|
+
* @param {?} error - Reported failure value.
|
|
604
|
+
* @returns {string} Error message.
|
|
605
|
+
*/
|
|
606
|
+
_messageFromUnknownFailure(error) {
|
|
607
|
+
if (this._hasStringFailure(error)) return error.trim().split("\n")[0]
|
|
608
|
+
|
|
609
|
+
return String(error || "Background job failed")
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Runs has string failure.
|
|
614
|
+
* @param {?} error - Reported failure value.
|
|
615
|
+
* @returns {error is string} Whether the value is a non-empty string.
|
|
616
|
+
*/
|
|
617
|
+
_hasStringFailure(error) {
|
|
618
|
+
return typeof error === "string" && error.trim().length > 0
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Runs copy string failure stack.
|
|
623
|
+
* @param {object} args - Options.
|
|
624
|
+
* @param {?} args.error - Reported failure value.
|
|
625
|
+
* @param {Error} args.normalizedError - Normalized error.
|
|
626
|
+
* @returns {void}
|
|
627
|
+
*/
|
|
628
|
+
_copyStringFailureStack({error, normalizedError}) {
|
|
629
|
+
if (this._hasStringFailure(error)) normalizedError.stack = error
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Drains all dispatchable jobs to ready workers, then arms the
|
|
634
|
+
* scheduled-job timer for the next future `scheduled_at_ms`. Coalesces
|
|
635
|
+
* concurrent triggers: a wake-up that lands while a drain is in
|
|
636
|
+
* flight just sets a re-drain flag and lets the in-flight drain
|
|
637
|
+
* re-loop after it finishes, so no signal is dropped but no two
|
|
638
|
+
* drains run in parallel.
|
|
639
|
+
*
|
|
640
|
+
* Resilience: in beacon mode this is the sole wake-up path for
|
|
641
|
+
* already-queued work, so a transient DB error during the drain (e.g.
|
|
642
|
+
* `nextAvailableJob()` rejecting) must not strand the queue until the
|
|
643
|
+
* next external signal. On any error we log it and arm a one-shot
|
|
644
|
+
* retry via `_scheduleErrorRetry` using `pollIntervalMs` as the
|
|
645
|
+
* cadence; on success the retry timer is cleared. Polling-mode runs
|
|
646
|
+
* `_drain` from its own interval, so the retry timer is a no-op there.
|
|
647
|
+
* @returns {Promise<void>}
|
|
648
|
+
*/
|
|
649
|
+
async _drain() {
|
|
650
|
+
if (!this._startDrain()) return
|
|
651
|
+
|
|
652
|
+
const errored = await this._drainUntilIdle()
|
|
653
|
+
|
|
654
|
+
await this._finishDrain({errored})
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Runs start drain.
|
|
659
|
+
* @returns {boolean} - Whether the drain should continue.
|
|
660
|
+
*/
|
|
661
|
+
_startDrain() {
|
|
662
|
+
if (this._stopped) return false
|
|
663
|
+
if (this._queueDrainIfAlreadyRunning()) return false
|
|
664
|
+
|
|
665
|
+
this._draining = true
|
|
666
|
+
return true
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Runs finish drain.
|
|
671
|
+
* @param {object} args - Options.
|
|
672
|
+
* @param {boolean} args.errored - Whether the drain hit an error.
|
|
673
|
+
* @returns {Promise<void>} - Resolves after follow-up timers are handled.
|
|
674
|
+
*/
|
|
675
|
+
async _finishDrain({errored}) {
|
|
676
|
+
if (this._stopped) return
|
|
677
|
+
if (errored) return this._scheduleErrorRetry()
|
|
678
|
+
|
|
679
|
+
await this._armScheduledTimerOrRetry()
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Runs arm scheduled timer or retry.
|
|
684
|
+
* @returns {Promise<void>} - Resolves after scheduled timer handling.
|
|
685
|
+
*/
|
|
686
|
+
async _armScheduledTimerOrRetry() {
|
|
687
|
+
try {
|
|
688
|
+
await this._armScheduledTimer()
|
|
689
|
+
} catch (error) {
|
|
690
|
+
this.logger.error(() => ["Background jobs scheduled-timer arming failed:", error])
|
|
691
|
+
this._scheduleErrorRetry()
|
|
692
|
+
return
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
this._clearErrorRetryTimer()
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Runs clear error retry timer.
|
|
700
|
+
@returns {void} */
|
|
701
|
+
_clearErrorRetryTimer() {
|
|
702
|
+
if (this._errorRetryTimer) {
|
|
703
|
+
clearTimeout(this._errorRetryTimer)
|
|
704
|
+
this._errorRetryTimer = undefined
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Runs queue drain if already running.
|
|
710
|
+
* @returns {boolean} - Whether another drain is already in progress.
|
|
711
|
+
*/
|
|
712
|
+
_queueDrainIfAlreadyRunning() {
|
|
713
|
+
if (!this._draining) return false
|
|
714
|
+
|
|
715
|
+
this._redrainQueued = true
|
|
716
|
+
return true
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Runs drain until idle.
|
|
721
|
+
* @returns {Promise<boolean>} - Whether the drain hit an error.
|
|
722
|
+
*/
|
|
723
|
+
async _drainUntilIdle() {
|
|
724
|
+
try {
|
|
725
|
+
return await this._runDrainLoop()
|
|
726
|
+
} finally {
|
|
727
|
+
this._draining = false
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Runs run drain loop.
|
|
733
|
+
* @returns {Promise<boolean>} - Whether the drain hit an error.
|
|
734
|
+
*/
|
|
735
|
+
async _runDrainLoop() {
|
|
736
|
+
do {
|
|
737
|
+
this._redrainQueued = false
|
|
738
|
+
const errored = await this._drainOnceWithErrorReport()
|
|
739
|
+
|
|
740
|
+
if (errored) return true
|
|
741
|
+
} while (this._redrainQueued && !this._stopped)
|
|
742
|
+
|
|
743
|
+
return false
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Runs drain once with error report.
|
|
748
|
+
* @returns {Promise<boolean>} - Whether one drain pass failed.
|
|
749
|
+
*/
|
|
750
|
+
async _drainOnceWithErrorReport() {
|
|
751
|
+
try {
|
|
752
|
+
await this._drainOnce()
|
|
753
|
+
return false
|
|
754
|
+
} catch (error) {
|
|
755
|
+
this.logger.error(() => ["Background jobs drain failed:", error])
|
|
756
|
+
return true
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Arms a one-shot `setTimeout` to retry `_drain` after a transient
|
|
762
|
+
* failure. Idempotent — repeated calls while a retry is already
|
|
763
|
+
* pending are no-ops. Polling mode already retries via its own
|
|
764
|
+
* interval, so this is a no-op in that mode.
|
|
765
|
+
* @returns {void}
|
|
766
|
+
*/
|
|
767
|
+
_scheduleErrorRetry() {
|
|
768
|
+
if (this._stopped) return
|
|
769
|
+
if (this._errorRetryTimer) return
|
|
770
|
+
if (this.dispatchStrategy === "polling") return
|
|
771
|
+
|
|
772
|
+
this._errorRetryTimer = setTimeout(() => {
|
|
773
|
+
this._errorRetryTimer = undefined
|
|
774
|
+
void this._drain()
|
|
775
|
+
}, this.pollIntervalMs)
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Inner drain loop: pulls eligible queued jobs and hands them off to
|
|
780
|
+
* ready workers until one of them runs out.
|
|
781
|
+
* @returns {Promise<void>}
|
|
782
|
+
*/
|
|
783
|
+
async _drainOnce() {
|
|
784
|
+
while (this.readyWorkers.size > 0 && !this._stopped) {
|
|
785
|
+
const job = await this.nextAvailableJobForReadyWorkers()
|
|
786
|
+
if (!job) return
|
|
787
|
+
|
|
788
|
+
const worker = this.readyWorkerForJob(job)
|
|
789
|
+
if (!worker) return
|
|
790
|
+
|
|
791
|
+
this.readyWorkers.delete(worker)
|
|
792
|
+
|
|
793
|
+
const handedOffAtMs = await this.store.markHandedOff({jobId: job.id, workerId: worker.workerId})
|
|
794
|
+
|
|
795
|
+
try {
|
|
796
|
+
worker.send({
|
|
797
|
+
type: "job",
|
|
798
|
+
payload: {
|
|
799
|
+
id: job.id,
|
|
800
|
+
jobName: job.jobName,
|
|
801
|
+
args: job.args,
|
|
802
|
+
workerId: worker.workerId,
|
|
803
|
+
handedOffAtMs,
|
|
804
|
+
options: {
|
|
805
|
+
executionMode: job.executionMode,
|
|
806
|
+
forked: job.forked
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
})
|
|
810
|
+
} catch (error) {
|
|
811
|
+
this.logger.warn(() => ["Failed to send job to worker, re-queueing:", error])
|
|
812
|
+
await this.store.markReturnedToQueue({jobId: job.id})
|
|
813
|
+
this.readyWorkers.add(worker)
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Runs next available job for ready workers.
|
|
820
|
+
* @returns {Promise<import("./types.js").BackgroundJobRow | null>} - Next queued job matching ready worker capacity.
|
|
821
|
+
*/
|
|
822
|
+
async nextAvailableJobForReadyWorkers() {
|
|
823
|
+
const executionModes = this.readyWorkerExecutionModes()
|
|
824
|
+
|
|
825
|
+
if (executionModes.length === 0) return null
|
|
826
|
+
if (executionModes.length === 3) return await this.store.nextAvailableJob()
|
|
827
|
+
|
|
828
|
+
return await this.store.nextAvailableJob({executionMode: executionModes})
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Runs ready worker execution modes.
|
|
833
|
+
* @returns {import("./types.js").BackgroundJobExecutionMode[]} - Execution modes currently accepted by ready workers.
|
|
834
|
+
*/
|
|
835
|
+
readyWorkerExecutionModes() {
|
|
836
|
+
const executionModes = new Set()
|
|
837
|
+
|
|
838
|
+
for (const worker of this.readyWorkers) {
|
|
839
|
+
this._addAcceptedExecutionModes({executionModes, worker})
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
return /** Narrows the runtime value to the documented type. @type {import("./types.js").BackgroundJobExecutionMode[]} */ ([...executionModes])
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* Runs add accepted execution modes.
|
|
847
|
+
* @param {object} args - Options.
|
|
848
|
+
* @param {Set<import("./types.js").BackgroundJobExecutionMode>} args.executionModes - Accepted modes.
|
|
849
|
+
* @param {JsonSocket} args.worker - Worker socket.
|
|
850
|
+
* @returns {void}
|
|
851
|
+
*/
|
|
852
|
+
_addAcceptedExecutionModes({executionModes, worker}) {
|
|
853
|
+
for (const capability of WORKER_EXECUTION_MODE_CAPABILITIES) {
|
|
854
|
+
if (capability.accepts(worker)) executionModes.add(capability.executionMode)
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Runs ready worker for job.
|
|
860
|
+
* @param {import("./types.js").BackgroundJobRow} job - Job being handed off.
|
|
861
|
+
* @returns {JsonSocket | undefined} - Ready worker for the job type.
|
|
862
|
+
*/
|
|
863
|
+
readyWorkerForJob(job) {
|
|
864
|
+
for (const worker of this.readyWorkers) {
|
|
865
|
+
if (this._workerAcceptsJob({job, worker})) return worker
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Runs worker accepts job.
|
|
871
|
+
* @param {object} args - Options.
|
|
872
|
+
* @param {import("./types.js").BackgroundJobRow} args.job - Job being handed off.
|
|
873
|
+
* @param {JsonSocket} args.worker - Worker socket.
|
|
874
|
+
* @returns {boolean} - Whether the worker accepts the job mode.
|
|
875
|
+
*/
|
|
876
|
+
_workerAcceptsJob({job, worker}) {
|
|
877
|
+
const capability = WORKER_EXECUTION_MODE_CAPABILITIES_BY_MODE.get(job.executionMode)
|
|
878
|
+
|
|
879
|
+
if (!capability) return false
|
|
880
|
+
|
|
881
|
+
return capability.accepts(worker)
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Arms a single `setTimeout` for the soonest future-scheduled job's
|
|
886
|
+
* `scheduled_at_ms`. Replaces the second responsibility of the legacy
|
|
887
|
+
* 1-second poll (becoming-eligible scheduled jobs). The timer is
|
|
888
|
+
* idempotently re-armed at the end of every drain.
|
|
889
|
+
* @returns {Promise<void>}
|
|
890
|
+
*/
|
|
891
|
+
async _armScheduledTimer() {
|
|
892
|
+
if (this._scheduledTimer) {
|
|
893
|
+
clearTimeout(this._scheduledTimer)
|
|
894
|
+
this._scheduledTimer = undefined
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
if (this._stopped) return
|
|
898
|
+
if (this.dispatchStrategy === "polling") return
|
|
899
|
+
|
|
900
|
+
const next = await this.store.nextScheduledJob()
|
|
901
|
+
if (!next || typeof next.scheduledAtMs !== "number") return
|
|
902
|
+
|
|
903
|
+
const delay = Math.max(0, Math.min(next.scheduledAtMs - Date.now(), MAX_TIMER_MS))
|
|
904
|
+
|
|
905
|
+
this._scheduledTimer = setTimeout(() => {
|
|
906
|
+
this._scheduledTimer = undefined
|
|
907
|
+
void this._drain()
|
|
908
|
+
}, delay)
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
async _sweepOrphans() {
|
|
912
|
+
try {
|
|
913
|
+
const count = await this.store.markOrphanedJobs()
|
|
914
|
+
|
|
915
|
+
if (count > 0) {
|
|
916
|
+
this.logger.warn(() => ["Marked orphaned background jobs", count])
|
|
917
|
+
// Reclaimed orphans become `queued` again — wake the dispatcher
|
|
918
|
+
// so they aren't stranded until the next external signal.
|
|
919
|
+
this._notifyEnqueued()
|
|
920
|
+
await this._drain()
|
|
921
|
+
}
|
|
922
|
+
} catch (error) {
|
|
923
|
+
this.logger.error(() => ["Failed to mark orphaned jobs:", error])
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|