@antelopejs/postgres 0.0.1-stage → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +152 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.js +91 -0
- package/dist/config.js.map +1 -0
- package/dist/connection.d.ts +14 -0
- package/dist/connection.js +128 -0
- package/dist/connection.js.map +1 -0
- package/dist/implementations/catalog/index.d.ts +7 -0
- package/dist/implementations/catalog/index.js +60 -0
- package/dist/implementations/catalog/index.js.map +1 -0
- package/dist/implementations/database/changes.d.ts +19 -0
- package/dist/implementations/database/changes.js +100 -0
- package/dist/implementations/database/changes.js.map +1 -0
- package/dist/implementations/database/coerce.d.ts +15 -0
- package/dist/implementations/database/coerce.js +195 -0
- package/dist/implementations/database/coerce.js.map +1 -0
- package/dist/implementations/database/context.d.ts +32 -0
- package/dist/implementations/database/context.js +50 -0
- package/dist/implementations/database/context.js.map +1 -0
- package/dist/implementations/database/cursors.d.ts +16 -0
- package/dist/implementations/database/cursors.js +269 -0
- package/dist/implementations/database/cursors.js.map +1 -0
- package/dist/implementations/database/ddl.d.ts +62 -0
- package/dist/implementations/database/ddl.js +355 -0
- package/dist/implementations/database/ddl.js.map +1 -0
- package/dist/implementations/database/expression.d.ts +7 -0
- package/dist/implementations/database/expression.js +30 -0
- package/dist/implementations/database/expression.js.map +1 -0
- package/dist/implementations/database/external-catalog.d.ts +37 -0
- package/dist/implementations/database/external-catalog.js +96 -0
- package/dist/implementations/database/external-catalog.js.map +1 -0
- package/dist/implementations/database/external-column-profile.d.ts +18 -0
- package/dist/implementations/database/external-column-profile.js +223 -0
- package/dist/implementations/database/external-column-profile.js.map +1 -0
- package/dist/implementations/database/external-declarations.d.ts +9 -0
- package/dist/implementations/database/external-declarations.js +67 -0
- package/dist/implementations/database/external-declarations.js.map +1 -0
- package/dist/implementations/database/external-discovery.d.ts +39 -0
- package/dist/implementations/database/external-discovery.js +219 -0
- package/dist/implementations/database/external-discovery.js.map +1 -0
- package/dist/implementations/database/external-errors.d.ts +20 -0
- package/dist/implementations/database/external-errors.js +67 -0
- package/dist/implementations/database/external-errors.js.map +1 -0
- package/dist/implementations/database/external-measures.d.ts +11 -0
- package/dist/implementations/database/external-measures.js +82 -0
- package/dist/implementations/database/external-measures.js.map +1 -0
- package/dist/implementations/database/external-payload.d.ts +32 -0
- package/dist/implementations/database/external-payload.js +206 -0
- package/dist/implementations/database/external-payload.js.map +1 -0
- package/dist/implementations/database/external-profile.d.ts +4 -0
- package/dist/implementations/database/external-profile.js +129 -0
- package/dist/implementations/database/external-profile.js.map +1 -0
- package/dist/implementations/database/external-reference.d.ts +2 -0
- package/dist/implementations/database/external-reference.js +49 -0
- package/dist/implementations/database/external-reference.js.map +1 -0
- package/dist/implementations/database/external-refusals.d.ts +5 -0
- package/dist/implementations/database/external-refusals.js +23 -0
- package/dist/implementations/database/external-refusals.js.map +1 -0
- package/dist/implementations/database/external-rows.d.ts +2 -0
- package/dist/implementations/database/external-rows.js +81 -0
- package/dist/implementations/database/external-rows.js.map +1 -0
- package/dist/implementations/database/external-sample.d.ts +9 -0
- package/dist/implementations/database/external-sample.js +29 -0
- package/dist/implementations/database/external-sample.js.map +1 -0
- package/dist/implementations/database/external-schema.d.ts +3 -0
- package/dist/implementations/database/external-schema.js +111 -0
- package/dist/implementations/database/external-schema.js.map +1 -0
- package/dist/implementations/database/external-types.d.ts +37 -0
- package/dist/implementations/database/external-types.js +387 -0
- package/dist/implementations/database/external-types.js.map +1 -0
- package/dist/implementations/database/external-writes.d.ts +3 -0
- package/dist/implementations/database/external-writes.js +298 -0
- package/dist/implementations/database/external-writes.js.map +1 -0
- package/dist/implementations/database/feed-pipeline.d.ts +12 -0
- package/dist/implementations/database/feed-pipeline.js +92 -0
- package/dist/implementations/database/feed-pipeline.js.map +1 -0
- package/dist/implementations/database/feeds.d.ts +34 -0
- package/dist/implementations/database/feeds.js +338 -0
- package/dist/implementations/database/feeds.js.map +1 -0
- package/dist/implementations/database/fields.d.ts +37 -0
- package/dist/implementations/database/fields.js +114 -0
- package/dist/implementations/database/fields.js.map +1 -0
- package/dist/implementations/database/identifier.d.ts +8 -0
- package/dist/implementations/database/identifier.js +62 -0
- package/dist/implementations/database/identifier.js.map +1 -0
- package/dist/implementations/database/instances.d.ts +4 -0
- package/dist/implementations/database/instances.js +57 -0
- package/dist/implementations/database/instances.js.map +1 -0
- package/dist/implementations/database/introspect.d.ts +3 -0
- package/dist/implementations/database/introspect.js +36 -0
- package/dist/implementations/database/introspect.js.map +1 -0
- package/dist/implementations/database/jsonb.d.ts +29 -0
- package/dist/implementations/database/jsonb.js +54 -0
- package/dist/implementations/database/jsonb.js.map +1 -0
- package/dist/implementations/database/listener.d.ts +3 -0
- package/dist/implementations/database/listener.js +93 -0
- package/dist/implementations/database/listener.js.map +1 -0
- package/dist/implementations/database/migrate.d.ts +6 -0
- package/dist/implementations/database/migrate.js +282 -0
- package/dist/implementations/database/migrate.js.map +1 -0
- package/dist/implementations/database/payload.d.ts +24 -0
- package/dist/implementations/database/payload.js +113 -0
- package/dist/implementations/database/payload.js.map +1 -0
- package/dist/implementations/database/pipeline.d.ts +10 -0
- package/dist/implementations/database/pipeline.js +56 -0
- package/dist/implementations/database/pipeline.js.map +1 -0
- package/dist/implementations/database/query.d.ts +11 -0
- package/dist/implementations/database/query.js +189 -0
- package/dist/implementations/database/query.js.map +1 -0
- package/dist/implementations/database/readings.d.ts +17 -0
- package/dist/implementations/database/readings.js +133 -0
- package/dist/implementations/database/readings.js.map +1 -0
- package/dist/implementations/database/reaper.d.ts +6 -0
- package/dist/implementations/database/reaper.js +121 -0
- package/dist/implementations/database/reaper.js.map +1 -0
- package/dist/implementations/database/relation.d.ts +65 -0
- package/dist/implementations/database/relation.js +237 -0
- package/dist/implementations/database/relation.js.map +1 -0
- package/dist/implementations/database/result.d.ts +4 -0
- package/dist/implementations/database/result.js +70 -0
- package/dist/implementations/database/result.js.map +1 -0
- package/dist/implementations/database/row-source.d.ts +64 -0
- package/dist/implementations/database/row-source.js +279 -0
- package/dist/implementations/database/row-source.js.map +1 -0
- package/dist/implementations/database/schema.d.ts +15 -0
- package/dist/implementations/database/schema.js +143 -0
- package/dist/implementations/database/schema.js.map +1 -0
- package/dist/implementations/database/selection.d.ts +18 -0
- package/dist/implementations/database/selection.js +129 -0
- package/dist/implementations/database/selection.js.map +1 -0
- package/dist/implementations/database/sql.d.ts +24 -0
- package/dist/implementations/database/sql.js +48 -0
- package/dist/implementations/database/sql.js.map +1 -0
- package/dist/implementations/database/stage.d.ts +22 -0
- package/dist/implementations/database/stage.js +76 -0
- package/dist/implementations/database/stage.js.map +1 -0
- package/dist/implementations/database/stages-aggregate.d.ts +11 -0
- package/dist/implementations/database/stages-aggregate.js +112 -0
- package/dist/implementations/database/stages-aggregate.js.map +1 -0
- package/dist/implementations/database/stages-array.d.ts +2 -0
- package/dist/implementations/database/stages-array.js +162 -0
- package/dist/implementations/database/stages-array.js.map +1 -0
- package/dist/implementations/database/stages-core.d.ts +2 -0
- package/dist/implementations/database/stages-core.js +107 -0
- package/dist/implementations/database/stages-core.js.map +1 -0
- package/dist/implementations/database/stages-date.d.ts +2 -0
- package/dist/implementations/database/stages-date.js +65 -0
- package/dist/implementations/database/stages-date.js.map +1 -0
- package/dist/implementations/database/stages-group.d.ts +5 -0
- package/dist/implementations/database/stages-group.js +151 -0
- package/dist/implementations/database/stages-group.js.map +1 -0
- package/dist/implementations/database/stages-join.d.ts +2 -0
- package/dist/implementations/database/stages-join.js +162 -0
- package/dist/implementations/database/stages-join.js.map +1 -0
- package/dist/implementations/database/stages-numeric.d.ts +2 -0
- package/dist/implementations/database/stages-numeric.js +152 -0
- package/dist/implementations/database/stages-numeric.js.map +1 -0
- package/dist/implementations/database/stages-object.d.ts +2 -0
- package/dist/implementations/database/stages-object.js +81 -0
- package/dist/implementations/database/stages-object.js.map +1 -0
- package/dist/implementations/database/stages-projection.d.ts +2 -0
- package/dist/implementations/database/stages-projection.js +75 -0
- package/dist/implementations/database/stages-projection.js.map +1 -0
- package/dist/implementations/database/stages-rows.d.ts +2 -0
- package/dist/implementations/database/stages-rows.js +101 -0
- package/dist/implementations/database/stages-rows.js.map +1 -0
- package/dist/implementations/database/stages-selection.d.ts +2 -0
- package/dist/implementations/database/stages-selection.js +146 -0
- package/dist/implementations/database/stages-selection.js.map +1 -0
- package/dist/implementations/database/stages-string.d.ts +2 -0
- package/dist/implementations/database/stages-string.js +101 -0
- package/dist/implementations/database/stages-string.js.map +1 -0
- package/dist/implementations/database/subquery.d.ts +4 -0
- package/dist/implementations/database/subquery.js +49 -0
- package/dist/implementations/database/subquery.js.map +1 -0
- package/dist/implementations/database/types.d.ts +37 -0
- package/dist/implementations/database/types.js +57 -0
- package/dist/implementations/database/types.js.map +1 -0
- package/dist/implementations/database/utils.d.ts +16 -0
- package/dist/implementations/database/utils.js +38 -0
- package/dist/implementations/database/utils.js.map +1 -0
- package/dist/implementations/database/value.d.ts +10 -0
- package/dist/implementations/database/value.js +153 -0
- package/dist/implementations/database/value.js.map +1 -0
- package/dist/implementations/database/writes-atomic.d.ts +6 -0
- package/dist/implementations/database/writes-atomic.js +93 -0
- package/dist/implementations/database/writes-atomic.js.map +1 -0
- package/dist/implementations/database/writes-identity.d.ts +4 -0
- package/dist/implementations/database/writes-identity.js +181 -0
- package/dist/implementations/database/writes-identity.js.map +1 -0
- package/dist/implementations/database/writes-insert.d.ts +2 -0
- package/dist/implementations/database/writes-insert.js +136 -0
- package/dist/implementations/database/writes-insert.js.map +1 -0
- package/dist/implementations/database/writes-shared.d.ts +36 -0
- package/dist/implementations/database/writes-shared.js +64 -0
- package/dist/implementations/database/writes-shared.js.map +1 -0
- package/dist/implementations/database/writes.d.ts +16 -0
- package/dist/implementations/database/writes.js +52 -0
- package/dist/implementations/database/writes.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +6 -0
- package/dist/logger.js.map +1 -0
- package/dist/test/antelope.test.d.ts +2 -0
- package/dist/test/antelope.test.js +89 -0
- package/dist/test/antelope.test.js.map +1 -0
- package/dist/test/atomic.test.d.ts +1 -0
- package/dist/test/atomic.test.js +132 -0
- package/dist/test/atomic.test.js.map +1 -0
- package/dist/test/catalog-owned.test.d.ts +1 -0
- package/dist/test/catalog-owned.test.js +17 -0
- package/dist/test/catalog-owned.test.js.map +1 -0
- package/dist/test/contention.test.d.ts +1 -0
- package/dist/test/contention.test.js +183 -0
- package/dist/test/contention.test.js.map +1 -0
- package/dist/test/indexes.test.d.ts +1 -0
- package/dist/test/indexes.test.js +311 -0
- package/dist/test/indexes.test.js.map +1 -0
- package/dist/test/unit/changes.spec.d.ts +1 -0
- package/dist/test/unit/changes.spec.js +103 -0
- package/dist/test/unit/changes.spec.js.map +1 -0
- package/dist/test/unit/coerce.spec.d.ts +1 -0
- package/dist/test/unit/coerce.spec.js +162 -0
- package/dist/test/unit/coerce.spec.js.map +1 -0
- package/dist/test/unit/config.spec.d.ts +1 -0
- package/dist/test/unit/config.spec.js +123 -0
- package/dist/test/unit/config.spec.js.map +1 -0
- package/dist/test/unit/connection.spec.d.ts +1 -0
- package/dist/test/unit/connection.spec.js +171 -0
- package/dist/test/unit/connection.spec.js.map +1 -0
- package/dist/test/unit/cursors.spec.d.ts +1 -0
- package/dist/test/unit/cursors.spec.js +823 -0
- package/dist/test/unit/cursors.spec.js.map +1 -0
- package/dist/test/unit/ddl.spec.d.ts +1 -0
- package/dist/test/unit/ddl.spec.js +571 -0
- package/dist/test/unit/ddl.spec.js.map +1 -0
- package/dist/test/unit/expression-array.spec.d.ts +1 -0
- package/dist/test/unit/expression-array.spec.js +488 -0
- package/dist/test/unit/expression-array.spec.js.map +1 -0
- package/dist/test/unit/expression-date.spec.d.ts +1 -0
- package/dist/test/unit/expression-date.spec.js +329 -0
- package/dist/test/unit/expression-date.spec.js.map +1 -0
- package/dist/test/unit/expression-numeric.spec.d.ts +1 -0
- package/dist/test/unit/expression-numeric.spec.js +362 -0
- package/dist/test/unit/expression-numeric.spec.js.map +1 -0
- package/dist/test/unit/expression-object.spec.d.ts +1 -0
- package/dist/test/unit/expression-object.spec.js +230 -0
- package/dist/test/unit/expression-object.spec.js.map +1 -0
- package/dist/test/unit/expression-stages.spec.d.ts +1 -0
- package/dist/test/unit/expression-stages.spec.js +82 -0
- package/dist/test/unit/expression-stages.spec.js.map +1 -0
- package/dist/test/unit/expression-string.spec.d.ts +1 -0
- package/dist/test/unit/expression-string.spec.js +249 -0
- package/dist/test/unit/expression-string.spec.js.map +1 -0
- package/dist/test/unit/expression.spec.d.ts +1 -0
- package/dist/test/unit/expression.spec.js +449 -0
- package/dist/test/unit/expression.spec.js.map +1 -0
- package/dist/test/unit/external-comparisons.spec.d.ts +1 -0
- package/dist/test/unit/external-comparisons.spec.js +147 -0
- package/dist/test/unit/external-comparisons.spec.js.map +1 -0
- package/dist/test/unit/external-types.spec.d.ts +1 -0
- package/dist/test/unit/external-types.spec.js +228 -0
- package/dist/test/unit/external-types.spec.js.map +1 -0
- package/dist/test/unit/feeds.spec.d.ts +1 -0
- package/dist/test/unit/feeds.spec.js +374 -0
- package/dist/test/unit/feeds.spec.js.map +1 -0
- package/dist/test/unit/fields.spec.d.ts +1 -0
- package/dist/test/unit/fields.spec.js +79 -0
- package/dist/test/unit/fields.spec.js.map +1 -0
- package/dist/test/unit/identifier.spec.d.ts +1 -0
- package/dist/test/unit/identifier.spec.js +50 -0
- package/dist/test/unit/identifier.spec.js.map +1 -0
- package/dist/test/unit/payload.spec.d.ts +1 -0
- package/dist/test/unit/payload.spec.js +278 -0
- package/dist/test/unit/payload.spec.js.map +1 -0
- package/dist/test/unit/pipeline-aggregate.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-aggregate.spec.js +199 -0
- package/dist/test/unit/pipeline-aggregate.spec.js.map +1 -0
- package/dist/test/unit/pipeline-fixture.d.ts +79 -0
- package/dist/test/unit/pipeline-fixture.js +277 -0
- package/dist/test/unit/pipeline-fixture.js.map +1 -0
- package/dist/test/unit/pipeline-group.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-group.spec.js +390 -0
- package/dist/test/unit/pipeline-group.spec.js.map +1 -0
- package/dist/test/unit/pipeline-join.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-join.spec.js +165 -0
- package/dist/test/unit/pipeline-join.spec.js.map +1 -0
- package/dist/test/unit/pipeline-lookup.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-lookup.spec.js +268 -0
- package/dist/test/unit/pipeline-lookup.spec.js.map +1 -0
- package/dist/test/unit/pipeline-projection.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-projection.spec.js +183 -0
- package/dist/test/unit/pipeline-projection.spec.js.map +1 -0
- package/dist/test/unit/pipeline-rows.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-rows.spec.js +321 -0
- package/dist/test/unit/pipeline-rows.spec.js.map +1 -0
- package/dist/test/unit/pipeline-selection.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-selection.spec.js +257 -0
- package/dist/test/unit/pipeline-selection.spec.js.map +1 -0
- package/dist/test/unit/pipeline-stages.spec.d.ts +1 -0
- package/dist/test/unit/pipeline-stages.spec.js +226 -0
- package/dist/test/unit/pipeline-stages.spec.js.map +1 -0
- package/dist/test/unit/pipeline.spec.d.ts +1 -0
- package/dist/test/unit/pipeline.spec.js +72 -0
- package/dist/test/unit/pipeline.spec.js.map +1 -0
- package/dist/test/unit/query.spec.d.ts +1 -0
- package/dist/test/unit/query.spec.js +212 -0
- package/dist/test/unit/query.spec.js.map +1 -0
- package/dist/test/unit/reaper.spec.d.ts +1 -0
- package/dist/test/unit/reaper.spec.js +122 -0
- package/dist/test/unit/reaper.spec.js.map +1 -0
- package/dist/test/unit/relation.spec.d.ts +1 -0
- package/dist/test/unit/relation.spec.js +348 -0
- package/dist/test/unit/relation.spec.js.map +1 -0
- package/dist/test/unit/result.spec.d.ts +1 -0
- package/dist/test/unit/result.spec.js +128 -0
- package/dist/test/unit/result.spec.js.map +1 -0
- package/dist/test/unit/row-source.spec.d.ts +1 -0
- package/dist/test/unit/row-source.spec.js +141 -0
- package/dist/test/unit/row-source.spec.js.map +1 -0
- package/dist/test/unit/schema.spec.d.ts +1 -0
- package/dist/test/unit/schema.spec.js +44 -0
- package/dist/test/unit/schema.spec.js.map +1 -0
- package/dist/test/unit/selection.spec.d.ts +1 -0
- package/dist/test/unit/selection.spec.js +182 -0
- package/dist/test/unit/selection.spec.js.map +1 -0
- package/dist/test/unit/spec-fixture.d.ts +11 -0
- package/dist/test/unit/spec-fixture.js +71 -0
- package/dist/test/unit/spec-fixture.js.map +1 -0
- package/dist/test/unit/sql.spec.d.ts +1 -0
- package/dist/test/unit/sql.spec.js +38 -0
- package/dist/test/unit/sql.spec.js.map +1 -0
- package/dist/test/unit/subquery.spec.d.ts +1 -0
- package/dist/test/unit/subquery.spec.js +154 -0
- package/dist/test/unit/subquery.spec.js.map +1 -0
- package/dist/test/unit/types.spec.d.ts +1 -0
- package/dist/test/unit/types.spec.js +39 -0
- package/dist/test/unit/types.spec.js.map +1 -0
- package/dist/test/unit/utils.spec.d.ts +1 -0
- package/dist/test/unit/utils.spec.js +22 -0
- package/dist/test/unit/utils.spec.js.map +1 -0
- package/dist/test/unit/value.spec.d.ts +1 -0
- package/dist/test/unit/value.spec.js +195 -0
- package/dist/test/unit/value.spec.js.map +1 -0
- package/dist/test/unit/writes-atomic.spec.d.ts +1 -0
- package/dist/test/unit/writes-atomic.spec.js +66 -0
- package/dist/test/unit/writes-atomic.spec.js.map +1 -0
- package/dist/test/unit/writes-insert.spec.d.ts +1 -0
- package/dist/test/unit/writes-insert.spec.js +270 -0
- package/dist/test/unit/writes-insert.spec.js.map +1 -0
- package/dist/test/unit/writes-replace.spec.d.ts +1 -0
- package/dist/test/unit/writes-replace.spec.js +100 -0
- package/dist/test/unit/writes-replace.spec.js.map +1 -0
- package/dist/test/unit/writes-target.spec.d.ts +1 -0
- package/dist/test/unit/writes-target.spec.js +118 -0
- package/dist/test/unit/writes-target.spec.js.map +1 -0
- package/dist/test/unit/writes-update.spec.d.ts +1 -0
- package/dist/test/unit/writes-update.spec.js +297 -0
- package/dist/test/unit/writes-update.spec.js.map +1 -0
- package/dist/test-external/catalog.test.d.ts +1 -0
- package/dist/test-external/catalog.test.js +348 -0
- package/dist/test-external/catalog.test.js.map +1 -0
- package/dist/test-external/fixture.d.ts +7 -0
- package/dist/test-external/fixture.js +163 -0
- package/dist/test-external/fixture.js.map +1 -0
- package/dist/test-external/native.test.d.ts +1 -0
- package/dist/test-external/native.test.js +132 -0
- package/dist/test-external/native.test.js.map +1 -0
- package/dist/test-external/reads.test.d.ts +1 -0
- package/dist/test-external/reads.test.js +232 -0
- package/dist/test-external/reads.test.js.map +1 -0
- package/dist/test-external/refusals.test.d.ts +1 -0
- package/dist/test-external/refusals.test.js +93 -0
- package/dist/test-external/refusals.test.js.map +1 -0
- package/dist/test-external/registration.test.d.ts +1 -0
- package/dist/test-external/registration.test.js +127 -0
- package/dist/test-external/registration.test.js.map +1 -0
- package/dist/test-external/sales.d.ts +5 -0
- package/dist/test-external/sales.js +126 -0
- package/dist/test-external/sales.js.map +1 -0
- package/dist/test-external/startup.test.d.ts +1 -0
- package/dist/test-external/startup.test.js +15 -0
- package/dist/test-external/startup.test.js.map +1 -0
- package/dist/test-external/writes.test.d.ts +1 -0
- package/dist/test-external/writes.test.js +315 -0
- package/dist/test-external/writes.test.js.map +1 -0
- package/package.json +77 -7
|
@@ -0,0 +1,823 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const spec_fixture_1 = require("./spec-fixture");
|
|
5
|
+
const connection_1 = require("../../connection");
|
|
6
|
+
const cursors_1 = require("../../implementations/database/cursors");
|
|
7
|
+
const CURSOR = '"antelopejs_cursor"';
|
|
8
|
+
const SQL = 'SELECT "n" FROM "t" WHERE "n" > ($1::int)';
|
|
9
|
+
const PARAMS = [7];
|
|
10
|
+
const BATCH_SIZE = 3;
|
|
11
|
+
const IDLE_TIMEOUT_MS = 30_000;
|
|
12
|
+
const REAPED_AFTER_MS = 1;
|
|
13
|
+
const REAP_WINDOW_MS = 40;
|
|
14
|
+
const REAPER_PROBE_MS = 987_654;
|
|
15
|
+
const BEGIN = "BEGIN";
|
|
16
|
+
const ROLLBACK = "ROLLBACK";
|
|
17
|
+
const RELEASE = "RELEASE";
|
|
18
|
+
const CLOSE = `CLOSE ${CURSOR}`;
|
|
19
|
+
const DECLARE = `DECLARE ${CURSOR} NO SCROLL CURSOR FOR ${SQL}`;
|
|
20
|
+
const FETCH = `FETCH FORWARD ${BATCH_SIZE} FROM ${CURSOR}`;
|
|
21
|
+
const FETCH_PREFIX = "FETCH FORWARD";
|
|
22
|
+
const PARAM_MARKER = /\$\d/;
|
|
23
|
+
const OPTIONS = {
|
|
24
|
+
cursorBatchSize: BATCH_SIZE,
|
|
25
|
+
cursorIdleTimeoutMs: IDLE_TIMEOUT_MS,
|
|
26
|
+
};
|
|
27
|
+
const REAPING = {
|
|
28
|
+
cursorBatchSize: BATCH_SIZE,
|
|
29
|
+
cursorIdleTimeoutMs: REAPED_AFTER_MS,
|
|
30
|
+
};
|
|
31
|
+
const PROBING = {
|
|
32
|
+
cursorBatchSize: BATCH_SIZE,
|
|
33
|
+
cursorIdleTimeoutMs: REAPER_PROBE_MS,
|
|
34
|
+
};
|
|
35
|
+
const NO_VALUES = [];
|
|
36
|
+
const STUB_FAILURE = "the stub client refused this statement";
|
|
37
|
+
const NEVER_ENDED = "the cursor never answered done";
|
|
38
|
+
const NEVER_REJECTED = "the read was expected to reject";
|
|
39
|
+
const NEVER_ARRIVED = "no read arrived while the sweep was running";
|
|
40
|
+
const NEVER_HELD = "the stub never reached the statement it was told to hold";
|
|
41
|
+
const DOUBLE_RELEASE = "this client was already handed back to the pool";
|
|
42
|
+
const DRAIN_LIMIT = 50;
|
|
43
|
+
const SETTLE_TURNS = 8;
|
|
44
|
+
const NOT_OBSERVED = -1;
|
|
45
|
+
const FORGOTTEN_HINT = "no longer remembered";
|
|
46
|
+
const DESCENDING_CURSORS = 4;
|
|
47
|
+
const DECLARE_POSITION = 1;
|
|
48
|
+
const STALE_TIMER = 0;
|
|
49
|
+
const LAST_TIMER = 1;
|
|
50
|
+
const NEXT_TURN_MS = 0;
|
|
51
|
+
const IDLE_TIMEOUT_OPTION = "cursorIdleTimeoutMs";
|
|
52
|
+
const REMEMBERED_ENDINGS = 1024;
|
|
53
|
+
const FIRST_SPEC_REQ_ID = -1;
|
|
54
|
+
function Recorder() {
|
|
55
|
+
return { statements: [], bound: [], releases: 0, acquires: 0 };
|
|
56
|
+
}
|
|
57
|
+
function StubClient(log, batches, failing) {
|
|
58
|
+
let isReleased = false;
|
|
59
|
+
const stub = {
|
|
60
|
+
query: (sql, values) => {
|
|
61
|
+
log.statements.push(sql);
|
|
62
|
+
log.bound.push(values ?? NO_VALUES);
|
|
63
|
+
if (sql === failing) {
|
|
64
|
+
return Promise.reject(new Error(STUB_FAILURE));
|
|
65
|
+
}
|
|
66
|
+
if (sql === log.holdsStatement) {
|
|
67
|
+
log.holdsStatement = undefined;
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
log.resumeHeld = () => resolve({ rows: [] });
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (!sql.startsWith(FETCH_PREFIX)) {
|
|
73
|
+
return Promise.resolve({ rows: [] });
|
|
74
|
+
}
|
|
75
|
+
const rows = batches.shift() ?? [];
|
|
76
|
+
if (!log.holdsNextFetch) {
|
|
77
|
+
return Promise.resolve({ rows });
|
|
78
|
+
}
|
|
79
|
+
log.holdsNextFetch = false;
|
|
80
|
+
return new Promise((resolve) => {
|
|
81
|
+
log.resumeFetch = () => resolve({ rows });
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
release: () => {
|
|
85
|
+
log.statements.push(RELEASE);
|
|
86
|
+
log.bound.push(NO_VALUES);
|
|
87
|
+
log.releases += 1;
|
|
88
|
+
if (isReleased) {
|
|
89
|
+
throw new Error(DOUBLE_RELEASE);
|
|
90
|
+
}
|
|
91
|
+
isReleased = true;
|
|
92
|
+
log.whenReleased?.();
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
return stub;
|
|
96
|
+
}
|
|
97
|
+
function Decode(rows) {
|
|
98
|
+
return rows.map((row) => row.n);
|
|
99
|
+
}
|
|
100
|
+
function Requesting(log, batches, failing) {
|
|
101
|
+
return () => Promise.resolve({
|
|
102
|
+
sql: SQL,
|
|
103
|
+
params: PARAMS,
|
|
104
|
+
decode: Decode,
|
|
105
|
+
acquire: () => {
|
|
106
|
+
log.acquires += 1;
|
|
107
|
+
return Promise.resolve(StubClient(log, batches, failing));
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function Rows(...values) {
|
|
112
|
+
return values.map((n) => ({ n }));
|
|
113
|
+
}
|
|
114
|
+
function Reopening(log, ...values) {
|
|
115
|
+
return () => Promise.resolve({
|
|
116
|
+
sql: SQL,
|
|
117
|
+
params: PARAMS,
|
|
118
|
+
decode: Decode,
|
|
119
|
+
acquire: () => {
|
|
120
|
+
log.acquires += 1;
|
|
121
|
+
return Promise.resolve(StubClient(log, [Rows(...values)]));
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
let lastReqId = FIRST_SPEC_REQ_ID + 1;
|
|
126
|
+
let claimed = [];
|
|
127
|
+
function NextReqId() {
|
|
128
|
+
lastReqId -= 1;
|
|
129
|
+
claimed.push(lastReqId);
|
|
130
|
+
return lastReqId;
|
|
131
|
+
}
|
|
132
|
+
function Read(reqId, open, options = OPTIONS) {
|
|
133
|
+
return (0, spec_fixture_1.WithOptions)(options, () => (0, cursors_1.ReadCursorRow)(reqId, open));
|
|
134
|
+
}
|
|
135
|
+
async function Drain(reqId, open) {
|
|
136
|
+
const values = [];
|
|
137
|
+
while (values.length < DRAIN_LIMIT) {
|
|
138
|
+
const next = await Read(reqId, open);
|
|
139
|
+
if (next.done) {
|
|
140
|
+
return values;
|
|
141
|
+
}
|
|
142
|
+
values.push(next.value);
|
|
143
|
+
}
|
|
144
|
+
throw new Error(NEVER_ENDED);
|
|
145
|
+
}
|
|
146
|
+
async function Rejection(read) {
|
|
147
|
+
try {
|
|
148
|
+
await read;
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
return err;
|
|
152
|
+
}
|
|
153
|
+
throw new Error(NEVER_REJECTED);
|
|
154
|
+
}
|
|
155
|
+
function Delay(ms) {
|
|
156
|
+
return new Promise((resolve) => {
|
|
157
|
+
setTimeout(resolve, ms).unref();
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
async function Settle() {
|
|
161
|
+
for (let turn = 0; turn < SETTLE_TURNS; turn += 1) {
|
|
162
|
+
await Delay(NEXT_TURN_MS);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function WhenHeld(log) {
|
|
166
|
+
for (let turn = 0; turn < DRAIN_LIMIT; turn += 1) {
|
|
167
|
+
if (log.resumeHeld) {
|
|
168
|
+
return log.resumeHeld;
|
|
169
|
+
}
|
|
170
|
+
await Delay(NEXT_TURN_MS);
|
|
171
|
+
}
|
|
172
|
+
throw new Error(NEVER_HELD);
|
|
173
|
+
}
|
|
174
|
+
async function OverflowEndings() {
|
|
175
|
+
const filler = Recorder();
|
|
176
|
+
for (let index = 0; index < REMEMBERED_ENDINGS; index += 1) {
|
|
177
|
+
await Read(NextReqId(), Requesting(filler, [Rows()]));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function TimerRecorder() {
|
|
181
|
+
return { armed: [], handlers: [], cleared: [] };
|
|
182
|
+
}
|
|
183
|
+
async function CapturingTimers(log, delayMs, body) {
|
|
184
|
+
const realSet = globalThis.setTimeout;
|
|
185
|
+
const realClear = globalThis.clearTimeout;
|
|
186
|
+
globalThis.setTimeout = ((handler, ms, ...rest) => {
|
|
187
|
+
const timer = realSet(handler, ms, ...rest);
|
|
188
|
+
if (ms === delayMs) {
|
|
189
|
+
log.armed.push(timer);
|
|
190
|
+
log.handlers.push(handler);
|
|
191
|
+
}
|
|
192
|
+
return timer;
|
|
193
|
+
});
|
|
194
|
+
globalThis.clearTimeout = ((timer) => {
|
|
195
|
+
if (log.armed.includes(timer)) {
|
|
196
|
+
log.cleared.push(timer);
|
|
197
|
+
}
|
|
198
|
+
realClear(timer);
|
|
199
|
+
});
|
|
200
|
+
try {
|
|
201
|
+
await body();
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
globalThis.setTimeout = realSet;
|
|
205
|
+
globalThis.clearTimeout = realClear;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function Count(log, statement) {
|
|
209
|
+
return log.statements.filter((sql) => sql === statement).length;
|
|
210
|
+
}
|
|
211
|
+
describe("the cursor registry", () => {
|
|
212
|
+
let baseline = 0;
|
|
213
|
+
beforeEach(() => {
|
|
214
|
+
baseline = (0, cursors_1.CountOpenCursors)();
|
|
215
|
+
claimed = [];
|
|
216
|
+
});
|
|
217
|
+
afterEach(async () => {
|
|
218
|
+
const held = (0, cursors_1.CountOpenCursors)();
|
|
219
|
+
await Promise.all(claimed.map((reqId) => (0, cursors_1.CloseOneCursor)(reqId)));
|
|
220
|
+
(0, chai_1.expect)(held).to.be.at.most(baseline);
|
|
221
|
+
});
|
|
222
|
+
it("refuses both ends of a forgotten range, its highest id evicted first", async () => {
|
|
223
|
+
const upper = Recorder();
|
|
224
|
+
const lower = Recorder();
|
|
225
|
+
const upperId = NextReqId();
|
|
226
|
+
const lowerId = NextReqId();
|
|
227
|
+
(0, chai_1.expect)(upperId).to.equal(FIRST_SPEC_REQ_ID);
|
|
228
|
+
const openUpper = Reopening(upper, 1, 2);
|
|
229
|
+
const openLower = Reopening(lower, 3, 4);
|
|
230
|
+
(0, chai_1.expect)(await Drain(upperId, openUpper)).to.deep.equal([1, 2]);
|
|
231
|
+
(0, chai_1.expect)(await Drain(lowerId, openLower)).to.deep.equal([3, 4]);
|
|
232
|
+
await OverflowEndings();
|
|
233
|
+
const refusedUpper = await Rejection(Read(upperId, openUpper));
|
|
234
|
+
const refusedLower = await Rejection(Read(lowerId, openLower));
|
|
235
|
+
(0, chai_1.expect)(refusedUpper.message).to.contain(`${upperId}`);
|
|
236
|
+
(0, chai_1.expect)(refusedUpper.message).to.contain(FORGOTTEN_HINT);
|
|
237
|
+
(0, chai_1.expect)(refusedLower.message).to.contain(`${lowerId}`);
|
|
238
|
+
(0, chai_1.expect)(refusedLower.message).to.contain(FORGOTTEN_HINT);
|
|
239
|
+
(0, chai_1.expect)([upper.acquires, lower.acquires]).to.deep.equal([1, 1]);
|
|
240
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
241
|
+
});
|
|
242
|
+
it("yields a full batch and then a short one, in order, and then ends", async () => {
|
|
243
|
+
const log = Recorder();
|
|
244
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4, 5)]);
|
|
245
|
+
(0, chai_1.expect)(await Drain(NextReqId(), open)).to.deep.equal([1, 2, 3, 4, 5]);
|
|
246
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([
|
|
247
|
+
BEGIN,
|
|
248
|
+
DECLARE,
|
|
249
|
+
FETCH,
|
|
250
|
+
FETCH,
|
|
251
|
+
CLOSE,
|
|
252
|
+
ROLLBACK,
|
|
253
|
+
RELEASE,
|
|
254
|
+
]);
|
|
255
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
256
|
+
});
|
|
257
|
+
it("ends after a short first batch without fetching a second time", async () => {
|
|
258
|
+
const log = Recorder();
|
|
259
|
+
const open = Requesting(log, [Rows(1, 2)]);
|
|
260
|
+
(0, chai_1.expect)(await Drain(NextReqId(), open)).to.deep.equal([1, 2]);
|
|
261
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([
|
|
262
|
+
BEGIN,
|
|
263
|
+
DECLARE,
|
|
264
|
+
FETCH,
|
|
265
|
+
CLOSE,
|
|
266
|
+
ROLLBACK,
|
|
267
|
+
RELEASE,
|
|
268
|
+
]);
|
|
269
|
+
});
|
|
270
|
+
it("ends immediately over a cursor that read no rows", async () => {
|
|
271
|
+
const log = Recorder();
|
|
272
|
+
const open = Requesting(log, [Rows()]);
|
|
273
|
+
const next = await Read(NextReqId(), open);
|
|
274
|
+
(0, chai_1.expect)(next.done).to.equal(true);
|
|
275
|
+
(0, chai_1.expect)(next.value).to.equal(undefined);
|
|
276
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([
|
|
277
|
+
BEGIN,
|
|
278
|
+
DECLARE,
|
|
279
|
+
FETCH,
|
|
280
|
+
CLOSE,
|
|
281
|
+
ROLLBACK,
|
|
282
|
+
RELEASE,
|
|
283
|
+
]);
|
|
284
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
285
|
+
});
|
|
286
|
+
it("rolls back after closing the cursor and before handing the client back", async () => {
|
|
287
|
+
const log = Recorder();
|
|
288
|
+
const open = Requesting(log, [Rows(1)]);
|
|
289
|
+
await Drain(NextReqId(), open);
|
|
290
|
+
const closed = log.statements.indexOf(CLOSE);
|
|
291
|
+
const rolled = log.statements.indexOf(ROLLBACK);
|
|
292
|
+
const released = log.statements.indexOf(RELEASE);
|
|
293
|
+
(0, chai_1.expect)(closed).to.be.lessThan(rolled);
|
|
294
|
+
(0, chai_1.expect)(rolled).to.be.lessThan(released);
|
|
295
|
+
});
|
|
296
|
+
it("holds one registration while iterating and none once exhausted", async () => {
|
|
297
|
+
const log = Recorder();
|
|
298
|
+
const reqId = NextReqId();
|
|
299
|
+
const open = Requesting(log, [Rows(1, 2)]);
|
|
300
|
+
await Read(reqId, open);
|
|
301
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline + 1);
|
|
302
|
+
await Read(reqId, open);
|
|
303
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline + 1);
|
|
304
|
+
(0, chai_1.expect)((await Read(reqId, open)).done).to.equal(true);
|
|
305
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
306
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
307
|
+
});
|
|
308
|
+
it("stays done after exhaustion, acquiring nothing", async () => {
|
|
309
|
+
const log = Recorder();
|
|
310
|
+
const reqId = NextReqId();
|
|
311
|
+
const open = Requesting(log, [Rows(1)]);
|
|
312
|
+
(0, chai_1.expect)(await Drain(reqId, open)).to.deep.equal([1]);
|
|
313
|
+
const after = await Read(reqId, open);
|
|
314
|
+
(0, chai_1.expect)(after.done).to.equal(true);
|
|
315
|
+
(0, chai_1.expect)(after.value).to.equal(undefined);
|
|
316
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
317
|
+
(0, chai_1.expect)(Count(log, BEGIN)).to.equal(1);
|
|
318
|
+
(0, chai_1.expect)(Count(log, DECLARE)).to.equal(1);
|
|
319
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
320
|
+
});
|
|
321
|
+
it("stays done after an explicit close, acquiring nothing", async () => {
|
|
322
|
+
const log = Recorder();
|
|
323
|
+
const reqId = NextReqId();
|
|
324
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
325
|
+
(0, chai_1.expect)((await Read(reqId, open)).value).to.equal(1);
|
|
326
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
327
|
+
const after = await Read(reqId, open);
|
|
328
|
+
(0, chai_1.expect)(after.done).to.equal(true);
|
|
329
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
330
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
331
|
+
(0, chai_1.expect)(Count(log, FETCH)).to.equal(1);
|
|
332
|
+
});
|
|
333
|
+
it("answers four concurrent reads over a two-row cursor on one client", async () => {
|
|
334
|
+
const log = Recorder();
|
|
335
|
+
const reqId = NextReqId();
|
|
336
|
+
const open = Requesting(log, [Rows(1, 2)]);
|
|
337
|
+
const answers = await Promise.all([
|
|
338
|
+
Read(reqId, open),
|
|
339
|
+
Read(reqId, open),
|
|
340
|
+
Read(reqId, open),
|
|
341
|
+
Read(reqId, open),
|
|
342
|
+
]);
|
|
343
|
+
(0, chai_1.expect)(answers.map((answer) => answer.value)).to.deep.equal([
|
|
344
|
+
1,
|
|
345
|
+
2,
|
|
346
|
+
undefined,
|
|
347
|
+
undefined,
|
|
348
|
+
]);
|
|
349
|
+
(0, chai_1.expect)(answers.map((answer) => answer.done)).to.deep.equal([
|
|
350
|
+
false,
|
|
351
|
+
false,
|
|
352
|
+
true,
|
|
353
|
+
true,
|
|
354
|
+
]);
|
|
355
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
356
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
357
|
+
(0, chai_1.expect)(Count(log, BEGIN)).to.equal(1);
|
|
358
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
359
|
+
});
|
|
360
|
+
it("throws on a read after the idle reaper reclaimed the cursor", async () => {
|
|
361
|
+
const log = Recorder();
|
|
362
|
+
const reqId = NextReqId();
|
|
363
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
364
|
+
(0, chai_1.expect)((await Read(reqId, open, REAPING)).value).to.equal(1);
|
|
365
|
+
await Delay(REAP_WINDOW_MS);
|
|
366
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
367
|
+
const err = await Rejection(Read(reqId, open));
|
|
368
|
+
(0, chai_1.expect)(err.message).to.contain(IDLE_TIMEOUT_OPTION);
|
|
369
|
+
(0, chai_1.expect)(err.message).to.contain(`${REAPED_AFTER_MS} ms`);
|
|
370
|
+
(0, chai_1.expect)(err.message).to.contain(`${reqId}`);
|
|
371
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
372
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
373
|
+
});
|
|
374
|
+
it("releases exactly once when closed part-way through", async () => {
|
|
375
|
+
const log = Recorder();
|
|
376
|
+
const reqId = NextReqId();
|
|
377
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
378
|
+
(0, chai_1.expect)((await Read(reqId, open)).value).to.equal(1);
|
|
379
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
380
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([
|
|
381
|
+
BEGIN,
|
|
382
|
+
DECLARE,
|
|
383
|
+
FETCH,
|
|
384
|
+
CLOSE,
|
|
385
|
+
ROLLBACK,
|
|
386
|
+
RELEASE,
|
|
387
|
+
]);
|
|
388
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
389
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
390
|
+
});
|
|
391
|
+
it("closes behind a read that is still in flight, and answers it first", async () => {
|
|
392
|
+
const log = Recorder();
|
|
393
|
+
const reqId = NextReqId();
|
|
394
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
395
|
+
const reading = Read(reqId, open);
|
|
396
|
+
const closing = (0, cursors_1.CloseOneCursor)(reqId);
|
|
397
|
+
const first = await reading;
|
|
398
|
+
await closing;
|
|
399
|
+
(0, chai_1.expect)(first.value).to.equal(1);
|
|
400
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([
|
|
401
|
+
BEGIN,
|
|
402
|
+
DECLARE,
|
|
403
|
+
FETCH,
|
|
404
|
+
CLOSE,
|
|
405
|
+
ROLLBACK,
|
|
406
|
+
RELEASE,
|
|
407
|
+
]);
|
|
408
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
409
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
410
|
+
});
|
|
411
|
+
it("does nothing on a second close, and nothing on a close after exhaustion", async () => {
|
|
412
|
+
const log = Recorder();
|
|
413
|
+
const reqId = NextReqId();
|
|
414
|
+
const open = Requesting(log, [Rows(1, 2)]);
|
|
415
|
+
await Drain(reqId, open);
|
|
416
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
417
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
418
|
+
(0, chai_1.expect)(Count(log, CLOSE)).to.equal(1);
|
|
419
|
+
(0, chai_1.expect)(Count(log, ROLLBACK)).to.equal(1);
|
|
420
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
421
|
+
});
|
|
422
|
+
it("acquires nothing on a close for a reqId that never opened", async () => {
|
|
423
|
+
await (0, cursors_1.CloseOneCursor)(NextReqId());
|
|
424
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
425
|
+
});
|
|
426
|
+
it("answers done, acquiring nothing, after a close that preceded every read", async () => {
|
|
427
|
+
const log = Recorder();
|
|
428
|
+
const reqId = NextReqId();
|
|
429
|
+
const open = Reopening(log, 1, 2);
|
|
430
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
431
|
+
const after = await Read(reqId, open);
|
|
432
|
+
(0, chai_1.expect)(after.done).to.equal(true);
|
|
433
|
+
(0, chai_1.expect)(after.value).to.equal(undefined);
|
|
434
|
+
(0, chai_1.expect)(log.acquires).to.equal(0);
|
|
435
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([]);
|
|
436
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
437
|
+
});
|
|
438
|
+
it("forgets a close that preceded every read, like any other ending", async () => {
|
|
439
|
+
const log = Recorder();
|
|
440
|
+
const reqId = NextReqId();
|
|
441
|
+
const open = Reopening(log, 1, 2);
|
|
442
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
443
|
+
await OverflowEndings();
|
|
444
|
+
const err = await Rejection(Read(reqId, open));
|
|
445
|
+
(0, chai_1.expect)(err.message).to.contain(`${reqId}`);
|
|
446
|
+
(0, chai_1.expect)(err.message).to.contain(FORGOTTEN_HINT);
|
|
447
|
+
(0, chai_1.expect)(log.acquires).to.equal(0);
|
|
448
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
449
|
+
});
|
|
450
|
+
it("rolls back and releases when the DECLARE is refused, registering nothing", async () => {
|
|
451
|
+
const log = Recorder();
|
|
452
|
+
const reqId = NextReqId();
|
|
453
|
+
const open = Requesting(log, [], DECLARE);
|
|
454
|
+
const err = await Rejection(Read(reqId, open));
|
|
455
|
+
(0, chai_1.expect)(err.message).to.equal(STUB_FAILURE);
|
|
456
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([BEGIN, DECLARE, ROLLBACK, RELEASE]);
|
|
457
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
458
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
459
|
+
(0, chai_1.expect)((await Read(reqId, open)).done).to.equal(true);
|
|
460
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
461
|
+
});
|
|
462
|
+
it("releases without rolling back when the BEGIN itself is refused", async () => {
|
|
463
|
+
const log = Recorder();
|
|
464
|
+
const open = Requesting(log, [], BEGIN);
|
|
465
|
+
await Rejection(Read(NextReqId(), open));
|
|
466
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([BEGIN, RELEASE]);
|
|
467
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
468
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
469
|
+
});
|
|
470
|
+
it("acquires nothing when the statement never compiled", async () => {
|
|
471
|
+
const log = Recorder();
|
|
472
|
+
const refused = new Error("this stage array compiles no relation");
|
|
473
|
+
const err = await Rejection(Read(NextReqId(), () => Promise.reject(refused)));
|
|
474
|
+
(0, chai_1.expect)(err).to.equal(refused);
|
|
475
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([]);
|
|
476
|
+
(0, chai_1.expect)(log.acquires).to.equal(0);
|
|
477
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
478
|
+
});
|
|
479
|
+
it("rolls back and releases when a FETCH is refused", async () => {
|
|
480
|
+
const log = Recorder();
|
|
481
|
+
const open = Requesting(log, [Rows(1, 2, 3)], FETCH);
|
|
482
|
+
await Rejection(Read(NextReqId(), open));
|
|
483
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([
|
|
484
|
+
BEGIN,
|
|
485
|
+
DECLARE,
|
|
486
|
+
FETCH,
|
|
487
|
+
CLOSE,
|
|
488
|
+
ROLLBACK,
|
|
489
|
+
RELEASE,
|
|
490
|
+
]);
|
|
491
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
492
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
493
|
+
});
|
|
494
|
+
it("answers two concurrent reads consecutive rows, over one open and one fetch", async () => {
|
|
495
|
+
const log = Recorder();
|
|
496
|
+
const reqId = NextReqId();
|
|
497
|
+
const open = Requesting(log, [Rows(1, 2, 3)]);
|
|
498
|
+
const [first, second] = await Promise.all([
|
|
499
|
+
Read(reqId, open),
|
|
500
|
+
Read(reqId, open),
|
|
501
|
+
]);
|
|
502
|
+
(0, chai_1.expect)([first.value, second.value]).to.deep.equal([1, 2]);
|
|
503
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([BEGIN, DECLARE, FETCH]);
|
|
504
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
505
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
506
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
507
|
+
});
|
|
508
|
+
it("arms an unreferenced reaper on every read", async () => {
|
|
509
|
+
const log = Recorder();
|
|
510
|
+
const reqId = NextReqId();
|
|
511
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
512
|
+
const timers = TimerRecorder();
|
|
513
|
+
await CapturingTimers(timers, REAPER_PROBE_MS, async () => {
|
|
514
|
+
await Read(reqId, open, PROBING);
|
|
515
|
+
await Read(reqId, open, PROBING);
|
|
516
|
+
await Read(reqId, open, PROBING);
|
|
517
|
+
});
|
|
518
|
+
(0, chai_1.expect)(timers.armed).to.have.length(3);
|
|
519
|
+
(0, chai_1.expect)(timers.armed.map((timer) => timer.hasRef())).to.deep.equal([
|
|
520
|
+
false,
|
|
521
|
+
false,
|
|
522
|
+
false,
|
|
523
|
+
]);
|
|
524
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
525
|
+
});
|
|
526
|
+
it("clears the reaper it armed on the previous read, and the last one on close", async () => {
|
|
527
|
+
const log = Recorder();
|
|
528
|
+
const reqId = NextReqId();
|
|
529
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
530
|
+
const timers = TimerRecorder();
|
|
531
|
+
await CapturingTimers(timers, REAPER_PROBE_MS, async () => {
|
|
532
|
+
await Read(reqId, open, PROBING);
|
|
533
|
+
await Read(reqId, open, PROBING);
|
|
534
|
+
await Read(reqId, open, PROBING);
|
|
535
|
+
(0, chai_1.expect)(timers.cleared).to.deep.equal([timers.armed[0], timers.armed[1]]);
|
|
536
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
537
|
+
});
|
|
538
|
+
(0, chai_1.expect)(timers.cleared).to.deep.equal(timers.armed);
|
|
539
|
+
});
|
|
540
|
+
it("ignores a reaper timer that fired before a read re-armed it", async () => {
|
|
541
|
+
const log = Recorder();
|
|
542
|
+
const reqId = NextReqId();
|
|
543
|
+
const open = Requesting(log, [Rows(1, 2, 3)]);
|
|
544
|
+
const timers = TimerRecorder();
|
|
545
|
+
await CapturingTimers(timers, REAPER_PROBE_MS, async () => {
|
|
546
|
+
await Read(reqId, open, PROBING);
|
|
547
|
+
await Read(reqId, open, PROBING);
|
|
548
|
+
});
|
|
549
|
+
timers.handlers[STALE_TIMER]();
|
|
550
|
+
await Delay(REAP_WINDOW_MS);
|
|
551
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([BEGIN, DECLARE, FETCH]);
|
|
552
|
+
(0, chai_1.expect)(log.releases).to.equal(0);
|
|
553
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline + 1);
|
|
554
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
555
|
+
});
|
|
556
|
+
it("keeps a reaper that fires mid-read from cutting into the read", async () => {
|
|
557
|
+
const log = Recorder();
|
|
558
|
+
const reqId = NextReqId();
|
|
559
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4, 5, 6)]);
|
|
560
|
+
const timers = TimerRecorder();
|
|
561
|
+
await CapturingTimers(timers, REAPER_PROBE_MS, async () => {
|
|
562
|
+
await Read(reqId, open, PROBING);
|
|
563
|
+
await Read(reqId, open, PROBING);
|
|
564
|
+
await Read(reqId, open, PROBING);
|
|
565
|
+
log.holdsNextFetch = true;
|
|
566
|
+
const held = Read(reqId, open, PROBING);
|
|
567
|
+
while (!log.resumeFetch) {
|
|
568
|
+
await Delay(NEXT_TURN_MS);
|
|
569
|
+
}
|
|
570
|
+
timers.handlers[timers.handlers.length - LAST_TIMER]();
|
|
571
|
+
log.resumeFetch();
|
|
572
|
+
(0, chai_1.expect)((await held).value).to.equal(4);
|
|
573
|
+
});
|
|
574
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([BEGIN, DECLARE, FETCH, FETCH]);
|
|
575
|
+
(0, chai_1.expect)(log.releases).to.equal(0);
|
|
576
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
577
|
+
});
|
|
578
|
+
it("reclaims a cursor left idle past its timeout, through the same teardown", async () => {
|
|
579
|
+
const log = Recorder();
|
|
580
|
+
const reqId = NextReqId();
|
|
581
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
582
|
+
(0, chai_1.expect)((await Read(reqId, open, REAPING)).value).to.equal(1);
|
|
583
|
+
await Delay(REAP_WINDOW_MS);
|
|
584
|
+
(0, chai_1.expect)(log.statements).to.deep.equal([
|
|
585
|
+
BEGIN,
|
|
586
|
+
DECLARE,
|
|
587
|
+
FETCH,
|
|
588
|
+
CLOSE,
|
|
589
|
+
ROLLBACK,
|
|
590
|
+
RELEASE,
|
|
591
|
+
]);
|
|
592
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
593
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
594
|
+
});
|
|
595
|
+
it("fetches a literal count and binds no parameter to it", async () => {
|
|
596
|
+
const log = Recorder();
|
|
597
|
+
const reqId = NextReqId();
|
|
598
|
+
const open = Requesting(log, [Rows(1, 2, 3)]);
|
|
599
|
+
await Read(reqId, open);
|
|
600
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
601
|
+
const fetched = log.statements.indexOf(FETCH);
|
|
602
|
+
(0, chai_1.expect)(log.statements[fetched]).to.equal(`FETCH FORWARD 3 FROM "antelopejs_cursor"`);
|
|
603
|
+
(0, chai_1.expect)(log.statements[fetched]).to.not.match(PARAM_MARKER);
|
|
604
|
+
(0, chai_1.expect)(log.bound[fetched]).to.deep.equal([]);
|
|
605
|
+
});
|
|
606
|
+
it("binds the rendered statement's parameters on the DECLARE", async () => {
|
|
607
|
+
const log = Recorder();
|
|
608
|
+
const reqId = NextReqId();
|
|
609
|
+
const open = Requesting(log, [Rows(1)]);
|
|
610
|
+
await Read(reqId, open);
|
|
611
|
+
await (0, cursors_1.CloseOneCursor)(reqId);
|
|
612
|
+
(0, chai_1.expect)(log.statements[DECLARE_POSITION]).to.equal(DECLARE);
|
|
613
|
+
(0, chai_1.expect)(log.statements[DECLARE_POSITION]).to.match(PARAM_MARKER);
|
|
614
|
+
(0, chai_1.expect)(log.bound[DECLARE_POSITION]).to.deep.equal(PARAMS);
|
|
615
|
+
});
|
|
616
|
+
it("closes every open cursor, and empties the registry", async () => {
|
|
617
|
+
const first = Recorder();
|
|
618
|
+
const second = Recorder();
|
|
619
|
+
await Read(NextReqId(), Requesting(first, [Rows(1, 2, 3)]));
|
|
620
|
+
await Read(NextReqId(), Requesting(second, [Rows(4, 5, 6)]));
|
|
621
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline + 2);
|
|
622
|
+
await (0, cursors_1.CloseAllCursors)();
|
|
623
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(0);
|
|
624
|
+
(0, chai_1.expect)([first.releases, second.releases]).to.deep.equal([1, 1]);
|
|
625
|
+
(0, chai_1.expect)([Count(first, ROLLBACK), Count(second, ROLLBACK)]).to.deep.equal([
|
|
626
|
+
1, 1,
|
|
627
|
+
]);
|
|
628
|
+
});
|
|
629
|
+
it("opens nothing for a read that arrives while the sweep is running", async () => {
|
|
630
|
+
const held = Recorder();
|
|
631
|
+
const arriving = Recorder();
|
|
632
|
+
const heldId = NextReqId();
|
|
633
|
+
const arrivingId = NextReqId();
|
|
634
|
+
const openArriving = Requesting(arriving, [Rows(7, 8, 9)]);
|
|
635
|
+
let late;
|
|
636
|
+
let isAnswered = false;
|
|
637
|
+
held.whenReleased = () => {
|
|
638
|
+
late =
|
|
639
|
+
late ??
|
|
640
|
+
Read(arrivingId, openArriving).then((answer) => {
|
|
641
|
+
isAnswered = true;
|
|
642
|
+
return answer;
|
|
643
|
+
});
|
|
644
|
+
};
|
|
645
|
+
const openHeld = Requesting(held, [Rows(1, 2, 3), Rows(4, 5, 6)]);
|
|
646
|
+
(0, chai_1.expect)((await Read(heldId, openHeld)).value).to.equal(1);
|
|
647
|
+
await (0, cursors_1.CloseAllCursors)();
|
|
648
|
+
if (!late) {
|
|
649
|
+
throw new Error(NEVER_ARRIVED);
|
|
650
|
+
}
|
|
651
|
+
(0, chai_1.expect)(isAnswered).to.equal(true);
|
|
652
|
+
(0, chai_1.expect)((await late).done).to.equal(true);
|
|
653
|
+
(0, chai_1.expect)(arriving.acquires).to.equal(0);
|
|
654
|
+
(0, chai_1.expect)(arriving.statements).to.deep.equal([]);
|
|
655
|
+
(0, chai_1.expect)(held.acquires).to.equal(1);
|
|
656
|
+
(0, chai_1.expect)(held.releases).to.equal(1);
|
|
657
|
+
});
|
|
658
|
+
it("counts a cursor whose teardown is still on the wire as checked out", async () => {
|
|
659
|
+
const log = Recorder();
|
|
660
|
+
const reqId = NextReqId();
|
|
661
|
+
const open = Requesting(log, [Rows(1)]);
|
|
662
|
+
(0, chai_1.expect)((await Read(reqId, open)).value).to.equal(1);
|
|
663
|
+
log.holdsStatement = CLOSE;
|
|
664
|
+
const ending = Read(reqId, open);
|
|
665
|
+
const resume = await WhenHeld(log);
|
|
666
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline + 1);
|
|
667
|
+
(0, chai_1.expect)(log.releases).to.equal(0);
|
|
668
|
+
resume();
|
|
669
|
+
(0, chai_1.expect)((await ending).done).to.equal(true);
|
|
670
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
671
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
672
|
+
});
|
|
673
|
+
it("does not resolve the sweep while a self-reclaim is still on the wire", async () => {
|
|
674
|
+
const log = Recorder();
|
|
675
|
+
const reqId = NextReqId();
|
|
676
|
+
const open = Requesting(log, [Rows(1)]);
|
|
677
|
+
(0, chai_1.expect)((await Read(reqId, open)).value).to.equal(1);
|
|
678
|
+
log.holdsStatement = CLOSE;
|
|
679
|
+
const ending = Read(reqId, open);
|
|
680
|
+
const resume = await WhenHeld(log);
|
|
681
|
+
let isSwept = false;
|
|
682
|
+
const sweeping = (0, cursors_1.CloseAllCursors)().then(() => {
|
|
683
|
+
isSwept = true;
|
|
684
|
+
});
|
|
685
|
+
await Settle();
|
|
686
|
+
(0, chai_1.expect)(isSwept).to.equal(false);
|
|
687
|
+
(0, chai_1.expect)(log.releases).to.equal(0);
|
|
688
|
+
resume();
|
|
689
|
+
await sweeping;
|
|
690
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
691
|
+
(0, chai_1.expect)((await ending).done).to.equal(true);
|
|
692
|
+
});
|
|
693
|
+
it("does not resolve the sweep while an explicit close is still on the wire", async () => {
|
|
694
|
+
const log = Recorder();
|
|
695
|
+
const reqId = NextReqId();
|
|
696
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
697
|
+
(0, chai_1.expect)((await Read(reqId, open)).value).to.equal(1);
|
|
698
|
+
log.holdsStatement = CLOSE;
|
|
699
|
+
const closing = (0, cursors_1.CloseOneCursor)(reqId);
|
|
700
|
+
const resume = await WhenHeld(log);
|
|
701
|
+
let isSwept = false;
|
|
702
|
+
const sweeping = (0, cursors_1.CloseAllCursors)().then(() => {
|
|
703
|
+
isSwept = true;
|
|
704
|
+
});
|
|
705
|
+
await Settle();
|
|
706
|
+
(0, chai_1.expect)(isSwept).to.equal(false);
|
|
707
|
+
(0, chai_1.expect)(log.releases).to.equal(0);
|
|
708
|
+
resume();
|
|
709
|
+
await Promise.all([closing, sweeping]);
|
|
710
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
711
|
+
});
|
|
712
|
+
it("does not resolve the sweep while a reaper teardown is still on the wire", async () => {
|
|
713
|
+
const log = Recorder();
|
|
714
|
+
const reqId = NextReqId();
|
|
715
|
+
const open = Requesting(log, [Rows(1, 2, 3), Rows(4)]);
|
|
716
|
+
log.holdsStatement = CLOSE;
|
|
717
|
+
(0, chai_1.expect)((await Read(reqId, open, REAPING)).value).to.equal(1);
|
|
718
|
+
const resume = await WhenHeld(log);
|
|
719
|
+
let isSwept = false;
|
|
720
|
+
const sweeping = (0, cursors_1.CloseAllCursors)().then(() => {
|
|
721
|
+
isSwept = true;
|
|
722
|
+
});
|
|
723
|
+
await Settle();
|
|
724
|
+
(0, chai_1.expect)(isSwept).to.equal(false);
|
|
725
|
+
(0, chai_1.expect)(log.releases).to.equal(0);
|
|
726
|
+
resume();
|
|
727
|
+
await sweeping;
|
|
728
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
729
|
+
});
|
|
730
|
+
it("hands every client back before the pool is ended", async () => {
|
|
731
|
+
const log = Recorder();
|
|
732
|
+
const reqId = NextReqId();
|
|
733
|
+
const open = Requesting(log, [Rows(1)]);
|
|
734
|
+
(0, chai_1.expect)((await Read(reqId, open)).value).to.equal(1);
|
|
735
|
+
log.holdsStatement = CLOSE;
|
|
736
|
+
const ending = Read(reqId, open);
|
|
737
|
+
const resume = await WhenHeld(log);
|
|
738
|
+
let checkedOutAtEnd = NOT_OBSERVED;
|
|
739
|
+
let releasesAtEnd = NOT_OBSERVED;
|
|
740
|
+
const disconnecting = (0, connection_1.SettleBeforeDisconnect)(() => {
|
|
741
|
+
checkedOutAtEnd = (0, cursors_1.CountOpenCursors)();
|
|
742
|
+
releasesAtEnd = log.releases;
|
|
743
|
+
return Promise.resolve();
|
|
744
|
+
});
|
|
745
|
+
await Settle();
|
|
746
|
+
(0, chai_1.expect)(checkedOutAtEnd).to.equal(NOT_OBSERVED);
|
|
747
|
+
resume();
|
|
748
|
+
await disconnecting;
|
|
749
|
+
(0, chai_1.expect)(checkedOutAtEnd).to.equal(0);
|
|
750
|
+
(0, chai_1.expect)(releasesAtEnd).to.equal(1);
|
|
751
|
+
(0, chai_1.expect)((await ending).done).to.equal(true);
|
|
752
|
+
});
|
|
753
|
+
it("opens a run of descending ids after an eviction, refusing none of them", async () => {
|
|
754
|
+
await OverflowEndings();
|
|
755
|
+
for (let index = 0; index < DESCENDING_CURSORS; index += 1) {
|
|
756
|
+
const log = Recorder();
|
|
757
|
+
const rows = await Drain(NextReqId(), Requesting(log, [Rows(1, 2)]));
|
|
758
|
+
(0, chai_1.expect)(rows).to.deep.equal([1, 2]);
|
|
759
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
760
|
+
(0, chai_1.expect)(Count(log, BEGIN)).to.equal(1);
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
it("refuses a reqId whose exhaustion it has forgotten, rather than re-opening it", async () => {
|
|
764
|
+
const log = Recorder();
|
|
765
|
+
const reqId = NextReqId();
|
|
766
|
+
const open = Reopening(log, 1, 2);
|
|
767
|
+
(0, chai_1.expect)(await Drain(reqId, open)).to.deep.equal([1, 2]);
|
|
768
|
+
(0, chai_1.expect)((await Read(reqId, open)).done).to.equal(true);
|
|
769
|
+
await OverflowEndings();
|
|
770
|
+
const err = await Rejection(Read(reqId, open));
|
|
771
|
+
(0, chai_1.expect)(err.message).to.contain(`${reqId}`);
|
|
772
|
+
(0, chai_1.expect)(err.message).to.contain(FORGOTTEN_HINT);
|
|
773
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
774
|
+
(0, chai_1.expect)(Count(log, BEGIN)).to.equal(1);
|
|
775
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
776
|
+
});
|
|
777
|
+
it("refuses a reqId whose reaping it has forgotten, rather than re-serving its rows", async () => {
|
|
778
|
+
const log = Recorder();
|
|
779
|
+
const reqId = NextReqId();
|
|
780
|
+
const open = Reopening(log, 1, 2);
|
|
781
|
+
(0, chai_1.expect)((await Read(reqId, open, REAPING)).value).to.equal(1);
|
|
782
|
+
await Delay(REAP_WINDOW_MS);
|
|
783
|
+
(0, chai_1.expect)(log.releases).to.equal(1);
|
|
784
|
+
await OverflowEndings();
|
|
785
|
+
const err = await Rejection(Read(reqId, open));
|
|
786
|
+
(0, chai_1.expect)(err.message).to.contain(`${reqId}`);
|
|
787
|
+
(0, chai_1.expect)(err.message).to.contain(FORGOTTEN_HINT);
|
|
788
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
789
|
+
(0, chai_1.expect)(Count(log, BEGIN)).to.equal(1);
|
|
790
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
791
|
+
});
|
|
792
|
+
it("keeps serving a live cursor the forgotten range has grown around", async () => {
|
|
793
|
+
const live = Recorder();
|
|
794
|
+
const ended = Recorder();
|
|
795
|
+
const liveId = NextReqId();
|
|
796
|
+
const endedId = NextReqId();
|
|
797
|
+
const openLive = Reopening(live, 1, 2);
|
|
798
|
+
(0, chai_1.expect)((await Read(liveId, openLive)).value).to.equal(1);
|
|
799
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline + 1);
|
|
800
|
+
(0, chai_1.expect)(await Drain(endedId, Reopening(ended, 3, 4))).to.deep.equal([3, 4]);
|
|
801
|
+
await OverflowEndings();
|
|
802
|
+
(0, chai_1.expect)((await Read(liveId, openLive)).value).to.equal(2);
|
|
803
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline + 1);
|
|
804
|
+
(0, chai_1.expect)(live.acquires).to.equal(1);
|
|
805
|
+
(0, chai_1.expect)(Count(live, BEGIN)).to.equal(1);
|
|
806
|
+
await (0, cursors_1.CloseOneCursor)(liveId);
|
|
807
|
+
(0, chai_1.expect)(live.releases).to.equal(1);
|
|
808
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
809
|
+
});
|
|
810
|
+
it("refuses a reqId whose failed open it has forgotten, rather than answering done", async () => {
|
|
811
|
+
const log = Recorder();
|
|
812
|
+
const reqId = NextReqId();
|
|
813
|
+
const open = Requesting(log, [], DECLARE);
|
|
814
|
+
(0, chai_1.expect)((await Rejection(Read(reqId, open))).message).to.equal(STUB_FAILURE);
|
|
815
|
+
await OverflowEndings();
|
|
816
|
+
const err = await Rejection(Read(reqId, open));
|
|
817
|
+
(0, chai_1.expect)(err.message).to.contain(`${reqId}`);
|
|
818
|
+
(0, chai_1.expect)(err.message).to.contain(FORGOTTEN_HINT);
|
|
819
|
+
(0, chai_1.expect)(log.acquires).to.equal(1);
|
|
820
|
+
(0, chai_1.expect)((0, cursors_1.CountOpenCursors)()).to.equal(baseline);
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
//# sourceMappingURL=cursors.spec.js.map
|