velocious 1.0.510 → 1.0.511
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/build/database/advisory-lock-runner.js +192 -0
- package/build/database/drivers/mysql/index.js +3 -0
- package/build/database/record/index.js +23 -111
- package/build/src/configuration-types.d.ts +1 -1
- package/build/src/configuration.d.ts +1 -1
- package/build/src/database/advisory-lock-runner.d.ts +124 -0
- package/build/src/database/advisory-lock-runner.d.ts.map +1 -0
- package/build/src/database/advisory-lock-runner.js +176 -0
- package/build/src/database/drivers/mysql/index.d.ts +2 -2
- package/build/src/database/drivers/mysql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/index.js +3 -1
- package/build/src/database/record/attachments/handle.d.ts +1 -1
- package/build/src/database/record/index.d.ts +13 -61
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +24 -108
- package/build/src/sync/sync-envelope-replay-service.d.ts +1 -1
- package/build/src/sync/sync-replay-upsert-applier.d.ts +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/database/advisory-lock-runner.js +192 -0
- package/src/database/drivers/mysql/index.js +3 -0
- package/src/database/record/index.js +23 -111
|
@@ -68,7 +68,7 @@ export default class SyncEnvelopeReplayService {
|
|
|
68
68
|
mutation: unknown;
|
|
69
69
|
context: Record<string, unknown>;
|
|
70
70
|
}) => Promise<unknown>) | undefined;
|
|
71
|
-
restArgs?: "
|
|
71
|
+
restArgs?: "ignore" | "error" | undefined;
|
|
72
72
|
afterApply?: ((args: {
|
|
73
73
|
mappedAttributes: Record<string, unknown>;
|
|
74
74
|
mutation: unknown;
|
|
@@ -34,7 +34,7 @@ export default class SyncReplayUpsertApplier {
|
|
|
34
34
|
mutation: unknown;
|
|
35
35
|
context: Record<string, unknown>;
|
|
36
36
|
}) => Promise<unknown>) | undefined;
|
|
37
|
-
restArgs?: "
|
|
37
|
+
restArgs?: "ignore" | "error" | undefined;
|
|
38
38
|
afterApply?: ((args: {
|
|
39
39
|
mappedAttributes: Record<string, unknown>;
|
|
40
40
|
mutation: unknown;
|
|
@@ -67,7 +67,7 @@ export default class SyncReplayUpsertApplier {
|
|
|
67
67
|
context: Record<string, unknown>;
|
|
68
68
|
}) => Promise<unknown>) | undefined;
|
|
69
69
|
modelClass: any;
|
|
70
|
-
restArgs: "
|
|
70
|
+
restArgs: "ignore" | "error";
|
|
71
71
|
serialize: ((args: {
|
|
72
72
|
mutation: unknown;
|
|
73
73
|
context: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/time-zone.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/drop.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/cli/commands/lint/relationships.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/column-types.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/remove-index.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/auditing.js","../src/database/record/counter-cache-magnitude.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/validation-messages.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/length.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/database/tenants/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/packages/velocious-package.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/api-manifest/controller.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-change-fanout.js","../src/sync/sync-channel-name.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-publish-suppression.js","../src/sync/sync-publisher-types.js","../src/sync/sync-publisher.js","../src/sync/sync-realtime-bridge.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-attributes.js","../src/sync/sync-scope-store.js","../src/sync/sync-websocket-channel.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-iterator.js","../src/tenants/tenant.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/is-date.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
|
|
1
|
+
{"root":["../index.js","../bin/velocious.js","../src/application.js","../src/configuration-resolver.js","../src/configuration-types.js","../src/configuration.js","../src/controller.js","../src/current-configuration.js","../src/current.js","../src/error-logger.js","../src/frontend-model-controller.js","../src/initializer.js","../src/logger.js","../src/mailer.js","../src/record-payload-values.js","../src/time-zone.js","../src/velocious-error.js","../src/authorization/ability.js","../src/authorization/base-resource.js","../src/background-jobs/client.js","../src/background-jobs/cron-expression.js","../src/background-jobs/forked-runner-child.js","../src/background-jobs/job-record.js","../src/background-jobs/job-registry.js","../src/background-jobs/job-runner.js","../src/background-jobs/job.js","../src/background-jobs/json-socket.js","../src/background-jobs/main.js","../src/background-jobs/normalize-error.js","../src/background-jobs/scheduler.js","../src/background-jobs/socket-request.js","../src/background-jobs/status-reporter.js","../src/background-jobs/store.js","../src/background-jobs/types.js","../src/background-jobs/worker.js","../src/background-jobs/web/authorization.js","../src/background-jobs/web/controller.js","../src/background-jobs/web/index.js","../src/background-jobs/web/path-matcher.js","../src/background-jobs/web/registry.js","../src/beacon/client.js","../src/beacon/in-process-broker.js","../src/beacon/in-process-client.js","../src/beacon/server.js","../src/beacon/types.js","../src/cli/base-command.js","../src/cli/browser-cli.js","../src/cli/index.js","../src/cli/tenant-database-command-helper.js","../src/cli/use-browser-cli.js","../src/cli/commands/background-jobs-main.js","../src/cli/commands/background-jobs-runner.js","../src/cli/commands/background-jobs-worker.js","../src/cli/commands/beacon.js","../src/cli/commands/console.js","../src/cli/commands/init.js","../src/cli/commands/routes.js","../src/cli/commands/run-script.js","../src/cli/commands/runner.js","../src/cli/commands/server.js","../src/cli/commands/test.js","../src/cli/commands/db/base-command.js","../src/cli/commands/db/create.js","../src/cli/commands/db/drop.js","../src/cli/commands/db/migrate.js","../src/cli/commands/db/reset.js","../src/cli/commands/db/rollback.js","../src/cli/commands/db/seed.js","../src/cli/commands/db/schema/dump.js","../src/cli/commands/db/schema/load.js","../src/cli/commands/db/tenants/check.js","../src/cli/commands/db/tenants/create.js","../src/cli/commands/db/tenants/drop.js","../src/cli/commands/db/tenants/migrate.js","../src/cli/commands/destroy/migration.js","../src/cli/commands/generate/base-models.js","../src/cli/commands/generate/frontend-models.js","../src/cli/commands/generate/migration.js","../src/cli/commands/generate/model.js","../src/cli/commands/lint/relationships.js","../src/database/advisory-lock-runner.js","../src/database/annotations-async-hooks.js","../src/database/annotations.js","../src/database/column-types.js","../src/database/datetime-storage.js","../src/database/handler.js","../src/database/initializer-from-require-context.js","../src/database/migrations-ledger.js","../src/database/migrator.js","../src/database/use-database.js","../src/database/drivers/base-column.js","../src/database/drivers/base-columns-index.js","../src/database/drivers/base-foreign-key.js","../src/database/drivers/base-table.js","../src/database/drivers/base.js","../src/database/drivers/mssql/column.js","../src/database/drivers/mssql/columns-index.js","../src/database/drivers/mssql/connect-connection.js","../src/database/drivers/mssql/foreign-key.js","../src/database/drivers/mssql/index.js","../src/database/drivers/mssql/options.js","../src/database/drivers/mssql/query-parser.js","../src/database/drivers/mssql/structure-sql.js","../src/database/drivers/mssql/table.js","../src/database/drivers/mssql/sql/alter-table.js","../src/database/drivers/mssql/sql/create-database.js","../src/database/drivers/mssql/sql/create-index.js","../src/database/drivers/mssql/sql/create-table.js","../src/database/drivers/mssql/sql/delete.js","../src/database/drivers/mssql/sql/drop-database.js","../src/database/drivers/mssql/sql/drop-table.js","../src/database/drivers/mssql/sql/insert.js","../src/database/drivers/mssql/sql/remove-index.js","../src/database/drivers/mssql/sql/update.js","../src/database/drivers/mssql/sql/upsert.js","../src/database/drivers/mysql/column.js","../src/database/drivers/mysql/columns-index.js","../src/database/drivers/mysql/foreign-key.js","../src/database/drivers/mysql/index.js","../src/database/drivers/mysql/options.js","../src/database/drivers/mysql/query-parser.js","../src/database/drivers/mysql/query.js","../src/database/drivers/mysql/structure-sql.js","../src/database/drivers/mysql/table.js","../src/database/drivers/mysql/sql/alter-table.js","../src/database/drivers/mysql/sql/create-database.js","../src/database/drivers/mysql/sql/create-index.js","../src/database/drivers/mysql/sql/create-table.js","../src/database/drivers/mysql/sql/delete.js","../src/database/drivers/mysql/sql/drop-database.js","../src/database/drivers/mysql/sql/drop-table.js","../src/database/drivers/mysql/sql/insert.js","../src/database/drivers/mysql/sql/remove-index.js","../src/database/drivers/mysql/sql/update.js","../src/database/drivers/mysql/sql/upsert.js","../src/database/drivers/pgsql/column.js","../src/database/drivers/pgsql/columns-index.js","../src/database/drivers/pgsql/foreign-key.js","../src/database/drivers/pgsql/index.js","../src/database/drivers/pgsql/options.js","../src/database/drivers/pgsql/query-parser.js","../src/database/drivers/pgsql/structure-sql.js","../src/database/drivers/pgsql/table.js","../src/database/drivers/pgsql/sql/alter-table.js","../src/database/drivers/pgsql/sql/create-database.js","../src/database/drivers/pgsql/sql/create-index.js","../src/database/drivers/pgsql/sql/create-table.js","../src/database/drivers/pgsql/sql/delete.js","../src/database/drivers/pgsql/sql/drop-database.js","../src/database/drivers/pgsql/sql/drop-table.js","../src/database/drivers/pgsql/sql/insert.js","../src/database/drivers/pgsql/sql/remove-index.js","../src/database/drivers/pgsql/sql/update.js","../src/database/drivers/pgsql/sql/upsert.js","../src/database/drivers/sqlite/base.js","../src/database/drivers/sqlite/column.js","../src/database/drivers/sqlite/columns-index.js","../src/database/drivers/sqlite/connection-sql-js.js","../src/database/drivers/sqlite/foreign-key.js","../src/database/drivers/sqlite/index.js","../src/database/drivers/sqlite/index.native.js","../src/database/drivers/sqlite/index.web.js","../src/database/drivers/sqlite/options.js","../src/database/drivers/sqlite/query-parser.js","../src/database/drivers/sqlite/query.js","../src/database/drivers/sqlite/query.native.js","../src/database/drivers/sqlite/query.web.js","../src/database/drivers/sqlite/structure-sql.js","../src/database/drivers/sqlite/table-rebuilder.js","../src/database/drivers/sqlite/table.js","../src/database/drivers/sqlite/web-persistence.js","../src/database/drivers/sqlite/sql/alter-table.js","../src/database/drivers/sqlite/sql/create-index.js","../src/database/drivers/sqlite/sql/create-table.js","../src/database/drivers/sqlite/sql/delete.js","../src/database/drivers/sqlite/sql/drop-table.js","../src/database/drivers/sqlite/sql/insert.js","../src/database/drivers/sqlite/sql/remove-index.js","../src/database/drivers/sqlite/sql/update.js","../src/database/drivers/sqlite/sql/upsert.js","../src/database/drivers/structure-sql/utils.js","../src/database/migration/index.js","../src/database/migrator/files-finder.js","../src/database/migrator/types.js","../src/database/pool/async-tracked-multi-connection.js","../src/database/pool/base-methods-forward.js","../src/database/pool/base.js","../src/database/pool/single-multi-use.js","../src/database/query/alter-table-base.js","../src/database/query/base.js","../src/database/query/create-database-base.js","../src/database/query/create-index-base.js","../src/database/query/create-table-base.js","../src/database/query/delete-base.js","../src/database/query/drop-database-base.js","../src/database/query/drop-table-base.js","../src/database/query/from-base.js","../src/database/query/from-plain.js","../src/database/query/from-table.js","../src/database/query/index.js","../src/database/query/insert-base.js","../src/database/query/join-base.js","../src/database/query/join-object.js","../src/database/query/join-plain.js","../src/database/query/join-tracker.js","../src/database/query/model-class-query.js","../src/database/query/order-base.js","../src/database/query/order-column.js","../src/database/query/order-plain.js","../src/database/query/preloader.js","../src/database/query/query-data.js","../src/database/query/remove-index-base.js","../src/database/query/select-base.js","../src/database/query/select-plain.js","../src/database/query/select-table-and-column.js","../src/database/query/update-base.js","../src/database/query/upsert-base.js","../src/database/query/where-base.js","../src/database/query/where-combinator.js","../src/database/query/where-hash.js","../src/database/query/where-model-class-hash.js","../src/database/query/where-not.js","../src/database/query/where-plain.js","../src/database/query/with-count.js","../src/database/query/preloader/belongs-to.js","../src/database/query/preloader/ensure-model-class-initialized.js","../src/database/query/preloader/has-many.js","../src/database/query/preloader/has-one.js","../src/database/query/preloader/selection.js","../src/database/query-parser/base-query-parser.js","../src/database/query-parser/from-parser.js","../src/database/query-parser/group-parser.js","../src/database/query-parser/joins-parser.js","../src/database/query-parser/limit-parser.js","../src/database/query-parser/options.js","../src/database/query-parser/order-parser.js","../src/database/query-parser/select-parser.js","../src/database/query-parser/where-parser.js","../src/database/record/acts-as-list.js","../src/database/record/auditing.js","../src/database/record/counter-cache-magnitude.js","../src/database/record/index.js","../src/database/record/record-not-found-error.js","../src/database/record/state-machine.js","../src/database/record/user-module.js","../src/database/record/validation-messages.js","../src/database/record/attachments/attachment-record.js","../src/database/record/attachments/download.js","../src/database/record/attachments/handle.js","../src/database/record/attachments/normalize-input.js","../src/database/record/attachments/store.js","../src/database/record/attachments/storage-drivers/filesystem.js","../src/database/record/attachments/storage-drivers/native.js","../src/database/record/attachments/storage-drivers/s3.js","../src/database/record/instance-relationships/base.js","../src/database/record/instance-relationships/belongs-to.js","../src/database/record/instance-relationships/has-many.js","../src/database/record/instance-relationships/has-one.js","../src/database/record/relationships/base.js","../src/database/record/relationships/belongs-to.js","../src/database/record/relationships/has-many.js","../src/database/record/relationships/has-one.js","../src/database/record/validators/base.js","../src/database/record/validators/format.js","../src/database/record/validators/length.js","../src/database/record/validators/presence.js","../src/database/record/validators/uniqueness.js","../src/database/table-data/index.js","../src/database/table-data/table-column.js","../src/database/table-data/table-foreign-key.js","../src/database/table-data/table-index.js","../src/database/table-data/table-reference.js","../src/database/tenants/data-copier.js","../src/database/tenants/schema-cloner.js","../src/database/tenants/tenant-table-plan.js","../src/environment-handlers/base.js","../src/environment-handlers/browser.js","../src/environment-handlers/node.js","../src/environment-handlers/node/cli/commands/background-jobs-main.js","../src/environment-handlers/node/cli/commands/background-jobs-runner.js","../src/environment-handlers/node/cli/commands/background-jobs-worker.js","../src/environment-handlers/node/cli/commands/beacon.js","../src/environment-handlers/node/cli/commands/cli-command-context.js","../src/environment-handlers/node/cli/commands/console.js","../src/environment-handlers/node/cli/commands/init.js","../src/environment-handlers/node/cli/commands/routes.js","../src/environment-handlers/node/cli/commands/run-script.js","../src/environment-handlers/node/cli/commands/runner.js","../src/environment-handlers/node/cli/commands/server.js","../src/environment-handlers/node/cli/commands/test.js","../src/environment-handlers/node/cli/commands/db/seed.js","../src/environment-handlers/node/cli/commands/db/schema/dump.js","../src/environment-handlers/node/cli/commands/db/schema/load.js","../src/environment-handlers/node/cli/commands/destroy/migration.js","../src/environment-handlers/node/cli/commands/generate/base-models.js","../src/environment-handlers/node/cli/commands/generate/frontend-models.js","../src/environment-handlers/node/cli/commands/generate/generated-file-banner.js","../src/environment-handlers/node/cli/commands/generate/migration.js","../src/environment-handlers/node/cli/commands/generate/model.js","../src/environment-handlers/node/cli/commands/lint/relationships.js","../src/error-reporting/request-details.js","../src/frontend-model-resource/base-resource.js","../src/frontend-model-resource/velocious-attachment-resource.js","../src/frontend-models/base.js","../src/frontend-models/built-in-resources.js","../src/frontend-models/clear-pending-debounced-callback.js","../src/frontend-models/event-hook-models.js","../src/frontend-models/model-registry.js","../src/frontend-models/outgoing-event-buffer.js","../src/frontend-models/preloader.js","../src/frontend-models/query.js","../src/frontend-models/resource-config-validation.js","../src/frontend-models/resource-definition.js","../src/frontend-models/transport-serialization.js","../src/frontend-models/use-created-event.js","../src/frontend-models/use-destroyed-event.js","../src/frontend-models/use-model-class-event.js","../src/frontend-models/use-updated-event.js","../src/frontend-models/websocket-channel.js","../src/frontend-models/websocket-publishers.js","../src/http-client/header.js","../src/http-client/index.js","../src/http-client/request.js","../src/http-client/response.js","../src/http-client/websocket-client.js","../src/http-server/cookie.js","../src/http-server/development-reloader.js","../src/http-server/index.js","../src/http-server/remote-address.js","../src/http-server/server-client.js","../src/http-server/server-lock.js","../src/http-server/websocket-channel-subscribers.js","../src/http-server/websocket-channel.js","../src/http-server/websocket-connection.js","../src/http-server/websocket-event-log-store.js","../src/http-server/websocket-events-host.js","../src/http-server/websocket-events.js","../src/http-server/client/index.js","../src/http-server/client/params-to-object.js","../src/http-server/client/request-parser.js","../src/http-server/client/request-runner.js","../src/http-server/client/request-timing.js","../src/http-server/client/request.js","../src/http-server/client/response.js","../src/http-server/client/websocket-request.js","../src/http-server/client/websocket-session.js","../src/http-server/client/request-buffer/form-data-part.js","../src/http-server/client/request-buffer/header.js","../src/http-server/client/request-buffer/index.js","../src/http-server/client/uploaded-file/memory-uploaded-file.js","../src/http-server/client/uploaded-file/temporary-uploaded-file.js","../src/http-server/client/uploaded-file/uploaded-file.js","../src/http-server/worker-handler/channel-subscriber-dispatch.js","../src/http-server/worker-handler/in-process.js","../src/http-server/worker-handler/index.js","../src/http-server/worker-handler/worker-script.js","../src/http-server/worker-handler/worker-thread.js","../src/jobs/mail-delivery.js","../src/logger/base-logger.js","../src/logger/console-logger.js","../src/logger/file-logger.js","../src/logger/outputs/array-output.js","../src/logger/outputs/console-output.js","../src/logger/outputs/file-output.js","../src/logger/outputs/stdout-output.js","../src/mailer/base.js","../src/mailer/delivery.js","../src/mailer/index.js","../src/mailer/backends/smtp.js","../src/packages/velocious-package.js","../src/plugins/sqljs-wasm-route-controller.js","../src/plugins/sqljs-wasm-route.js","../src/routes/app-routes.js","../src/routes/base-route.js","../src/routes/basic-route.js","../src/routes/get-route.js","../src/routes/index.js","../src/routes/namespace-route.js","../src/routes/plugin-routes.js","../src/routes/post-route.js","../src/routes/resolver.js","../src/routes/resource-route.js","../src/routes/root-route.js","../src/routes/built-in/api-manifest/controller.js","../src/routes/built-in/debug/controller.js","../src/routes/built-in/errors/controller.js","../src/routes/hooks/frontend-model-command-route-hook.js","../src/sync/conflict-strategy.js","../src/sync/device-identity.js","../src/sync/local-mutation-log.js","../src/sync/offline-grant.js","../src/sync/peer-mutation-bundle.js","../src/sync/query-scope.js","../src/sync/server-change-feed.js","../src/sync/server-sequence-allocator.js","../src/sync/stable-json.js","../src/sync/sync-api-client-types.js","../src/sync/sync-api-client.js","../src/sync/sync-api-controller.js","../src/sync/sync-change-fanout.js","../src/sync/sync-channel-name.js","../src/sync/sync-client-registry.js","../src/sync/sync-client-types.js","../src/sync/sync-client.js","../src/sync/sync-envelope-replay-service.js","../src/sync/sync-model-change-feed-service.js","../src/sync/sync-publish-suppression.js","../src/sync/sync-publisher-types.js","../src/sync/sync-publisher.js","../src/sync/sync-realtime-bridge.js","../src/sync/sync-replay-upsert-applier.js","../src/sync/sync-resource-base.js","../src/sync/sync-scope-attributes.js","../src/sync/sync-scope-store.js","../src/sync/sync-websocket-channel.js","../src/tenants/default-tenant-database-provisioning.js","../src/tenants/tenant-iterator.js","../src/tenants/tenant.js","../src/testing/base-expect.js","../src/testing/browser-frontend-model-event-hook-scenarios.js","../src/testing/browser-test-app.js","../src/testing/expect-to-change.js","../src/testing/expect-utils.js","../src/testing/expect.js","../src/testing/request-client.js","../src/testing/test-files-finder.js","../src/testing/test-filter-parser.js","../src/testing/test-runner.js","../src/testing/test-suite-splitter.js","../src/testing/test.js","../src/types/external-modules.d.ts","../src/utils/backtrace-cleaner-node.js","../src/utils/backtrace-cleaner.js","../src/utils/deburr-column-name.js","../src/utils/event-emitter.js","../src/utils/file-exists.js","../src/utils/format-value.js","../src/utils/is-date.js","../src/utils/model-scope.js","../src/utils/nest-callbacks.js","../src/utils/plain-object.js","../src/utils/ransack.js","../src/utils/rest-args-error.js","../src/utils/singularize-model-name.js","../src/utils/split-sql-statements.js","../src/utils/to-import-specifier.js","../src/utils/with-tracked-stack-async-hooks.js","../src/utils/with-tracked-stack.js"],"version":"6.0.3"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import timeout from "awaitery/build/timeout.js"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Thrown when an advisory lock could not be acquired before `timeoutMs` elapsed.
|
|
7
|
+
*/
|
|
8
|
+
class AdvisoryLockTimeoutError extends Error {
|
|
9
|
+
/**
|
|
10
|
+
* Runs constructor.
|
|
11
|
+
* @param {string} message - Error message.
|
|
12
|
+
* @param {{name: string}} args - The advisory lock name that timed out.
|
|
13
|
+
*/
|
|
14
|
+
constructor(message, {name}) {
|
|
15
|
+
super(message)
|
|
16
|
+
this.name = "AdvisoryLockTimeoutError"
|
|
17
|
+
this.lockName = name
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when `withAdvisoryLockOrFail` finds the lock already held.
|
|
23
|
+
*/
|
|
24
|
+
class AdvisoryLockBusyError extends Error {
|
|
25
|
+
/**
|
|
26
|
+
* Runs constructor.
|
|
27
|
+
* @param {string} message - Error message.
|
|
28
|
+
* @param {{name: string}} args - The advisory lock name that was already held.
|
|
29
|
+
*/
|
|
30
|
+
constructor(message, {name}) {
|
|
31
|
+
super(message)
|
|
32
|
+
this.name = "AdvisoryLockBusyError"
|
|
33
|
+
this.lockName = name
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Thrown when a callback holds an advisory lock longer than `holdTimeoutMs`.
|
|
39
|
+
*/
|
|
40
|
+
class AdvisoryLockHoldTimeoutError extends Error {
|
|
41
|
+
/**
|
|
42
|
+
* Runs constructor.
|
|
43
|
+
* @param {string} message - Error message.
|
|
44
|
+
* @param {{name: string}} args - The advisory lock name whose hold timed out.
|
|
45
|
+
*/
|
|
46
|
+
constructor(message, {name}) {
|
|
47
|
+
super(message)
|
|
48
|
+
this.name = "AdvisoryLockHoldTimeoutError"
|
|
49
|
+
this.lockName = name
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Runs advisory locks on the caller connection by default, using a dedicated
|
|
55
|
+
* lock connection only when a positive hold timeout needs separate ownership.
|
|
56
|
+
*/
|
|
57
|
+
export default class AdvisoryLockRunner {
|
|
58
|
+
/**
|
|
59
|
+
* Creates an advisory-lock runner for one model database identifier.
|
|
60
|
+
* @param {{configuration: import("../configuration.js").default, connectionProvider: () => import("./drivers/base.js").default, databaseIdentifier: string}} args - Runner dependencies.
|
|
61
|
+
*/
|
|
62
|
+
constructor({configuration, connectionProvider, databaseIdentifier}) {
|
|
63
|
+
this.configuration = configuration
|
|
64
|
+
this.connectionProvider = connectionProvider
|
|
65
|
+
this.databaseIdentifier = databaseIdentifier
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Runs a callback after acquiring the advisory lock, waiting up to `timeoutMs`.
|
|
70
|
+
* @template T
|
|
71
|
+
* @param {string} name - Lock name.
|
|
72
|
+
* @param {() => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
73
|
+
* @param {{timeoutMs?: number | null, holdTimeoutMs?: number | null}} [args] - Lock and hold timeout options.
|
|
74
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
75
|
+
*/
|
|
76
|
+
async withAdvisoryLock(name, callback, args = {}) {
|
|
77
|
+
return await this.withLockConnection(args.holdTimeoutMs, async (connection) => {
|
|
78
|
+
const acquired = await connection.acquireAdvisoryLock(name, args)
|
|
79
|
+
|
|
80
|
+
if (!acquired) {
|
|
81
|
+
throw new AdvisoryLockTimeoutError(`Timed out waiting for advisory lock ${JSON.stringify(name)}`, {name})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return await this.runLockedCallback({callback, connection, holdTimeoutMs: args.holdTimeoutMs, name})
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Runs a callback only if the advisory lock can be acquired immediately.
|
|
90
|
+
* @template T
|
|
91
|
+
* @param {string} name - Lock name.
|
|
92
|
+
* @param {() => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
93
|
+
* @param {{holdTimeoutMs?: number | null}} [args] - Hold timeout options.
|
|
94
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
95
|
+
*/
|
|
96
|
+
async withAdvisoryLockOrFail(name, callback, args = {}) {
|
|
97
|
+
return await this.withLockConnection(args.holdTimeoutMs, async (connection) => {
|
|
98
|
+
const acquired = await connection.tryAcquireAdvisoryLock(name)
|
|
99
|
+
|
|
100
|
+
if (!acquired) {
|
|
101
|
+
throw new AdvisoryLockBusyError(`Advisory lock ${JSON.stringify(name)} is already held`, {name})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return await this.runLockedCallback({callback, connection, holdTimeoutMs: args.holdTimeoutMs, name})
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Runs the lock holder callback and releases the lock from its owning connection.
|
|
110
|
+
* @template T
|
|
111
|
+
* @param {{callback: () => Promise<T>, connection: import("./drivers/base.js").default, holdTimeoutMs?: number | null, name: string}} args - Locked callback args.
|
|
112
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
113
|
+
*/
|
|
114
|
+
async runLockedCallback({callback, connection, holdTimeoutMs, name}) {
|
|
115
|
+
try {
|
|
116
|
+
return await AdvisoryLockRunner.runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs)
|
|
117
|
+
} finally {
|
|
118
|
+
await connection.releaseAdvisoryLock(name)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Runs lock work on the caller connection unless a positive hold timeout needs
|
|
124
|
+
* its own lock connection.
|
|
125
|
+
* @template T
|
|
126
|
+
* @param {number | null | undefined} holdTimeoutMs - Max hold time; positive values use a dedicated lock connection.
|
|
127
|
+
* @param {(connection: import("./drivers/base.js").default) => Promise<T>} callback - Callback receiving the connection that owns the advisory lock.
|
|
128
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
129
|
+
*/
|
|
130
|
+
async withLockConnection(holdTimeoutMs, callback) {
|
|
131
|
+
if (holdTimeoutMs && holdTimeoutMs > 0) {
|
|
132
|
+
return await this.withDedicatedConnection(callback)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return await callback(this.connectionProvider())
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Spawns a hold-timeout lock connection and closes it after lock work completes when
|
|
140
|
+
* the spawned driver owns the underlying physical connection.
|
|
141
|
+
* @template T
|
|
142
|
+
* @param {(connection: import("./drivers/base.js").default) => Promise<T>} callback - Callback that receives the dedicated lock connection.
|
|
143
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
144
|
+
*/
|
|
145
|
+
async withDedicatedConnection(callback) {
|
|
146
|
+
const connection = await this.configuration.getDatabasePool(this.databaseIdentifier).spawnConnection()
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
return await callback(connection)
|
|
150
|
+
} finally {
|
|
151
|
+
if (!connection.getArgs().getConnection) {
|
|
152
|
+
await connection.close()
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Runs `callback`, rejecting with `AdvisoryLockHoldTimeoutError` if it has
|
|
159
|
+
* not settled within `holdTimeoutMs`. The callback is not cancelled; callers
|
|
160
|
+
* use a dedicated advisory-lock connection so the lock can still be released.
|
|
161
|
+
* @template T
|
|
162
|
+
* @param {string} name - Lock name (for the error message).
|
|
163
|
+
* @param {() => Promise<T>} callback - Callback holding the lock.
|
|
164
|
+
* @param {number | null} [holdTimeoutMs] - Max hold time; falsy disables the timeout.
|
|
165
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
166
|
+
*/
|
|
167
|
+
static async runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs) {
|
|
168
|
+
if (!holdTimeoutMs || holdTimeoutMs <= 0) {
|
|
169
|
+
return await callback()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let callbackSettled = false
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
return await timeout({timeout: holdTimeoutMs}, async () => {
|
|
176
|
+
try {
|
|
177
|
+
return await callback()
|
|
178
|
+
} finally {
|
|
179
|
+
callbackSettled = true
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (!callbackSettled) {
|
|
184
|
+
throw new AdvisoryLockHoldTimeoutError(`Advisory lock ${JSON.stringify(name)} held longer than ${holdTimeoutMs}ms`, {name})
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
throw error
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export {AdvisoryLockBusyError, AdvisoryLockHoldTimeoutError, AdvisoryLockTimeoutError}
|
|
@@ -31,6 +31,9 @@ import Update from "./sql/update.js"
|
|
|
31
31
|
const MYSQL_INDEFINITE_LOCK_TIMEOUT_SECONDS = 60 * 60 * 24 * 365
|
|
32
32
|
|
|
33
33
|
export default class VelociousDatabaseDriversMysql extends Base{
|
|
34
|
+
/** @type {import("mysql").Pool | undefined} */
|
|
35
|
+
pool = undefined
|
|
36
|
+
|
|
34
37
|
/** @type {string | null} */
|
|
35
38
|
_desiredSessionTimeZone = "+00:00"
|
|
36
39
|
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
/** @typedef {import("../../configuration-types.js").TenantDatabaseProviderType} TenantDatabaseProviderType */
|
|
26
26
|
|
|
27
|
-
import
|
|
27
|
+
import AdvisoryLockRunner, {AdvisoryLockBusyError, AdvisoryLockHoldTimeoutError, AdvisoryLockTimeoutError} from "../advisory-lock-runner.js"
|
|
28
28
|
import BelongsToInstanceRelationship from "./instance-relationships/belongs-to.js"
|
|
29
29
|
import BelongsToRelationship from "./relationships/belongs-to.js"
|
|
30
30
|
import Configuration from "../../configuration.js"
|
|
@@ -164,60 +164,6 @@ function buildRelatedRecordWithInverse(parent, relationshipName, attributes, all
|
|
|
164
164
|
return record
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
/**
|
|
168
|
-
* Thrown by `Record.withAdvisoryLock` when the caller supplied a
|
|
169
|
-
* `timeoutMs` and the lock was not granted before it elapsed.
|
|
170
|
-
*/
|
|
171
|
-
class AdvisoryLockTimeoutError extends Error {
|
|
172
|
-
/**
|
|
173
|
-
* Runs constructor.
|
|
174
|
-
* @param {string} message - Error message.
|
|
175
|
-
* @param {{name: string}} args - The advisory lock name that timed out.
|
|
176
|
-
*/
|
|
177
|
-
constructor(message, {name}) {
|
|
178
|
-
super(message)
|
|
179
|
-
this.name = "AdvisoryLockTimeoutError"
|
|
180
|
-
this.lockName = name
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Thrown by `Record.withAdvisoryLockOrFail` when the lock is already held
|
|
186
|
-
* by another session at the moment of the call.
|
|
187
|
-
*/
|
|
188
|
-
class AdvisoryLockBusyError extends Error {
|
|
189
|
-
/**
|
|
190
|
-
* Runs constructor.
|
|
191
|
-
* @param {string} message - Error message.
|
|
192
|
-
* @param {{name: string}} args - The advisory lock name that was already held.
|
|
193
|
-
*/
|
|
194
|
-
constructor(message, {name}) {
|
|
195
|
-
super(message)
|
|
196
|
-
this.name = "AdvisoryLockBusyError"
|
|
197
|
-
this.lockName = name
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Thrown by `Record.withAdvisoryLock` / `withAdvisoryLockOrFail` when the
|
|
203
|
-
* caller supplied a `holdTimeoutMs` and the callback ran longer than it. The
|
|
204
|
-
* lock is released before this is thrown, so a hung holder can't block other
|
|
205
|
-
* sessions indefinitely. Note: the callback itself is not cancelled — pass an
|
|
206
|
-
* AbortSignal to the work if it needs to stop.
|
|
207
|
-
*/
|
|
208
|
-
class AdvisoryLockHoldTimeoutError extends Error {
|
|
209
|
-
/**
|
|
210
|
-
* Runs constructor.
|
|
211
|
-
* @param {string} message - Error message.
|
|
212
|
-
* @param {{name: string}} args - The advisory lock name whose hold timed out.
|
|
213
|
-
*/
|
|
214
|
-
constructor(message, {name}) {
|
|
215
|
-
super(message)
|
|
216
|
-
this.name = "AdvisoryLockHoldTimeoutError"
|
|
217
|
-
this.lockName = name
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
167
|
class TenantDatabaseScopeError extends Error {
|
|
222
168
|
/**
|
|
223
169
|
* Runs constructor.
|
|
@@ -2675,10 +2621,13 @@ class VelociousDatabaseRecord {
|
|
|
2675
2621
|
}
|
|
2676
2622
|
|
|
2677
2623
|
/**
|
|
2678
|
-
* Runs the callback while holding a named advisory lock
|
|
2679
|
-
*
|
|
2680
|
-
*
|
|
2681
|
-
*
|
|
2624
|
+
* Runs the callback while holding a named advisory lock. Calls without
|
|
2625
|
+
* a positive `holdTimeoutMs` use the caller connection; calls with a positive
|
|
2626
|
+
* `holdTimeoutMs` use a dedicated lock connection so timeout cleanup can
|
|
2627
|
+
* release the lock even when callback database work is stuck. Advisory locks
|
|
2628
|
+
* are cooperative and session-scoped: they serialize callers that opt into
|
|
2629
|
+
* the same `name`, without touching row or table locks, so unrelated traffic
|
|
2630
|
+
* is free to proceed.
|
|
2682
2631
|
*
|
|
2683
2632
|
* The lock is acquired before the callback runs and released in a
|
|
2684
2633
|
* `finally` block afterwards, so the callback's return value is
|
|
@@ -2694,18 +2643,13 @@ class VelociousDatabaseRecord {
|
|
|
2694
2643
|
static async withAdvisoryLock(name, callback, args = {}) {
|
|
2695
2644
|
await this.ensureInitialized()
|
|
2696
2645
|
|
|
2697
|
-
const
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
}
|
|
2646
|
+
const runner = new AdvisoryLockRunner({
|
|
2647
|
+
configuration: this._getConfiguration(),
|
|
2648
|
+
connectionProvider: () => this.connection(),
|
|
2649
|
+
databaseIdentifier: this.getDatabaseIdentifier()
|
|
2650
|
+
})
|
|
2703
2651
|
|
|
2704
|
-
|
|
2705
|
-
return await this.runWithAdvisoryLockHoldTimeout(name, callback, args.holdTimeoutMs)
|
|
2706
|
-
} finally {
|
|
2707
|
-
await connection.releaseAdvisoryLock(name)
|
|
2708
|
-
}
|
|
2652
|
+
return await runner.withAdvisoryLock(name, callback, args)
|
|
2709
2653
|
}
|
|
2710
2654
|
|
|
2711
2655
|
/**
|
|
@@ -2725,31 +2669,19 @@ class VelociousDatabaseRecord {
|
|
|
2725
2669
|
static async withAdvisoryLockOrFail(name, callback, args = {}) {
|
|
2726
2670
|
await this.ensureInitialized()
|
|
2727
2671
|
|
|
2728
|
-
const
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
}
|
|
2672
|
+
const runner = new AdvisoryLockRunner({
|
|
2673
|
+
configuration: this._getConfiguration(),
|
|
2674
|
+
connectionProvider: () => this.connection(),
|
|
2675
|
+
databaseIdentifier: this.getDatabaseIdentifier()
|
|
2676
|
+
})
|
|
2734
2677
|
|
|
2735
|
-
|
|
2736
|
-
return await this.runWithAdvisoryLockHoldTimeout(name, callback, args.holdTimeoutMs)
|
|
2737
|
-
} finally {
|
|
2738
|
-
await connection.releaseAdvisoryLock(name)
|
|
2739
|
-
}
|
|
2678
|
+
return await runner.withAdvisoryLockOrFail(name, callback, args)
|
|
2740
2679
|
}
|
|
2741
2680
|
|
|
2742
2681
|
/**
|
|
2743
2682
|
* Runs `callback`, rejecting with `AdvisoryLockHoldTimeoutError` if it has
|
|
2744
|
-
* not settled within `holdTimeoutMs`. The
|
|
2745
|
-
*
|
|
2746
|
-
* callback is not cancelled — this is a safety net, not cancellation.
|
|
2747
|
-
*
|
|
2748
|
-
* Uses `awaitery`'s shared `timeout` helper for the hard timeout, then
|
|
2749
|
-
* translates its timeout into the typed `AdvisoryLockHoldTimeoutError` so
|
|
2750
|
-
* callers can catch it like the other advisory-lock errors. A `callbackSettled`
|
|
2751
|
-
* flag distinguishes the timeout from a rejection thrown by the callback
|
|
2752
|
-
* itself, which is rethrown unchanged.
|
|
2683
|
+
* not settled within `holdTimeoutMs`. The callback is not cancelled — this is
|
|
2684
|
+
* a safety net, not cancellation.
|
|
2753
2685
|
* @template T
|
|
2754
2686
|
* @param {string} name - Lock name (for the error message).
|
|
2755
2687
|
* @param {() => Promise<T>} callback - Callback holding the lock.
|
|
@@ -2757,27 +2689,7 @@ class VelociousDatabaseRecord {
|
|
|
2757
2689
|
* @returns {Promise<T>}
|
|
2758
2690
|
*/
|
|
2759
2691
|
static async runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs) {
|
|
2760
|
-
|
|
2761
|
-
return await callback()
|
|
2762
|
-
}
|
|
2763
|
-
|
|
2764
|
-
let callbackSettled = false
|
|
2765
|
-
|
|
2766
|
-
try {
|
|
2767
|
-
return await timeout({timeout: holdTimeoutMs}, async () => {
|
|
2768
|
-
try {
|
|
2769
|
-
return await callback()
|
|
2770
|
-
} finally {
|
|
2771
|
-
callbackSettled = true
|
|
2772
|
-
}
|
|
2773
|
-
})
|
|
2774
|
-
} catch (error) {
|
|
2775
|
-
if (!callbackSettled) {
|
|
2776
|
-
throw new AdvisoryLockHoldTimeoutError(`Advisory lock ${JSON.stringify(name)} held longer than ${holdTimeoutMs}ms`, {name})
|
|
2777
|
-
}
|
|
2778
|
-
|
|
2779
|
-
throw error
|
|
2780
|
-
}
|
|
2692
|
+
return await AdvisoryLockRunner.runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs)
|
|
2781
2693
|
}
|
|
2782
2694
|
|
|
2783
2695
|
/**
|