@harperfast/harper 5.3.0-beta.4 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/backup.ts +6 -1
- package/components/Application.ts +486 -115
- package/components/DESIGN.md +109 -21
- package/components/deploymentProvenance.ts +28 -0
- package/components/operations.js +14 -7
- package/components/packageComponent.ts +5 -1
- package/config-root.schema.json +1 -1
- package/dataLayer/DESIGN.md +35 -7
- package/dataLayer/blobBackup.ts +71 -30
- package/dataLayer/harperBridge/ResourceBridge.ts +16 -2
- package/dataLayer/rocksdbBackup.ts +88 -34
- package/dataLayer/schemaDescribe.ts +45 -1
- package/dist/bin/backup.js +1 -1
- package/dist/bin/backup.js.map +1 -1
- package/dist/components/Application.d.ts +11 -21
- package/dist/components/Application.js +436 -105
- package/dist/components/Application.js.map +1 -1
- package/dist/components/deploymentProvenance.d.ts +4 -0
- package/dist/components/deploymentProvenance.js +32 -0
- package/dist/components/deploymentProvenance.js.map +1 -0
- package/dist/components/operations.js +14 -7
- package/dist/components/operations.js.map +1 -1
- package/dist/components/packageComponent.js +6 -1
- package/dist/components/packageComponent.js.map +1 -1
- package/dist/dataLayer/blobBackup.d.ts +30 -3
- package/dist/dataLayer/blobBackup.js +73 -36
- package/dist/dataLayer/blobBackup.js.map +1 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +1 -0
- package/dist/dataLayer/harperBridge/ResourceBridge.js +15 -3
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/dataLayer/rocksdbBackup.d.ts +4 -1
- package/dist/dataLayer/rocksdbBackup.js +74 -36
- package/dist/dataLayer/rocksdbBackup.js.map +1 -1
- package/dist/dataLayer/schemaDescribe.js +45 -1
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/resources/DatabaseTransaction.d.ts +1 -0
- package/dist/resources/DatabaseTransaction.js +33 -8
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/ResourceInterface.d.ts +7 -3
- package/dist/resources/ResourceInterface.js +2 -0
- package/dist/resources/ResourceInterface.js.map +1 -1
- package/dist/resources/Table.d.ts +151 -445
- package/dist/resources/Table.js +209 -8
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/write.d.ts +11 -0
- package/dist/resources/analytics/write.js +3 -0
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/blob.d.ts +30 -0
- package/dist/resources/blob.js +189 -1
- package/dist/resources/blob.js.map +1 -1
- package/dist/resources/databases.d.ts +1 -0
- package/dist/resources/databases.js +80 -15
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/derivedIndexRuntime.d.ts +13 -0
- package/dist/resources/derivedIndexRuntime.js +57 -5
- package/dist/resources/derivedIndexRuntime.js.map +1 -1
- package/dist/resources/derivedIndexes.d.ts +1 -0
- package/dist/resources/derivedIndexes.js +116 -15
- package/dist/resources/derivedIndexes.js.map +1 -1
- package/dist/resources/fullTextSchema.d.ts +5 -3
- package/dist/resources/fullTextSchema.js +48 -5
- package/dist/resources/fullTextSchema.js.map +1 -1
- package/dist/resources/fullTextSchemaLifecycle.d.ts +2 -0
- package/dist/resources/fullTextSchemaLifecycle.js +33 -0
- package/dist/resources/fullTextSchemaLifecycle.js.map +1 -1
- package/dist/resources/graphql.js +30 -12
- package/dist/resources/graphql.js.map +1 -1
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +21 -1
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +114 -5
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
- package/dist/resources/indexes/fullTextDerivedIndex.d.ts +11 -2
- package/dist/resources/indexes/fullTextDerivedIndex.js +187 -24
- package/dist/resources/indexes/fullTextDerivedIndex.js.map +1 -1
- package/dist/resources/indexes/fullTextNativeBinding.d.ts +99 -1
- package/dist/resources/indexes/fullTextNativeBinding.js +35 -1
- package/dist/resources/indexes/fullTextNativeBinding.js.map +1 -1
- package/dist/resources/indexes/fullTextQueryIndex.d.ts +58 -0
- package/dist/resources/indexes/fullTextQueryIndex.js +943 -0
- package/dist/resources/indexes/fullTextQueryIndex.js.map +1 -0
- package/dist/resources/indexes/fullTextQueryProtocol.d.ts +6 -0
- package/dist/resources/indexes/fullTextQueryProtocol.js +32 -0
- package/dist/resources/indexes/fullTextQueryProtocol.js.map +1 -0
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.d.ts +4 -1
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js +30 -7
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js.map +1 -1
- package/dist/resources/search.d.ts +41 -0
- package/dist/resources/search.js +468 -26
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/transactionBroadcast.js +101 -50
- package/dist/resources/transactionBroadcast.js.map +1 -1
- package/dist/resources/typeParity.d.ts +9 -0
- package/dist/resources/typeParity.js +3 -0
- package/dist/resources/typeParity.js.map +1 -0
- package/dist/server/REST.js.map +1 -1
- package/dist/server/itc/serverHandlers.js +48 -8
- package/dist/server/itc/serverHandlers.js.map +1 -1
- package/dist/server/serverHelpers/contentTypes.d.ts +7 -0
- package/dist/server/serverHelpers/contentTypes.js +36 -23
- package/dist/server/serverHelpers/contentTypes.js.map +1 -1
- package/dist/server/serverHelpers/uwsServer.js +28 -5
- package/dist/server/serverHelpers/uwsServer.js.map +1 -1
- package/dist/server/threads/itc.js +19 -0
- package/dist/server/threads/itc.js.map +1 -1
- package/dist/server/threads/manageThreads.d.ts +3 -0
- package/dist/server/threads/manageThreads.js +90 -23
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/utility/operation_authorization.js +25 -7
- package/dist/utility/operation_authorization.js.map +1 -1
- package/dist/utility/signalling.js +3 -0
- package/dist/utility/signalling.js.map +1 -1
- package/dist/validation/searchValidator.js +22 -2
- package/dist/validation/searchValidator.js.map +1 -1
- package/npm-shrinkwrap.json +22 -22
- package/package.json +2 -4
- package/resources/DESIGN.md +19 -2
- package/resources/DatabaseTransaction.ts +40 -10
- package/resources/FULL_TEXT.md +97 -0
- package/resources/ResourceInterface.ts +8 -2
- package/resources/Table.ts +767 -17
- package/resources/analytics/write.ts +3 -3
- package/resources/blob.ts +183 -1
- package/resources/databases.ts +126 -14
- package/resources/derivedIndexRuntime.ts +79 -6
- package/resources/derivedIndexes.ts +142 -18
- package/resources/fullTextSchema.ts +55 -9
- package/resources/fullTextSchemaLifecycle.ts +45 -0
- package/resources/graphql.ts +33 -12
- package/resources/indexes/DESIGN.md +167 -15
- package/resources/indexes/HierarchicalNavigableSmallWorld.ts +125 -5
- package/resources/indexes/fullTextDerivedIndex.ts +216 -32
- package/resources/indexes/fullTextNativeBinding.ts +133 -3
- package/resources/indexes/fullTextQueryIndex.ts +1120 -0
- package/resources/indexes/fullTextQueryProtocol.ts +35 -0
- package/resources/indexes/nativeFullTextDerivedIndexLifecycle.ts +28 -8
- package/resources/search.ts +513 -26
- package/resources/transactionBroadcast.ts +86 -47
- package/resources/typeParity.ts +20 -0
- package/schema.graphql +18 -5
- package/server/DESIGN.md +18 -0
- package/server/REST.ts +1 -1
- package/server/itc/serverHandlers.js +61 -8
- package/server/serverHelpers/contentTypes.ts +31 -26
- package/server/serverHelpers/uwsServer.ts +35 -7
- package/server/threads/itc.js +21 -0
- package/server/threads/manageThreads.js +95 -21
- package/studio/web/assets/{Chat-Bq60AO-g.js → Chat-CNEKMllJ.js} +13 -13
- package/studio/web/assets/FloatingChat-CEnWhHeR.js +23 -0
- package/studio/web/assets/SearchDialog-CwhJdEdY.js +1 -0
- package/studio/web/assets/{abnfDiagram-O67JEVCF-DpPZWMOf.js → abnfDiagram-O67JEVCF-raXE027J.js} +1 -1
- package/studio/web/assets/alertDialog-BbWD9Xxa.js +1 -0
- package/studio/web/assets/apiToken-DC5vsaaO.js +1 -0
- package/studio/web/assets/applications-DQZxDy0x.js +296 -0
- package/studio/web/assets/architecture-7GRP2DOG-DDmz3hpI.js +1 -0
- package/studio/web/assets/{architectureDiagram-NJMV4G6O-OmgLraID.js → architectureDiagram-NJMV4G6O-C8_Eet7w.js} +1 -1
- package/studio/web/assets/arrow-up-D2g_57vT.js +1 -0
- package/studio/web/assets/authStore-CJCaADw9.js +3 -0
- package/studio/web/assets/{blockDiagram-BEXU5L5S-Cv7CD3Ai.js → blockDiagram-BEXU5L5S-DR6S5-1D.js} +1 -1
- package/studio/web/assets/{button-MFP9n8Ck.js → button-DWwfgGWI.js} +2 -2
- package/studio/web/assets/{c4Diagram-YGBWAQC7-Ds1vKYnN.js → c4Diagram-YGBWAQC7-BAfZ1G01.js} +1 -1
- package/studio/web/assets/channel-D0AkPjJ8.js +1 -0
- package/studio/web/assets/{chevron-up-CFe8x5Bp.js → chevron-up-CFxbMGv2.js} +1 -1
- package/studio/web/assets/{chunk-3FUC2YCW-DpnBPH8B.js → chunk-3FUC2YCW-DuRp-j19.js} +1 -1
- package/studio/web/assets/{chunk-5DYCD2WN-LLLCQSzg.js → chunk-5DYCD2WN-BceBfIHT.js} +1 -1
- package/studio/web/assets/{chunk-742MDFTN-BL8J_pIO.js → chunk-742MDFTN-CIkt8ijt.js} +1 -1
- package/studio/web/assets/{chunk-7INBJB4K-C-hJHiiK.js → chunk-7INBJB4K-BpeAXyOi.js} +1 -1
- package/studio/web/assets/{chunk-7M6MHVWA-C6ZqkFbA.js → chunk-7M6MHVWA-h6WlaTzO.js} +1 -1
- package/studio/web/assets/{chunk-7PRAP22T-CUXM8BG6.js → chunk-7PRAP22T-KyqX6x3f.js} +1 -1
- package/studio/web/assets/{chunk-GTNCS2PH-DJ2BFvS1.js → chunk-GTNCS2PH-DGHLXyow.js} +1 -1
- package/studio/web/assets/{chunk-GWA4HPMP-C42bSqLL.js → chunk-GWA4HPMP-DsejB6gA.js} +1 -1
- package/studio/web/assets/{chunk-MBY4JIJT-C-5jz6Lo.js → chunk-MBY4JIJT-BwSGweQP.js} +1 -1
- package/studio/web/assets/{chunk-NETBCI7D-D-bzlN4r.js → chunk-NETBCI7D-C8UnOw_f.js} +1 -1
- package/studio/web/assets/{chunk-O7XYJQB3-ep14zA23.js → chunk-O7XYJQB3-CBS3nZYV.js} +1 -1
- package/studio/web/assets/{chunk-UA2S7LBM-BMRWRHED.js → chunk-UA2S7LBM-BHpEdH8D.js} +1 -1
- package/studio/web/assets/{chunk-WEXAMYUT-DdLYVdX1.js → chunk-WEXAMYUT-BAIhTwyh.js} +1 -1
- package/studio/web/assets/{chunk-Z7XXMR3K-BmKEDjcP.js → chunk-Z7XXMR3K-DSHbImdf.js} +1 -1
- package/studio/web/assets/{chunk-ZIGJFQKS-DLZgdNxA.js → chunk-ZIGJFQKS-Cs8fUn7y.js} +1 -1
- package/studio/web/assets/{classDiagram-v2-NBCMYWYE-DOI5vgKT.js → classDiagram-v2-NBCMYWYE-DmDPkt2u.js} +1 -1
- package/studio/web/assets/cn-6T8VranJ.js +1 -0
- package/studio/web/assets/{codicon-Brq4_Ui5.ttf → codicon-DF1abBS2.ttf} +0 -0
- package/studio/web/assets/{createLucideIcon-bziYxJli.js → createLucideIcon-fO5dL7D5.js} +1 -1
- package/studio/web/assets/{css.worker-l1psR_wG.js → css.worker-DoT-OOzx.js} +36 -36
- package/studio/web/assets/{cssMode-DJyc9mHj.js → cssMode-Dz2DxF4e.js} +1 -1
- package/studio/web/assets/{cynefin-OW5HDTMX-BSW-DB7S.js → cynefin-OW5HDTMX-DIvbXLSj.js} +1 -1
- package/studio/web/assets/{cynefinDiagram-VND7K2PF-CbAHEwxt.js → cynefinDiagram-VND7K2PF-BdtaXiCE.js} +1 -1
- package/studio/web/assets/{dagre-6A5THRUB-Csxewgs4.js → dagre-6A5THRUB-C7RUWHyz.js} +1 -1
- package/studio/web/assets/{diagram-22UHCM2B-a0rt8tY4.js → diagram-22UHCM2B-DJCvcaWP.js} +1 -1
- package/studio/web/assets/{diagram-3UASUU5V-lEj2SVNh.js → diagram-3UASUU5V-Du6VKWln.js} +1 -1
- package/studio/web/assets/{diagram-ATOU4E4O-HcrAeB-q.js → diagram-ATOU4E4O-dxRfeG4B.js} +1 -1
- package/studio/web/assets/{diagram-CDSNMT55-CYxiuyEx.js → diagram-CDSNMT55-l5Ga0u-W.js} +1 -1
- package/studio/web/assets/{diagram-MLGK6HIB-ChbCJTgJ.js → diagram-MLGK6HIB-CNQY47LA.js} +1 -1
- package/studio/web/assets/{diagram-MPIPVDR6-DaX9Y-N3.js → diagram-MPIPVDR6-7prveD1B.js} +1 -1
- package/studio/web/assets/{dist-Cz2Y6-6G.js → dist-BrRuMUzt.js} +1 -1
- package/studio/web/assets/{download-CtostjYn.js → download-Cn6tPG4L.js} +1 -1
- package/studio/web/assets/{ebnfDiagram-ZINNZB2B-CwAsENB1.js → ebnfDiagram-ZINNZB2B-5OnkTpfi.js} +1 -1
- package/studio/web/assets/{editor-DDIsQfj6.js → editor-B3mjd3tz.js} +1 -1
- package/studio/web/assets/editor.worker-Yd1NR0QT.js +33 -0
- package/studio/web/assets/{elk-276RUBZZ-Hexg9E4D.js → elk-276RUBZZ-DxDQPjQT.js} +1 -1
- package/studio/web/assets/{erDiagram-OPXOYQCR-CeC-wwO1.js → erDiagram-OPXOYQCR-CQlCX84D.js} +1 -1
- package/studio/web/assets/eventmodeling-NTZA5JFV-DONQf5aG.js +1 -0
- package/studio/web/assets/flowDiagram-KWPJA3E3-BoZ8_QR1.js +1 -0
- package/studio/web/assets/{ganttDiagram-FUAMR5RP-C2_Hhl1-.js → ganttDiagram-FUAMR5RP-bloX3Voy.js} +1 -1
- package/studio/web/assets/{getAnalytics-CjthMQqF.js → getAnalytics-C0FHjtdQ.js} +1 -1
- package/studio/web/assets/{gitGraph-4MIJSDKK-xIk5Vuew.js → gitGraph-4MIJSDKK-BrXWmJt2.js} +1 -1
- package/studio/web/assets/{gitGraphDiagram-X574FWY7-CMxJ34up.js → gitGraphDiagram-X574FWY7-C2KnnZeY.js} +1 -1
- package/studio/web/assets/{html-g1BJHxLy.js → html-BsRGM7tp.js} +1 -1
- package/studio/web/assets/{html.worker-DdwM4IrA.js → html.worker-B1dwY0Ay.js} +27 -27
- package/studio/web/assets/{htmlMode-Vh5IglCQ.js → htmlMode-tUKJaA3o.js} +1 -1
- package/studio/web/assets/index-72cEH474.css +1 -0
- package/studio/web/assets/index-BuqFjN5K.js +828 -0
- package/studio/web/assets/index.lazy-CcpfQFY_.js +2 -0
- package/studio/web/assets/{info-A6RAGUB7-o49TEbj-.js → info-A6RAGUB7-BhzBHe4U.js} +1 -1
- package/studio/web/assets/{infoDiagram-VRGFBTTK-Cjhh7yzZ.js → infoDiagram-VRGFBTTK-B0J1132p.js} +1 -1
- package/studio/web/assets/{ishikawaDiagram-OU5B5YK6-C63aXRmh.js → ishikawaDiagram-OU5B5YK6-BNk0tuQx.js} +1 -1
- package/studio/web/assets/{javascript-5VIolqf7.js → javascript-BZ_uRGHl.js} +1 -1
- package/studio/web/assets/{journeyDiagram-ZHPQQLJL-D_o0P5Mu.js → journeyDiagram-ZHPQQLJL-Be79RMQM.js} +1 -1
- package/studio/web/assets/json.worker-BQqXGI3X.js +65 -0
- package/studio/web/assets/{jsonMode-DG4zQraI.js → jsonMode-DgB-aFMj.js} +1 -1
- package/studio/web/assets/{kanban-definition-PNTS6WVX-CTI9SSxY.js → kanban-definition-PNTS6WVX-4uuoQP9W.js} +1 -1
- package/studio/web/assets/{languageServices-t5FBpX-i.js → languageServices-BleuBw17.js} +1 -1
- package/studio/web/assets/localStorageKeys-etzFY_xV.js +1 -0
- package/studio/web/assets/{lspLanguageFeatures-DgVnNPh-.js → lspLanguageFeatures-ByVYLSsQ.js} +1 -1
- package/studio/web/assets/{mermaid-parser.core-C2lcH_jP.js → mermaid-parser.core-V1UYMeXV.js} +3 -3
- package/studio/web/assets/{mermaid.core-BG5bjfIG.js → mermaid.core-1PX6R49U.js} +4 -4
- package/studio/web/assets/{mindmap-definition-NLK3R4M7-BK7ho6JD.js → mindmap-definition-NLK3R4M7-C70Ctm0J.js} +1 -1
- package/studio/web/assets/notifications-D1Nf-Edn.js +1 -0
- package/studio/web/assets/notifications-TuzN0IMi.js +1 -0
- package/studio/web/assets/{packet-AYTQ26CC-BHPy6KBV.js → packet-AYTQ26CC-DWbXHx5g.js} +1 -1
- package/studio/web/assets/{pegDiagram-GJSIUBJH-DzjwG3jO.js → pegDiagram-GJSIUBJH-d6z1cc7W.js} +1 -1
- package/studio/web/assets/{pie-WAS4IAKB-D0cP-DTU.js → pie-WAS4IAKB-DjoTm3yr.js} +1 -1
- package/studio/web/assets/{pieDiagram-5QR66LMP-C_hOP9Lv.js → pieDiagram-5QR66LMP-Dz3RHpDA.js} +1 -1
- package/studio/web/assets/profile-D7C7Lupz.js +1 -0
- package/studio/web/assets/{quadrantDiagram-O4NWA36T-CZW8PbV1.js → quadrantDiagram-O4NWA36T-CIF5Qkou.js} +1 -1
- package/studio/web/assets/{radar-RG4KPBEZ-C8fk0U81.js → radar-RG4KPBEZ-CVBgjCOj.js} +1 -1
- package/studio/web/assets/{railroad-74A4TZTK-B60FWm17.js → railroad-74A4TZTK-BdhXw10Q.js} +1 -1
- package/studio/web/assets/railroad-abnf-HS5TGJTU-BcoQPN39.js +1 -0
- package/studio/web/assets/railroad-ebnf-LZEXJU2U-B1Lke2JN.js +1 -0
- package/studio/web/assets/railroad-peg-WCYAUIDC-D-oJFkiV.js +1 -0
- package/studio/web/assets/{railroadDiagram-XR7U4H2S-DyyNmgbU.js → railroadDiagram-XR7U4H2S-y3Jv2U6N.js} +1 -1
- package/studio/web/assets/regions-nGQCm-v8.js +1 -0
- package/studio/web/assets/register-C3x9Ze6P.js +909 -0
- package/studio/web/assets/register-DjpsE8to.css +1 -0
- package/studio/web/assets/{requirementDiagram-PLB6GJNP-C4H-mLKu.js → requirementDiagram-PLB6GJNP-ChINZEmu.js} +1 -1
- package/studio/web/assets/restartGate-nHAFLDh-.js +1 -0
- package/studio/web/assets/{sankeyDiagram-IPEJSGJF-DHDyga4c.js → sankeyDiagram-IPEJSGJF-D9AyLce2.js} +1 -1
- package/studio/web/assets/{sequenceDiagram-PO4LG4MO-CdNcHXRI.js → sequenceDiagram-PO4LG4MO-hfk4aIEm.js} +1 -1
- package/studio/web/assets/{setComponentFile-z4-qJCbA.js → setComponentFile-DpjrRqeG.js} +1 -1
- package/studio/web/assets/{setup-CS50uJ4x.js → setup-CGiKLZ9e.js} +2 -2
- package/studio/web/assets/{stateDiagram-v2-GCMORJYK-CpKuXq15.js → stateDiagram-v2-GCMORJYK-Bs8RIb9K.js} +1 -1
- package/studio/web/assets/status-CGJwrNPH.js +61 -0
- package/studio/web/assets/{swimlanes-2SLR337P-NRHa2D8I.js → swimlanes-2SLR337P-B52xrf6t.js} +1 -1
- package/studio/web/assets/swimlanesDiagram-TC7HE7FX-DfN7BAP5.js +8 -0
- package/studio/web/assets/tabs-BCTQzoQK.js +1 -0
- package/studio/web/assets/{timeline-definition-EJHVYXUP-D39Y-xpq.js → timeline-definition-EJHVYXUP-DJSITpQX.js} +1 -1
- package/studio/web/assets/toggleHighContrast-C-Ne6P7T.js +51 -0
- package/studio/web/assets/toggleHighContrast-n7clI0si.css +1 -0
- package/studio/web/assets/{treeView-Q6P3EWNA-CRWR9OqD.js → treeView-Q6P3EWNA-C-epdxRo.js} +1 -1
- package/studio/web/assets/{treemap-WGGIJYW6-ZfXyJgLO.js → treemap-WGGIJYW6-DOVyp_zw.js} +1 -1
- package/studio/web/assets/{ts.worker-DDMUrpqh.js → ts.worker-Clm12uY6.js} +131 -131
- package/studio/web/assets/{tsMode-D83Gg3cq.js → tsMode-CSreYTys.js} +1 -1
- package/studio/web/assets/{typescript-Dfp-GrNq.js → typescript-MnxBk89W.js} +1 -1
- package/studio/web/assets/{useEntityRestURL-BKetlINf.js → useEntityRestURL-TNrh77-s.js} +1 -1
- package/studio/web/assets/{usecaseDiagram-POWQR4AR-jf-zIDZ_.js → usecaseDiagram-POWQR4AR-B6252cbq.js} +1 -1
- package/studio/web/assets/{vendor-core-BdkdbUek.js → vendor-core-6LhfJlRC.js} +1 -1
- package/studio/web/assets/vendor-datadog-ozKf-pts.js +6 -0
- package/studio/web/assets/{vendor-react-izWchTRL.js → vendor-react-BOliS0BL.js} +1 -1
- package/studio/web/assets/vendor-tanstack-Bntfka-M.js +2 -0
- package/studio/web/assets/vendor-ui-9EYYDgoN.js +41 -0
- package/studio/web/assets/{vennDiagram-UO4OBE2U-BKYAZUh_.js → vennDiagram-UO4OBE2U-DZTsDA4k.js} +1 -1
- package/studio/web/assets/{wardley-WFR3VGLG-BO7f36ci.js → wardley-WFR3VGLG-Cfqoe6z4.js} +1 -1
- package/studio/web/assets/{wardleyDiagram-VNRHLVJA-Djb0JDQc.js → wardleyDiagram-VNRHLVJA-qu_f7Tvl.js} +1 -1
- package/studio/web/assets/{workers-CCvmDLH3.js → workers-BfZlUNVI.js} +3 -3
- package/studio/web/assets/{xml-06pZp00U.js → xml-BHd6qGH7.js} +1 -1
- package/studio/web/assets/{xychartDiagram-PMCCYNJV-BQh9ubvb.js → xychartDiagram-PMCCYNJV-UrOKRsmR.js} +1 -1
- package/studio/web/assets/{yaml-iSnWMVlV.js → yaml-C53R8OQq.js} +1 -1
- package/studio/web/assets/{yaml.worker-DAK2o_H1.js → yaml.worker-D9JekGdp.js} +183 -183
- package/studio/web/index.html +15 -15
- package/utility/operation_authorization.ts +27 -7
- package/utility/signalling.ts +3 -0
- package/validation/searchValidator.ts +22 -13
- package/studio/web/assets/FloatingChat-D4560T0p.js +0 -23
- package/studio/web/assets/alertDialog-UrbiMgQt.js +0 -1
- package/studio/web/assets/apiToken-BEvbFPMc.js +0 -1
- package/studio/web/assets/applications-CSUVTH4E.js +0 -296
- package/studio/web/assets/architecture-7GRP2DOG-11l4Ny1l.js +0 -1
- package/studio/web/assets/authStore-5jSS5pTW.js +0 -3
- package/studio/web/assets/channel-BDtouPd6.js +0 -1
- package/studio/web/assets/dialog-DTepachC.js +0 -1
- package/studio/web/assets/editor.worker-CkkvdXvO.js +0 -33
- package/studio/web/assets/eventmodeling-NTZA5JFV-CFb03e0o.js +0 -1
- package/studio/web/assets/flowDiagram-KWPJA3E3-Cidi00_Y.js +0 -1
- package/studio/web/assets/index-CPoDzQTe.css +0 -1
- package/studio/web/assets/index-DGRAzvO4.js +0 -824
- package/studio/web/assets/index.lazy-vgSic7et.js +0 -2
- package/studio/web/assets/json.worker-CSi2hF-a.js +0 -65
- package/studio/web/assets/notifications-BeWcX04m.js +0 -1
- package/studio/web/assets/notifications-DUGWrWoO.js +0 -1
- package/studio/web/assets/profile-BvUEDBzW.js +0 -1
- package/studio/web/assets/railroad-abnf-HS5TGJTU-CLMVZvH0.js +0 -1
- package/studio/web/assets/railroad-ebnf-LZEXJU2U--tlwFoVB.js +0 -1
- package/studio/web/assets/railroad-peg-WCYAUIDC-Dpuslblm.js +0 -1
- package/studio/web/assets/regions-CB-_2m7M.js +0 -1
- package/studio/web/assets/register-1w1Zr3b2.js +0 -848
- package/studio/web/assets/register-jjEx9u7D.css +0 -1
- package/studio/web/assets/setLocalStorage-D_kflv4U.js +0 -1
- package/studio/web/assets/status-CI0wOdOE.js +0 -61
- package/studio/web/assets/swimlanesDiagram-TC7HE7FX-BBk4t4hO.js +0 -8
- package/studio/web/assets/tabs-CnQ_zenf.js +0 -1
- package/studio/web/assets/toggleHighContrast--ixms01u.css +0 -1
- package/studio/web/assets/toggleHighContrast-BsAE4jPe.js +0 -49
- package/studio/web/assets/useLocalStorage-BYoZF60G.js +0 -1
- package/studio/web/assets/vendor-datadog-fCQhBHGk.js +0 -6
- package/studio/web/assets/vendor-tanstack-CQ1aRjVa.js +0 -2
- package/studio/web/assets/vendor-ui-aE1tHcW7.js +0 -41
- package/studio/web/assets/x-vYntCxm4.js +0 -1
|
@@ -355,7 +355,7 @@ function storeTableSizeMetrics(analyticsTable: Table, dbName: string, tables: Ta
|
|
|
355
355
|
return dbUsedSize;
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
-
function storeDBSizeMetrics(analyticsTable: Table, databases: Databases) {
|
|
358
|
+
export function storeDBSizeMetrics(analyticsTable: Table, databases: Databases) {
|
|
359
359
|
for (const [db, tables] of Object.entries(databases)) {
|
|
360
360
|
try {
|
|
361
361
|
const [firstTable] = Object.values(tables);
|
|
@@ -400,7 +400,7 @@ function storeDBSizeMetrics(analyticsTable: Table, databases: Databases) {
|
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
async function storeVolumeMetrics(analyticsTable: Table, databases: Databases) {
|
|
403
|
+
export async function storeVolumeMetrics(analyticsTable: Table, databases: Databases) {
|
|
404
404
|
await Promise.all(
|
|
405
405
|
Object.entries(databases).map(async ([db, tables]) => {
|
|
406
406
|
try {
|
|
@@ -669,7 +669,7 @@ export function buildRocksDBTxnLogMetric(
|
|
|
669
669
|
* @param now - The current time.
|
|
670
670
|
* @param period - The period to store the metrics for.
|
|
671
671
|
*/
|
|
672
|
-
function storeRocksDBStatsMetrics(
|
|
672
|
+
export function storeRocksDBStatsMetrics(
|
|
673
673
|
analyticsTable: Table,
|
|
674
674
|
databases: Databases,
|
|
675
675
|
now: number,
|
package/resources/blob.ts
CHANGED
|
@@ -1578,6 +1578,8 @@ function runReclamation(): void {
|
|
|
1578
1578
|
let earliest = Infinity;
|
|
1579
1579
|
for (const [filePath, pending] of pendingReclamation) {
|
|
1580
1580
|
if (pending.unlinking) continue;
|
|
1581
|
+
// Unlinking during a restore would delete bytes it just wrote at this path.
|
|
1582
|
+
if (isBlobRestoreFenced(pending.fileInfo?.store)) continue;
|
|
1581
1583
|
if (pending.deadline > now) {
|
|
1582
1584
|
earliest = pending.deadline;
|
|
1583
1585
|
break; // insertion order is deadline order; nothing behind this entry is due
|
|
@@ -1648,7 +1650,9 @@ function runReclamation(): void {
|
|
|
1648
1650
|
const instanceStorageInfo = storageInfoForBlob.get(blob);
|
|
1649
1651
|
if (instanceStorageInfo) discardStorage(instanceStorageInfo);
|
|
1650
1652
|
}
|
|
1653
|
+
const unlinkDone = beginBlobUnlink(blobSaveDatabaseName(storageInfo?.store));
|
|
1651
1654
|
unlink(filePath, (error) => {
|
|
1655
|
+
unlinkDone();
|
|
1652
1656
|
pendingReclamation.delete(filePath);
|
|
1653
1657
|
if (pendingReclamation.size === 0) queueTailDeadline = 0;
|
|
1654
1658
|
// Hand the slot back: it is shared by hash, so leaving it claimed would make every later
|
|
@@ -1808,6 +1812,150 @@ export function createBlobFromStoredBody(
|
|
|
1808
1812
|
// can be committed referencing fileIds whose blob files were never durably written.
|
|
1809
1813
|
let pendingMigrationBlobSaves: Promise<void>[] | undefined;
|
|
1810
1814
|
|
|
1815
|
+
// Database -> the token of the restore that currently owns its fence. Restores of one database can
|
|
1816
|
+
// overlap, because a restore releases its lock before awaiting its `reload` broadcast. Ownership, so
|
|
1817
|
+
// that a superseded restore's late reload cannot unfence a database another restore is still working
|
|
1818
|
+
// on, and a restore that dies without reloading leaves nothing behind that a rerun cannot take over.
|
|
1819
|
+
const blobRestoreFences = new Map<string, string>();
|
|
1820
|
+
// Bumped every time a restore takes a database's fence. A check for "is it fenced right now" is not
|
|
1821
|
+
// enough for work that spans the whole restore: an orphan sweep can read the fence as clear, have an
|
|
1822
|
+
// entire restore happen while it awaits an unlink, and then keep deleting on a verdict reached
|
|
1823
|
+
// against the generation that restore replaced. Long-running work captures this instead.
|
|
1824
|
+
const blobRestoreEpochs = new Map<string, number>();
|
|
1825
|
+
const inFlightBlobSaves = new Map<string, Set<Promise<void>>>();
|
|
1826
|
+
// Count of blob-root unlinks dispatched per database, with the waiters a fence parks on until that
|
|
1827
|
+
// count reaches zero. A counter rather than a set of promises: this sits on the deletion path for
|
|
1828
|
+
// every blob, and the overwhelmingly common case has no restore running and nothing to await.
|
|
1829
|
+
const inFlightBlobUnlinks = new Map<string, { count: number; waiters: Array<() => void> }>();
|
|
1830
|
+
|
|
1831
|
+
function blobSaveDatabaseName(store: any): string | undefined {
|
|
1832
|
+
return typeof store?.databaseName === 'string' ? store.databaseName : undefined;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
function assertBlobSaveAllowed(store: any): void {
|
|
1836
|
+
const databaseName = blobSaveDatabaseName(store);
|
|
1837
|
+
if (databaseName && blobRestoreFences.has(databaseName)) {
|
|
1838
|
+
// 503, not a bare Error: the block is lifted by the restore's `reload` phase, so this is a
|
|
1839
|
+
// retry-after condition rather than a fault in the request.
|
|
1840
|
+
throw new BlobReadError(
|
|
1841
|
+
`Cannot save a blob for database '${databaseName}' while it is being restored`,
|
|
1842
|
+
BLOB_UNAVAILABLE_STATUS
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
function trackBlobSave(store: any, saving?: Promise<void>): void {
|
|
1848
|
+
const databaseName = blobSaveDatabaseName(store);
|
|
1849
|
+
if (!databaseName || !saving) return;
|
|
1850
|
+
let saves = inFlightBlobSaves.get(databaseName);
|
|
1851
|
+
if (!saves) inFlightBlobSaves.set(databaseName, (saves = new Set()));
|
|
1852
|
+
saves.add(saving);
|
|
1853
|
+
const remove = () => {
|
|
1854
|
+
saves.delete(saving);
|
|
1855
|
+
if (saves.size === 0) inFlightBlobSaves.delete(databaseName);
|
|
1856
|
+
};
|
|
1857
|
+
saving.then(remove, remove);
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
/**
|
|
1861
|
+
* Fence blob saves, deferred reclamation and orphan cleanup for a database, and wait out the work
|
|
1862
|
+
* already dispatched, so a restore can purge and rewrite its roots safely.
|
|
1863
|
+
*
|
|
1864
|
+
* Closing the database does not do this: a save is an asynchronous file pipeline that outlives the
|
|
1865
|
+
* handle it started from, a reclamation is a timer that never consults the database, and an orphan
|
|
1866
|
+
* sweep is dispatched fire-and-forget.
|
|
1867
|
+
*/
|
|
1868
|
+
export async function blockBlobSavesForRestore(databaseName: string, restoreToken: string): Promise<void> {
|
|
1869
|
+
// Takes ownership whether or not another restore held it: the database never unfences in between.
|
|
1870
|
+
blobRestoreFences.set(databaseName, restoreToken);
|
|
1871
|
+
blobRestoreEpochs.set(databaseName, (blobRestoreEpochs.get(databaseName) ?? 0) + 1);
|
|
1872
|
+
const saves = inFlightBlobSaves.get(databaseName);
|
|
1873
|
+
if (saves) await Promise.allSettled([...saves]);
|
|
1874
|
+
await drainBlobUnlinks(databaseName);
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
/**
|
|
1878
|
+
* Release one restore's fence. Only the current owner's token lifts it, so an earlier restore's late
|
|
1879
|
+
* `reload` cannot unfence a database another restore has since taken over.
|
|
1880
|
+
*/
|
|
1881
|
+
export function resumeBlobSavesAfterRestore(
|
|
1882
|
+
databaseName: string,
|
|
1883
|
+
restoreToken: string,
|
|
1884
|
+
generationReplaced = true
|
|
1885
|
+
): void {
|
|
1886
|
+
// Only the owner may lift the fence; a superseded restore's reload arriving late does nothing.
|
|
1887
|
+
if (blobRestoreFences.get(databaseName) !== restoreToken) return;
|
|
1888
|
+
blobRestoreFences.delete(databaseName);
|
|
1889
|
+
// A drain that ran while the fence was up skipped these entries without recording a next deadline,
|
|
1890
|
+
// so nothing is scheduled to come back for them. Whatever survives below needs a wakeup.
|
|
1891
|
+
if (pendingReclamation.size > 0) scheduleReclamation(Date.now());
|
|
1892
|
+
// A restore that aborted before it destroyed anything leaves the generation intact, so its queued
|
|
1893
|
+
// reclamations still condemn the files they were queued against. Discarding those would strand
|
|
1894
|
+
// every superseded blob the database had pending at the moment an admission check happened to fail.
|
|
1895
|
+
if (!generationReplaced) return;
|
|
1896
|
+
// Every queued reclamation for this database belongs to the generation the restore just replaced:
|
|
1897
|
+
// its file paths were condemned against records that no longer exist. Draining them now would
|
|
1898
|
+
// unlink restored bytes at the same paths, so they are dropped rather than resumed.
|
|
1899
|
+
discardReclamationForDatabase(databaseName);
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
function isBlobRestoreFenced(store: any): boolean {
|
|
1903
|
+
const databaseName = blobSaveDatabaseName(store);
|
|
1904
|
+
return !!databaseName && blobRestoreFences.has(databaseName);
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
/**
|
|
1908
|
+
* A token for work that outlives a single check -- an orphan sweep, say -- so it can tell whether any
|
|
1909
|
+
* restore has touched this database since it started, not merely whether one is running right now.
|
|
1910
|
+
*/
|
|
1911
|
+
export function blobRestoreGeneration(store: any): { database?: string; epoch: number; fenced: boolean } {
|
|
1912
|
+
const database = blobSaveDatabaseName(store);
|
|
1913
|
+
return {
|
|
1914
|
+
database,
|
|
1915
|
+
epoch: database ? (blobRestoreEpochs.get(database) ?? 0) : 0,
|
|
1916
|
+
fenced: !!database && blobRestoreFences.has(database),
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
/** True once a restore has fenced this database since `since` was taken, or is fencing it now. */
|
|
1921
|
+
export function blobRestoreGenerationChanged(since: { database?: string; epoch: number }): boolean {
|
|
1922
|
+
if (!since.database) return false;
|
|
1923
|
+
if (blobRestoreFences.has(since.database)) return true;
|
|
1924
|
+
return (blobRestoreEpochs.get(since.database) ?? 0) !== since.epoch;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
function discardReclamationForDatabase(databaseName: string): void {
|
|
1928
|
+
for (const [filePath, pending] of [...pendingReclamation]) {
|
|
1929
|
+
if (pending.unlinking) continue; // already dispatched; its callback owns the entry
|
|
1930
|
+
if (blobSaveDatabaseName(pending.fileInfo?.store) !== databaseName) continue;
|
|
1931
|
+
pendingReclamation.delete(filePath);
|
|
1932
|
+
settleReclamationWaiters(pending);
|
|
1933
|
+
}
|
|
1934
|
+
if (pendingReclamation.size === 0) resetDrainedQueue();
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
/** Register a dispatched blob-root unlink so a restore fence can wait for it to land. */
|
|
1938
|
+
export function beginBlobUnlink(databaseName: string | undefined): () => void {
|
|
1939
|
+
if (!databaseName) return () => {};
|
|
1940
|
+
let unlinks = inFlightBlobUnlinks.get(databaseName);
|
|
1941
|
+
if (!unlinks) inFlightBlobUnlinks.set(databaseName, (unlinks = { count: 0, waiters: [] }));
|
|
1942
|
+
unlinks.count++;
|
|
1943
|
+
let settled = false;
|
|
1944
|
+
return () => {
|
|
1945
|
+
if (settled) return;
|
|
1946
|
+
settled = true;
|
|
1947
|
+
if (--unlinks.count > 0) return;
|
|
1948
|
+
inFlightBlobUnlinks.delete(databaseName);
|
|
1949
|
+
for (const wake of unlinks.waiters) wake();
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
function drainBlobUnlinks(databaseName: string): Promise<void> | undefined {
|
|
1954
|
+
const unlinks = inFlightBlobUnlinks.get(databaseName);
|
|
1955
|
+
if (!unlinks || unlinks.count === 0) return;
|
|
1956
|
+
return new Promise<void>((resolve) => unlinks.waiters.push(resolve));
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1811
1959
|
export function saveBlob(blob: FileBackedBlob, deleteOnFailure = false) {
|
|
1812
1960
|
let storageInfo = storageInfoForBlob.get(blob);
|
|
1813
1961
|
if (!storageInfo) {
|
|
@@ -1826,6 +1974,7 @@ export function saveBlob(blob: FileBackedBlob, deleteOnFailure = false) {
|
|
|
1826
1974
|
if (storageInfo.fileId) return storageInfo; // if there is any file id, we are already saving and can return the info
|
|
1827
1975
|
storageInfo.store = currentStore;
|
|
1828
1976
|
}
|
|
1977
|
+
assertBlobSaveAllowed(storageInfo.store);
|
|
1829
1978
|
storageInfo.deleteOnFailure = deleteOnFailure;
|
|
1830
1979
|
if (blob.saveInRecord) {
|
|
1831
1980
|
if (!storageInfo.contentBuffer) {
|
|
@@ -1848,6 +1997,7 @@ export function saveBlob(blob: FileBackedBlob, deleteOnFailure = false) {
|
|
|
1848
1997
|
// for native blobs, we have to read them from the stream
|
|
1849
1998
|
writeBlobWithStream(blob as any, Readable.from(blob.stream()), storageInfo);
|
|
1850
1999
|
}
|
|
2000
|
+
trackBlobSave(storageInfo.store, storageInfo.saving);
|
|
1851
2001
|
// Track the in-flight save when a migration is collecting them. storageInfo.saving is set
|
|
1852
2002
|
// by writeBlobWithStream; writeBlobWithBuffer for small blobs may not produce one. The
|
|
1853
2003
|
// wrapping `.then(...)` removes resolved promises from the list so a long migration does not
|
|
@@ -2081,7 +2231,9 @@ function writeBlobWithStream(
|
|
|
2081
2231
|
}
|
|
2082
2232
|
if (storageInfo.deleteOnFailure) {
|
|
2083
2233
|
store.unlock(lockKey);
|
|
2234
|
+
const unlinkDone = beginBlobUnlink(blobSaveDatabaseName(store));
|
|
2084
2235
|
unlink(filePath, (error) => {
|
|
2236
|
+
unlinkDone();
|
|
2085
2237
|
if (error) logger.debug?.('Error while deleting aborted blob file', error);
|
|
2086
2238
|
});
|
|
2087
2239
|
} else if (idleTimeoutMs > 0 && !(error as { sourceBlobUnavailable?: boolean }).sourceBlobUnavailable) {
|
|
@@ -2343,6 +2495,7 @@ export function repairBlobFile(
|
|
|
2343
2495
|
if (!storageInfo?.fileId || !storageInfo.store) return undefined;
|
|
2344
2496
|
if (storageInfo.start !== undefined || storageInfo.end !== undefined) return undefined;
|
|
2345
2497
|
store = storageInfo.store;
|
|
2498
|
+
assertBlobSaveAllowed(store);
|
|
2346
2499
|
storageInfo.filePath ??= getFilePath(storageInfo);
|
|
2347
2500
|
const filePath = storageInfo.filePath;
|
|
2348
2501
|
const descriptorSize = (blob as { size?: number }).size;
|
|
@@ -2396,6 +2549,7 @@ export function repairBlobFile(
|
|
|
2396
2549
|
repairTargetPath: filePath,
|
|
2397
2550
|
repairTempLockKey,
|
|
2398
2551
|
});
|
|
2552
|
+
trackBlobSave(store, repairStorageInfo.saving);
|
|
2399
2553
|
locksOwnedByWriter = true;
|
|
2400
2554
|
const settled = (repairStorageInfo.saving as Promise<void>).then(() => {
|
|
2401
2555
|
if (descriptorSize === undefined) (blob as { size?: number }).size = verifiedSize;
|
|
@@ -3350,6 +3504,10 @@ export async function cleanupOrphans(database: any, databaseName?: string) {
|
|
|
3350
3504
|
auditStore = table.auditStore;
|
|
3351
3505
|
if (auditStore) break;
|
|
3352
3506
|
}
|
|
3507
|
+
// Captured before the scan, not before the deletions: the verdict this sweep acts on -- "no record
|
|
3508
|
+
// references this path" -- is formed by the scan below, so a restore that lands while it runs has
|
|
3509
|
+
// already invalidated it.
|
|
3510
|
+
const generation = blobRestoreGeneration(store);
|
|
3353
3511
|
const pathsToCheck = new Set<string>();
|
|
3354
3512
|
const rootPaths = getRootBlobPathsForDB(store);
|
|
3355
3513
|
if (rootPaths) {
|
|
@@ -3452,17 +3610,41 @@ export async function cleanupOrphans(database: any, databaseName?: string) {
|
|
|
3452
3610
|
}
|
|
3453
3611
|
logger.warn?.('Deleting', pathsToCheck.size, 'orphaned blobs');
|
|
3454
3612
|
orphansDeleted += pathsToCheck.size;
|
|
3613
|
+
let deleted = 0;
|
|
3614
|
+
let skipped = 0;
|
|
3615
|
+
let abandonedForRestore = false;
|
|
3455
3616
|
for (const path of pathsToCheck) {
|
|
3617
|
+
// This walk is dispatched fire-and-forget and can outlive a restore's close acknowledgement, so
|
|
3618
|
+
// it compares generations rather than asking whether a restore is running right now: one await
|
|
3619
|
+
// here can span a whole restore, leaving the fence clear again by the next iteration.
|
|
3620
|
+
if (!abandonedForRestore && blobRestoreGenerationChanged(generation)) {
|
|
3621
|
+
abandonedForRestore = true;
|
|
3622
|
+
logger.warn?.('Stopping orphaned blob cleanup: the database has been restored since this scan began');
|
|
3623
|
+
}
|
|
3624
|
+
if (abandonedForRestore) {
|
|
3625
|
+
// Keep walking, but only to hand back the locks taken for every candidate up front. Leaving
|
|
3626
|
+
// them held would block the repair path until the process restarts, and collecting the
|
|
3627
|
+
// untouched paths into a second set first would double the footprint of a sweep this
|
|
3628
|
+
// function is explicitly built to run over hours.
|
|
3629
|
+
skipped++;
|
|
3630
|
+
const lockKey = repairTempLocks.get(path);
|
|
3631
|
+
if (lockKey) (store as any).unlock(lockKey);
|
|
3632
|
+
continue;
|
|
3633
|
+
}
|
|
3634
|
+
const unlinkDone = beginBlobUnlink(blobSaveDatabaseName(store));
|
|
3456
3635
|
try {
|
|
3457
3636
|
await unlinkPromised(path);
|
|
3637
|
+
deleted++;
|
|
3458
3638
|
} catch (error) {
|
|
3459
3639
|
logger.debug?.('Error deleting file', error);
|
|
3460
3640
|
} finally {
|
|
3641
|
+
unlinkDone();
|
|
3461
3642
|
const lockKey = repairTempLocks.get(path);
|
|
3462
3643
|
if (lockKey) (store as any).unlock(lockKey);
|
|
3463
3644
|
}
|
|
3464
3645
|
}
|
|
3465
|
-
|
|
3646
|
+
orphansDeleted -= skipped;
|
|
3647
|
+
logger.warn?.('Finished deleting', deleted, 'orphaned blobs');
|
|
3466
3648
|
pathsToCheck.clear();
|
|
3467
3649
|
}
|
|
3468
3650
|
// check each object for any blob references and removes from the paths to check if found
|
package/resources/databases.ts
CHANGED
|
@@ -95,6 +95,7 @@ import { resolveRocksMemoryConfig } from '../utility/rocksMemoryConfig.ts';
|
|
|
95
95
|
import { isProcessRunning } from '../utility/processManagement/processManagement.js';
|
|
96
96
|
import {
|
|
97
97
|
compileFullTextDefinitions,
|
|
98
|
+
compileFullTextFields,
|
|
98
99
|
persistedFullTextIndexNames,
|
|
99
100
|
reconcileFullTextIndexGenerations,
|
|
100
101
|
type FullTextDefinition,
|
|
@@ -104,7 +105,9 @@ import { projectAttributesToProperties } from './jsonSchemaTypes.ts';
|
|
|
104
105
|
import {
|
|
105
106
|
definitionsEqual,
|
|
106
107
|
mergePeerFullTextDefinitions,
|
|
108
|
+
mergePeerFullTextFields,
|
|
107
109
|
readPersistedFullTextDefinitions,
|
|
110
|
+
readPersistedFullTextFields,
|
|
108
111
|
retainFullTextDefinitions,
|
|
109
112
|
serializeFullTextState,
|
|
110
113
|
} from './fullTextSchemaLifecycle.ts';
|
|
@@ -1443,6 +1446,12 @@ function initStores(
|
|
|
1443
1446
|
for (const warning of warnings) logger.warn(warning);
|
|
1444
1447
|
} else if (warnings.length === 0) warnedFullTextStates.delete(warningKey);
|
|
1445
1448
|
}
|
|
1449
|
+
const fullTextFields = readPersistedFullTextFields(
|
|
1450
|
+
primaryAttribute.fullTextFields,
|
|
1451
|
+
primaryAttribute.fullTextIndexes,
|
|
1452
|
+
attributes,
|
|
1453
|
+
(message) => logger.warn(`${databaseName}.${tableName}: ${message}`)
|
|
1454
|
+
);
|
|
1446
1455
|
const fullTextIndexGenerations = persistedFullTextIndexGenerations(
|
|
1447
1456
|
primaryAttribute.fullTextIndexGenerations,
|
|
1448
1457
|
fullTextIndexes
|
|
@@ -1451,6 +1460,7 @@ function initStores(
|
|
|
1451
1460
|
if (table && !recreateTable) {
|
|
1452
1461
|
if (primaryAttribute.audit === true && table.audit !== true) table.enableAuditing();
|
|
1453
1462
|
table.fullTextIndexes = fullTextIndexes;
|
|
1463
|
+
table.fullTextFields = fullTextFields;
|
|
1454
1464
|
table.fullTextIndexGenerations = fullTextIndexGenerations;
|
|
1455
1465
|
table.fullTextIndexRetirements = fullTextIndexRetirements;
|
|
1456
1466
|
indices = table.indices;
|
|
@@ -1605,6 +1615,7 @@ function initStores(
|
|
|
1605
1615
|
indices,
|
|
1606
1616
|
attributes,
|
|
1607
1617
|
fullTextIndexes,
|
|
1618
|
+
fullTextFields,
|
|
1608
1619
|
fullTextIndexGenerations,
|
|
1609
1620
|
fullTextIndexRetirements,
|
|
1610
1621
|
schemaDefined: primaryAttribute.schemaDefined,
|
|
@@ -2165,6 +2176,7 @@ interface TableDefinition {
|
|
|
2165
2176
|
/** Internal: this declaration came from the application owned by the current dedicated worker. */
|
|
2166
2177
|
isolatedApplicationOwner?: boolean;
|
|
2167
2178
|
fullTextIndexes?: FullTextDefinition[];
|
|
2179
|
+
fullTextFields?: string[];
|
|
2168
2180
|
}
|
|
2169
2181
|
/**
|
|
2170
2182
|
* Ensure that we have this database object (that holds a set of tables) set up
|
|
@@ -3353,6 +3365,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3353
3365
|
cacheControl,
|
|
3354
3366
|
isolatedApplicationOwner,
|
|
3355
3367
|
fullTextIndexes,
|
|
3368
|
+
fullTextFields,
|
|
3356
3369
|
} = tableDefinition;
|
|
3357
3370
|
const auditExplicitlyEnabled = audit === true;
|
|
3358
3371
|
const auditExplicitlyDisabled = audit === false;
|
|
@@ -3555,6 +3568,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3555
3568
|
let published = false;
|
|
3556
3569
|
let fullTextValuesForPersistence: unknown;
|
|
3557
3570
|
let fullTextPersistencePending = false;
|
|
3571
|
+
let fullTextFieldsForPersistence: string[] | undefined;
|
|
3558
3572
|
let activeFullTextIndexes: FullTextDefinition[] | undefined;
|
|
3559
3573
|
let fullTextIndexGenerationMap: FullTextIndexGenerations = Object.create(null);
|
|
3560
3574
|
let fullTextIndexRetirementNames: string[] | undefined;
|
|
@@ -3604,23 +3618,43 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3604
3618
|
);
|
|
3605
3619
|
}
|
|
3606
3620
|
let persistedPrimary = persistedPrimaryDescriptor(Table.dbisDB);
|
|
3607
|
-
|
|
3621
|
+
const persistedFullTextState = (name: string, liveValue: unknown) =>
|
|
3622
|
+
persistedPrimary.descriptor === undefined ? liveValue : persistedPrimary.descriptor[name];
|
|
3623
|
+
let persistedFullTextValues = persistedFullTextState('fullTextIndexes', Table.fullTextIndexes);
|
|
3624
|
+
if (origin === 'cluster') {
|
|
3625
|
+
const declaredFields = new Set(
|
|
3626
|
+
readPersistedFullTextFields(
|
|
3627
|
+
persistedFullTextState('fullTextFields', Table.fullTextFields),
|
|
3628
|
+
persistedFullTextValues,
|
|
3629
|
+
catalogAttributes(Table.dbisDB),
|
|
3630
|
+
fullTextWarning
|
|
3631
|
+
)
|
|
3632
|
+
);
|
|
3633
|
+
attributes = attributes.filter((attribute) => {
|
|
3634
|
+
if (!declaredFields.has(attribute.name)) return true;
|
|
3635
|
+
fullTextWarning(`Ignoring peer attribute '${attribute.name}'; the local full-text field is authoritative`);
|
|
3636
|
+
return false;
|
|
3637
|
+
});
|
|
3638
|
+
}
|
|
3608
3639
|
const incomingFullTextValues = fullTextIndexesExplicit ? fullTextIndexes : [];
|
|
3609
3640
|
let fullTextValidationAttributes: any[] | undefined;
|
|
3610
3641
|
if (
|
|
3611
3642
|
(persistedFullTextValues !== undefined && (rootStore instanceof RocksDatabase || fullTextIndexesExplicit)) ||
|
|
3612
|
-
|
|
3643
|
+
persistedFullTextState('fullTextIndexRetirements', Table.fullTextIndexRetirements) !== undefined ||
|
|
3644
|
+
(persistedFullTextState('fullTextFields', Table.fullTextFields) !== undefined &&
|
|
3645
|
+
(rootStore instanceof RocksDatabase || fullTextIndexesExplicit || fullTextFields !== undefined)) ||
|
|
3646
|
+
(fullTextFields !== undefined && (!Array.isArray(fullTextFields) || fullTextFields.length > 0)) ||
|
|
3613
3647
|
Table.fullTextIndexes?.length > 0 ||
|
|
3614
3648
|
(fullTextIndexesExplicit && (!Array.isArray(incomingFullTextValues) || incomingFullTextValues.length > 0))
|
|
3615
3649
|
) {
|
|
3616
3650
|
if (!(rootStore instanceof RocksDatabase)) {
|
|
3617
3651
|
exclusiveLock();
|
|
3618
3652
|
persistedPrimary = persistedPrimaryDescriptor(Table.dbisDB);
|
|
3619
|
-
persistedFullTextValues =
|
|
3653
|
+
persistedFullTextValues = persistedFullTextState('fullTextIndexes', Table.fullTextIndexes);
|
|
3620
3654
|
}
|
|
3621
3655
|
const originalAttributes = Table.attributes.slice();
|
|
3622
3656
|
fullTextIndexRetirementNames = persistedFullTextIndexNames(
|
|
3623
|
-
|
|
3657
|
+
persistedFullTextState('fullTextIndexRetirements', Table.fullTextIndexRetirements)
|
|
3624
3658
|
);
|
|
3625
3659
|
const relationshipAttributes = originalAttributes.filter((attribute: any) => attribute.relationship);
|
|
3626
3660
|
const originalMetadata = {
|
|
@@ -3629,6 +3663,12 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3629
3663
|
cacheControl: Table.cacheControl,
|
|
3630
3664
|
schemaDefined: Table.schemaDefined,
|
|
3631
3665
|
};
|
|
3666
|
+
const originalFullTextState = {
|
|
3667
|
+
indexes: Table.fullTextIndexes.slice(),
|
|
3668
|
+
fields: [...Table.fullTextFields],
|
|
3669
|
+
generations: Object.assign(Object.create(null), Table.fullTextIndexGenerations),
|
|
3670
|
+
retirements: [...Table.fullTextIndexRetirements],
|
|
3671
|
+
};
|
|
3632
3672
|
armFullTextLiveStateRestore = () => {
|
|
3633
3673
|
if (restoreFullTextLiveState) return;
|
|
3634
3674
|
restoreFullTextLiveState = () => {
|
|
@@ -3640,16 +3680,32 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3640
3680
|
Object.assign(Table, originalMetadata);
|
|
3641
3681
|
Table.properties = projectAttributesToProperties(restored);
|
|
3642
3682
|
const restoredPrimary = persistedPrimaryDescriptor(Table.dbisDB).descriptor;
|
|
3683
|
+
if (restoredPrimary === undefined) {
|
|
3684
|
+
Table.fullTextIndexes = originalFullTextState.indexes;
|
|
3685
|
+
Table.fullTextFields = originalFullTextState.fields;
|
|
3686
|
+
Table.fullTextIndexGenerations = originalFullTextState.generations;
|
|
3687
|
+
Table.fullTextIndexRetirements = originalFullTextState.retirements;
|
|
3688
|
+
Table.schemaVersion++;
|
|
3689
|
+
Table.updatedAttributes();
|
|
3690
|
+
refreshDerivedIndexes(Table);
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3643
3693
|
const restoredFullTextIndexes =
|
|
3644
|
-
rootStore instanceof RocksDatabase && restoredPrimary
|
|
3645
|
-
? readPersistedFullTextDefinitions(restoredPrimary
|
|
3694
|
+
rootStore instanceof RocksDatabase && restoredPrimary.audit === true
|
|
3695
|
+
? readPersistedFullTextDefinitions(restoredPrimary.fullTextIndexes, restored, fullTextWarning)
|
|
3646
3696
|
: [];
|
|
3647
3697
|
Table.fullTextIndexes = restoredFullTextIndexes;
|
|
3698
|
+
Table.fullTextFields = readPersistedFullTextFields(
|
|
3699
|
+
restoredPrimary.fullTextFields,
|
|
3700
|
+
restoredPrimary.fullTextIndexes,
|
|
3701
|
+
restored,
|
|
3702
|
+
fullTextWarning
|
|
3703
|
+
);
|
|
3648
3704
|
Table.fullTextIndexGenerations = persistedFullTextIndexGenerations(
|
|
3649
|
-
restoredPrimary
|
|
3705
|
+
restoredPrimary.fullTextIndexGenerations,
|
|
3650
3706
|
restoredFullTextIndexes
|
|
3651
3707
|
);
|
|
3652
|
-
Table.fullTextIndexRetirements = persistedFullTextIndexNames(restoredPrimary
|
|
3708
|
+
Table.fullTextIndexRetirements = persistedFullTextIndexNames(restoredPrimary.fullTextIndexRetirements);
|
|
3653
3709
|
Table.schemaVersion++;
|
|
3654
3710
|
Table.updatedAttributes();
|
|
3655
3711
|
refreshDerivedIndexes(Table);
|
|
@@ -3672,8 +3728,28 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3672
3728
|
// Before the full-text branches can write an interim descriptor; the check on the merged list
|
|
3673
3729
|
// below stays authoritative.
|
|
3674
3730
|
assertDerivedFieldOwnership(validationAttributes as any[]);
|
|
3731
|
+
const validateFullTextFields = (definitions: unknown) => {
|
|
3732
|
+
const names = persistedFullTextIndexNames(definitions).map((name) => ({ name }));
|
|
3733
|
+
if (origin === 'cluster')
|
|
3734
|
+
return mergePeerFullTextFields(
|
|
3735
|
+
persistedFullTextState('fullTextFields', Table.fullTextFields),
|
|
3736
|
+
fullTextFields,
|
|
3737
|
+
persistedFullTextValues,
|
|
3738
|
+
definitions,
|
|
3739
|
+
validationAttributes,
|
|
3740
|
+
fullTextWarning
|
|
3741
|
+
);
|
|
3742
|
+
const requestedNames = new Set(names.map(({ name }) => name));
|
|
3743
|
+
return compileFullTextFields(
|
|
3744
|
+
fullTextFields === undefined ? [...requestedNames] : fullTextFields,
|
|
3745
|
+
names,
|
|
3746
|
+
validationAttributes,
|
|
3747
|
+
true
|
|
3748
|
+
);
|
|
3749
|
+
};
|
|
3675
3750
|
|
|
3676
|
-
const persistedAudit =
|
|
3751
|
+
const persistedAudit =
|
|
3752
|
+
persistedPrimary.descriptor === undefined ? Table.audit : persistedPrimary.descriptor.audit;
|
|
3677
3753
|
const durableAudit = persistedAudit === true;
|
|
3678
3754
|
const finalAudit =
|
|
3679
3755
|
origin === 'cluster'
|
|
@@ -3700,6 +3776,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3700
3776
|
: [];
|
|
3701
3777
|
} else if (fullTextIndexesExplicit) {
|
|
3702
3778
|
const compiled = compileFullTextDefinitions(incomingFullTextValues, validationAttributes);
|
|
3779
|
+
fullTextFieldsForPersistence = validateFullTextFields(compiled);
|
|
3703
3780
|
if (compiled.length > 0 && !(rootStore instanceof RocksDatabase))
|
|
3704
3781
|
throw new ClientError(
|
|
3705
3782
|
`Table '${databaseName}.${tableName}' cannot use @fullText with the LMDB storage engine`,
|
|
@@ -3710,7 +3787,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3710
3787
|
`Table '${databaseName}.${tableName}' must enable audit logging before using @fullText because its transaction log is the derived-index recovery source`,
|
|
3711
3788
|
400
|
|
3712
3789
|
);
|
|
3713
|
-
const pinAudit = compiled.length > 0 &&
|
|
3790
|
+
const pinAudit = compiled.length > 0 && persistedAudit !== true;
|
|
3714
3791
|
const requestedNames = new Set(compiled.map(({ name }) => name));
|
|
3715
3792
|
const durableDefinitions = readPersistedFullTextDefinitions(
|
|
3716
3793
|
persistedFullTextValues,
|
|
@@ -3739,15 +3816,25 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3739
3816
|
if (interimDefinitions.length > 0) {
|
|
3740
3817
|
interimPrimary.fullTextIndexes = interimDefinitions;
|
|
3741
3818
|
interimPrimary.fullTextIndexGenerations = persistedFullTextIndexGenerations(
|
|
3742
|
-
|
|
3819
|
+
persistedFullTextState('fullTextIndexGenerations', Table.fullTextIndexGenerations),
|
|
3743
3820
|
interimDefinitions
|
|
3744
3821
|
);
|
|
3745
3822
|
} else {
|
|
3746
3823
|
delete interimPrimary.fullTextIndexes;
|
|
3747
3824
|
delete interimPrimary.fullTextIndexGenerations;
|
|
3748
3825
|
}
|
|
3826
|
+
const interimFullTextFields = readPersistedFullTextFields(
|
|
3827
|
+
persistedFullTextState('fullTextFields', Table.fullTextFields),
|
|
3828
|
+
persistedFullTextValues,
|
|
3829
|
+
durableAttributes,
|
|
3830
|
+
fullTextWarning
|
|
3831
|
+
).filter((name) => requestedNames.has(name));
|
|
3832
|
+
if (interimFullTextFields.length > 0) interimPrimary.fullTextFields = interimFullTextFields;
|
|
3833
|
+
else delete interimPrimary.fullTextFields;
|
|
3749
3834
|
const retirements = new Set(
|
|
3750
|
-
persistedFullTextIndexNames(
|
|
3835
|
+
persistedFullTextIndexNames(
|
|
3836
|
+
persistedFullTextState('fullTextIndexRetirements', Table.fullTextIndexRetirements)
|
|
3837
|
+
)
|
|
3751
3838
|
);
|
|
3752
3839
|
for (const name of transitionRetirements) retirements.add(name);
|
|
3753
3840
|
for (const name of requestedNames) if (!transitionRetirements.has(name)) retirements.delete(name);
|
|
@@ -3779,6 +3866,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3779
3866
|
fullTextValuesForPersistence = persistedFullTextValues;
|
|
3780
3867
|
activeFullTextIndexes = rootStore instanceof RocksDatabase && finalAudit ? retained : [];
|
|
3781
3868
|
}
|
|
3869
|
+
fullTextFieldsForPersistence ??= validateFullTextFields(fullTextValuesForPersistence);
|
|
3782
3870
|
}
|
|
3783
3871
|
if (activeFullTextIndexes !== undefined) {
|
|
3784
3872
|
const durableGenerationDefinitions = readPersistedFullTextDefinitions(
|
|
@@ -3793,7 +3881,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3793
3881
|
);
|
|
3794
3882
|
fullTextIndexGenerationMap = reconcileFullTextIndexGenerations(
|
|
3795
3883
|
durableGenerationDefinitions,
|
|
3796
|
-
|
|
3884
|
+
persistedFullTextState('fullTextIndexGenerations', Table.fullTextIndexGenerations),
|
|
3797
3885
|
finalGenerationDefinitions,
|
|
3798
3886
|
createFullTextIndexGeneration
|
|
3799
3887
|
);
|
|
@@ -3889,12 +3977,30 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
3889
3977
|
activeFullTextIndexes = compiled;
|
|
3890
3978
|
}
|
|
3891
3979
|
}
|
|
3980
|
+
fullTextFieldsForPersistence =
|
|
3981
|
+
origin === 'cluster'
|
|
3982
|
+
? mergePeerFullTextFields(
|
|
3983
|
+
undefined,
|
|
3984
|
+
fullTextFields,
|
|
3985
|
+
[],
|
|
3986
|
+
fullTextValuesForPersistence,
|
|
3987
|
+
attributes,
|
|
3988
|
+
fullTextWarning
|
|
3989
|
+
)
|
|
3990
|
+
: compileFullTextFields(
|
|
3991
|
+
fullTextFields === undefined ? persistedFullTextIndexNames(fullTextValuesForPersistence) : fullTextFields,
|
|
3992
|
+
persistedFullTextIndexNames(fullTextValuesForPersistence).map((name) => ({ name })),
|
|
3993
|
+
attributes,
|
|
3994
|
+
true
|
|
3995
|
+
);
|
|
3892
3996
|
const auditStore = rootStore.auditStore;
|
|
3893
3997
|
primaryKeyAttribute = attributes.find((attribute) => attribute.isPrimaryKey) || {};
|
|
3894
3998
|
primaryKey = primaryKeyAttribute.name;
|
|
3895
3999
|
primaryKeyAttribute.isPrimaryKey = true;
|
|
3896
4000
|
primaryKeyAttribute.is_hash_attribute = true; // backward-compat: harperdb@4.x reads this field to open the DBI with correct flags
|
|
3897
4001
|
primaryKeyAttribute.schemaDefined = schemaDefined;
|
|
4002
|
+
if (fullTextFieldsForPersistence.length > 0) primaryKeyAttribute.fullTextFields = fullTextFieldsForPersistence;
|
|
4003
|
+
else delete primaryKeyAttribute.fullTextFields;
|
|
3898
4004
|
// Old readers treat every attribute row as live schema, so relationships stay on the ignored primary descriptor.
|
|
3899
4005
|
if (relationshipDefinitions) primaryKeyAttribute.relationships = relationshipDefinitions;
|
|
3900
4006
|
if (Array.isArray(fullTextValuesForPersistence) && fullTextValuesForPersistence.length > 0) {
|
|
@@ -4043,6 +4149,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
4043
4149
|
indices: {},
|
|
4044
4150
|
attributes,
|
|
4045
4151
|
fullTextIndexes: activeFullTextIndexes ?? [],
|
|
4152
|
+
fullTextFields: fullTextFieldsForPersistence,
|
|
4046
4153
|
fullTextIndexGenerations: fullTextIndexGenerationMap,
|
|
4047
4154
|
fullTextIndexRetirements: fullTextIndexRetirementNames ?? [],
|
|
4048
4155
|
schemaDefined,
|
|
@@ -4463,6 +4570,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
4463
4570
|
if (
|
|
4464
4571
|
!deferredPrimaryRow &&
|
|
4465
4572
|
(fullTextPersistencePending ||
|
|
4573
|
+
fullTextFieldsForPersistence !== undefined ||
|
|
4466
4574
|
(rootStore instanceof RocksDatabase &&
|
|
4467
4575
|
activeFullTextIndexes !== undefined &&
|
|
4468
4576
|
Array.isArray(fullTextValuesForPersistence)))
|
|
@@ -4470,10 +4578,12 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
4470
4578
|
const { key, descriptor } = persistedPrimaryDescriptor(attributesDbi);
|
|
4471
4579
|
if (descriptor && !tableIsDropping(descriptor, key)) {
|
|
4472
4580
|
const updatedPrimary = { ...descriptor };
|
|
4581
|
+
if (fullTextFieldsForPersistence?.length) updatedPrimary.fullTextFields = fullTextFieldsForPersistence;
|
|
4582
|
+
else if (fullTextFieldsForPersistence) delete updatedPrimary.fullTextFields;
|
|
4473
4583
|
if (Array.isArray(fullTextValuesForPersistence) && fullTextValuesForPersistence.length > 0) {
|
|
4474
4584
|
updatedPrimary.fullTextIndexes = fullTextValuesForPersistence;
|
|
4475
4585
|
updatedPrimary.fullTextIndexGenerations = fullTextIndexGenerationMap;
|
|
4476
|
-
} else {
|
|
4586
|
+
} else if (Array.isArray(fullTextValuesForPersistence)) {
|
|
4477
4587
|
delete updatedPrimary.fullTextIndexes;
|
|
4478
4588
|
delete updatedPrimary.fullTextIndexGenerations;
|
|
4479
4589
|
}
|
|
@@ -4488,6 +4598,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
4488
4598
|
else delete updatedPrimary.fullTextIndexRetirements;
|
|
4489
4599
|
if (
|
|
4490
4600
|
!definitionsEqual(descriptor.fullTextIndexes, updatedPrimary.fullTextIndexes) ||
|
|
4601
|
+
!definitionsEqual(descriptor.fullTextFields, updatedPrimary.fullTextFields) ||
|
|
4491
4602
|
JSON.stringify(descriptor.fullTextIndexGenerations ?? {}) !==
|
|
4492
4603
|
JSON.stringify(updatedPrimary.fullTextIndexGenerations ?? {}) ||
|
|
4493
4604
|
JSON.stringify(descriptor.fullTextIndexRetirements ?? []) !==
|
|
@@ -4560,6 +4671,7 @@ function declareTable<TableResourceType>(target: TableTarget, tableDefinition: T
|
|
|
4560
4671
|
} finally {
|
|
4561
4672
|
releaseLock();
|
|
4562
4673
|
}
|
|
4674
|
+
if (fullTextFieldsForPersistence !== undefined) Table.fullTextFields = fullTextFieldsForPersistence;
|
|
4563
4675
|
if (activeFullTextIndexes !== undefined) {
|
|
4564
4676
|
Table.fullTextIndexes = activeFullTextIndexes;
|
|
4565
4677
|
Table.fullTextIndexGenerations = fullTextIndexGenerationMap;
|