deepline 0.3.461 → 0.3.463
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/dist/bundling-sources/sdk/src/client-core.ts +7593 -0
- package/dist/bundling-sources/sdk/src/client.ts +8 -7366
- package/dist/bundling-sources/sdk/src/http-core.ts +1239 -0
- package/dist/bundling-sources/sdk/src/http.ts +6 -1231
- package/dist/bundling-sources/sdk/src/index.ts +4 -1
- package/dist/bundling-sources/sdk/src/play.ts +5 -5
- package/dist/bundling-sources/sdk/src/plays/client-core.ts +437 -0
- package/dist/bundling-sources/sdk/src/plays/client.ts +4 -421
- package/dist/bundling-sources/sdk/src/plays/input-example.ts +3 -4
- package/dist/bundling-sources/sdk/src/plays/play-description.ts +1 -1
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +1 -1
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/server.ts +43 -0
- package/dist/bundling-sources/sdk/src/types.ts +15 -5
- package/dist/bundling-sources/shared_libs/integration-contracts/billing-entitlements.ts +15 -0
- package/dist/bundling-sources/shared_libs/monitors/billing/tamradar.ts +17 -17
- package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +0 -307
- package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
- package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +3 -2
- package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +34 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +61 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +122 -2
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +11 -1
- package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-failure-codes.ts +24 -0
- package/dist/bundling-sources/shared_libs/observability/dlq.ts +32 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +57 -3
- package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +66 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +36 -7
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +250 -11
- package/dist/bundling-sources/shared_libs/play-runtime/array-input-store.ts +319 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +991 -359
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +110 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +155 -6
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +110 -6
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -13
- package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +14 -1
- package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +57 -1
- package/dist/bundling-sources/shared_libs/play-runtime/free-company-lookup-batching.ts +218 -0
- package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +42 -5
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-budget-state-backend.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +92 -31
- package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +69 -14
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +93 -23
- package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +15 -4
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +22 -18
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +5 -0
- package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +190 -14
- package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +131 -0
- package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +77 -2
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +271 -2
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +51 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +27 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-text-for-log.ts +63 -0
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +112 -16
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +104 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +265 -151
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +17 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +35 -14
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +12 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-labels.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +136 -70
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +237 -36
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +148 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +285 -32
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +251 -56
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +29 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/sandbox-create-outcome.ts +27 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +22 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1397 -382
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-array-input-receipts.ts +920 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +38 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +14 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +31 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +20 -7
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +12 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/index.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1496 -320
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +31 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1389 -129
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +162 -23
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +499 -115
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +377 -9
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +117 -8
- package/dist/bundling-sources/shared_libs/play-runtime/secret-resolution-retry-policy.ts +25 -0
- package/dist/bundling-sources/shared_libs/play-runtime/terminal-runtime-performance.ts +391 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/mapped-calls.ts +171 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +16 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +38 -12
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +33 -9
- package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +28 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +55 -5
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +41 -1
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +4 -0
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +9 -3
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest-contract.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +3 -2
- package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +2 -2
- package/dist/bundling-sources/shared_libs/plays/run-output-summary.ts +66 -0
- package/dist/bundling-sources/shared_libs/plays/script-entry.ts +1 -1
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +43 -1
- package/dist/bundling-sources/shared_libs/product-notifications/content.ts +9 -0
- package/dist/bundling-sources/shared_libs/product-notifications/email.ts +91 -13
- package/dist/bundling-sources/shared_libs/product-notifications/events.ts +3 -0
- package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +41 -24
- package/dist/bundling-sources/shared_libs/security/attested-client-ip.ts +91 -0
- package/dist/bundling-sources/shared_libs/security/internal-actor.ts +0 -11
- package/dist/cli/{auth-6HJXNWUG.mjs → auth-LZLBR4C3.mjs} +5 -4
- package/dist/cli/auth-XPGKBJKB.js +41 -0
- package/dist/cli/{billing-6P5HO6QG.js → billing-6TJPNJQD.js} +152 -78
- package/dist/cli/{billing-MJ42N7YF.mjs → billing-OTOP5RE4.mjs} +84 -10
- package/dist/cli/{chunk-FCAZQ7WV.js → chunk-2NISBXMN.js} +52 -50
- package/dist/cli/{chunk-PNATXKLP.js → chunk-2ZIRCBYG.js} +6 -6
- package/dist/cli/{chunk-5FDKJQZE.js → chunk-3BOIOCNX.js} +1 -1
- package/dist/cli/chunk-3BVLLJ3H.mjs +1038 -0
- package/dist/cli/{chunk-FJZILBL7.mjs → chunk-3U5EAP6E.mjs} +5 -5
- package/dist/cli/{describe-FRAVCY5F.mjs → chunk-4YZKBBLZ.mjs} +19 -36
- package/dist/cli/{chunk-QWRHGGUH.js → chunk-5DRNNC72.js} +20 -2
- package/dist/cli/{chunk-Z2GUFYT6.js → chunk-5LEAXRHV.js} +11 -11
- package/dist/cli/{chunk-5MDIZX7M.js → chunk-5LHXOIPT.js} +8 -6
- package/dist/cli/{chunk-NMJ4D2WO.js → chunk-6PMCRYDA.js} +216 -91
- package/dist/cli/{chunk-EBU7LQ64.js → chunk-6V7KVRR5.js} +3 -3
- package/dist/cli/{chunk-MGXEUZHL.mjs → chunk-7D6X7IXW.mjs} +7 -5
- package/dist/cli/{chunk-SAZFZQRI.js → chunk-7FCYPAPP.js} +2 -2
- package/dist/cli/{chunk-ACCR7POB.js → chunk-7XYDDCQ2.js} +27 -27
- package/dist/cli/{chunk-5IYOUBFZ.js → chunk-ALZBANZI.js} +28 -54
- package/dist/cli/{chunk-3DNKFH2G.mjs → chunk-BAPTQDLF.mjs} +19 -1
- package/dist/cli/chunk-BGNWI3KH.js +827 -0
- package/dist/cli/{chunk-V7REJRDZ.mjs → chunk-C25QE4CH.mjs} +1 -1
- package/dist/cli/{chunk-FGMX4HUZ.js → chunk-CBZP6J3V.js} +29 -27
- package/dist/cli/{chunk-QEYHTIV4.mjs → chunk-CTQ56DXP.mjs} +10 -1
- package/dist/cli/{chunk-IHHLTHE7.mjs → chunk-CVQ7N5CV.mjs} +267 -38
- package/dist/cli/{chunk-7DH2FD7Y.mjs → chunk-D464JW3N.mjs} +5 -85
- package/dist/cli/{chunk-MEAIOXJL.mjs → chunk-DHXCBITQ.mjs} +7 -5
- package/dist/cli/chunk-F2RHUPVH.mjs +827 -0
- package/dist/cli/chunk-F6QV42MC.mjs +91 -0
- package/dist/cli/{chunk-OZBWRICM.js → chunk-FK2HNDCN.js} +2 -2
- package/dist/cli/{chunk-BGY2PLP7.mjs → chunk-GUT7CLOL.mjs} +23 -49
- package/dist/cli/{chunk-RY4IVOU3.mjs → chunk-I624J4H5.mjs} +16 -806
- package/dist/cli/{chunk-Z2XUZC34.js → chunk-IAYSWZDJ.js} +188 -76
- package/dist/cli/{chunk-FGLKOWSC.mjs → chunk-IKWRUNAP.mjs} +1 -1
- package/dist/cli/{chunk-KCCOQ5G5.js → chunk-JVDKZJUH.js} +511 -282
- package/dist/cli/{chunk-HDFRJ4IT.mjs → chunk-JVHOS3K3.mjs} +177 -65
- package/dist/cli/chunk-LYFKBLJI.mjs +1039 -0
- package/dist/cli/{chunk-SLEUWLJE.mjs → chunk-MSY22NQW.mjs} +5 -5
- package/dist/cli/{chunk-5FY72YOV.js → chunk-NAPTMYTY.js} +8 -8
- package/dist/cli/{chunk-O6QOMHCH.js → chunk-NDHJR2WZ.js} +37 -35
- package/dist/cli/{chunk-KXMNM4AQ.js → chunk-NMU3VR5U.js} +4 -5
- package/dist/cli/chunk-NTLI6P6Y.mjs +19 -0
- package/dist/cli/{chunk-RFONC4WJ.mjs → chunk-O3BJYD6D.mjs} +3 -3
- package/dist/cli/{describe-2WQY7ZCY.js → chunk-PVY4DPPF.js} +27 -44
- package/dist/cli/{chunk-WIYWSYDS.mjs → chunk-Q2EIZKVX.mjs} +3 -3
- package/dist/cli/{chunk-VZBCEA5S.mjs → chunk-RD6IQ2JY.mjs} +223 -92
- package/dist/cli/chunk-RGOUCIIZ.js +1039 -0
- package/dist/cli/{chunk-EIMG75BT.mjs → chunk-S3A4IXBQ.mjs} +4 -5
- package/dist/cli/{chunk-QIW7TVV6.mjs → chunk-S4XQCFES.mjs} +14 -12
- package/dist/cli/chunk-SKU6ECIY.js +19 -0
- package/dist/cli/{chunk-CRYOUPEB.js → chunk-TIRBDQ3W.js} +16 -16
- package/dist/cli/{chunk-G7L27KZB.mjs → chunk-TKAQR3IB.mjs} +31 -21
- package/dist/cli/{chunk-MDJPEGVN.js → chunk-UC4SFYNU.js} +392 -261
- package/dist/cli/{chunk-3BMLICF7.mjs → chunk-UIURR26V.mjs} +13 -8
- package/dist/cli/{chunk-TNMBPMMC.js → chunk-UROQDCVW.js} +13 -4
- package/dist/cli/{chunk-R64BGGRQ.mjs → chunk-VDGTTH7K.mjs} +2 -2
- package/dist/cli/chunk-VLEVVDWG.js +91 -0
- package/dist/cli/{chunk-R2GLGLDR.mjs → chunk-VPHN2HAL.mjs} +216 -91
- package/dist/cli/chunk-VY2GBNTX.js +1038 -0
- package/dist/cli/{chunk-CFUTOWE4.js → chunk-WG3KGAII.js} +8 -88
- package/dist/cli/{chunk-QAJAJPKK.mjs → chunk-WUMIYOXQ.mjs} +4 -2
- package/dist/cli/{chunk-SCIR5JXW.js → chunk-WUZS2HK6.js} +56 -51
- package/dist/cli/{chunk-T3MVIPHG.mjs → chunk-XDWS2JJT.mjs} +1 -1
- package/dist/cli/{chunk-KGQNIA37.js → chunk-XQCTG5OO.js} +44 -34
- package/dist/cli/{chunk-KVJ5VHW5.mjs → chunk-XW2JIYG7.mjs} +2 -2
- package/dist/cli/chunk-YGGIZ3VT.js +920 -0
- package/dist/cli/command-docs.d.mts +5 -0
- package/dist/cli/command-docs.d.ts +5 -0
- package/dist/cli/command-docs.js +2 -2
- package/dist/cli/command-docs.mjs +1 -1
- package/dist/cli/{csv-NX7NO3O6.js → csv-EH5QWR4O.js} +13 -12
- package/dist/cli/{csv-DQ6GW5B5.mjs → csv-OK45Z5XQ.mjs} +4 -3
- package/dist/cli/{db-R72DFMP6.js → db-3ESJKETS.js} +30 -27
- package/dist/cli/{db-2YP33M4K.mjs → db-6Z5E4HKN.mjs} +10 -7
- package/dist/cli/describe-PNDQB7YS.mjs +48 -0
- package/dist/cli/describe-QUF7VTTR.js +48 -0
- package/dist/cli/describe-core.d.mts +153 -5
- package/dist/cli/describe-core.d.ts +153 -5
- package/dist/cli/describe-core.js +9 -5
- package/dist/cli/describe-core.mjs +10 -6
- package/dist/cli/{executions-WFBU7L2Q.mjs → executions-2NTWQFEG.mjs} +7 -5
- package/dist/cli/{executions-ZLHD4QIT.js → executions-KUOBRX5V.js} +9 -7
- package/dist/cli/{feedback-CN3HJFVF.mjs → feedback-7RPRMSGY.mjs} +6 -5
- package/dist/cli/{feedback-NDV6TPHG.js → feedback-UPHAZJ4C.js} +10 -9
- package/dist/cli/getting-started.d.mts +6 -6
- package/dist/cli/getting-started.d.ts +6 -6
- package/dist/cli/getting-started.js +2 -2
- package/dist/cli/getting-started.mjs +1 -1
- package/dist/cli/{git-QAD6E3HW.mjs → git-SCYP6WSZ.mjs} +5 -4
- package/dist/cli/git-UH653WHV.js +25 -0
- package/dist/cli/index.js +152 -142
- package/dist/cli/index.mjs +56 -46
- package/dist/cli/{legacy-noops-KVC5QJ74.js → legacy-noops-7XMFCVRG.js} +8 -7
- package/dist/cli/{legacy-noops-TPTKNBI2.mjs → legacy-noops-A4KYAGI6.mjs} +5 -4
- package/dist/cli/{monitors-SV57JFLO.mjs → monitors-FLC5J7RI.mjs} +19 -6
- package/dist/cli/{monitors-KCROV6PJ.js → monitors-NZV6IX5H.js} +103 -90
- package/dist/cli/{org-NJYX5743.js → org-IZ7UP3XF.js} +70 -67
- package/dist/cli/{org-KX6QIR7A.mjs → org-LUETJ7Z5.mjs} +9 -6
- package/dist/cli/pages-22ML3O7O.js +252 -0
- package/dist/cli/pages-EUX5EAGF.mjs +252 -0
- package/dist/cli/{play-IQQ57L7Z.mjs → play-CDHPAKKM.mjs} +512 -1508
- package/dist/cli/{play-32L7EQN4.js → play-USJBQADG.js} +1090 -2086
- package/dist/cli/{providers-4WEC2EQN.mjs → providers-CCXZ3SQF.mjs} +7 -5
- package/dist/cli/{providers-ZQV6QLVQ.js → providers-WFEUNPGC.js} +10 -8
- package/dist/cli/{quickstart-HKUSFADF.js → quickstart-O4JSUORZ.js} +13 -12
- package/dist/cli/{quickstart-RQ76RIUE.mjs → quickstart-ZUULI635.mjs} +5 -4
- package/dist/cli/run-ISDJYJMU.js +443 -0
- package/dist/cli/run-QJ4NX5F5.mjs +443 -0
- package/dist/cli/{search-ZRAVFBZC.mjs → search-IX3XKZJ3.mjs} +8 -6
- package/dist/cli/search-TIFNLRPM.js +32 -0
- package/dist/cli/{secrets-CMJOVNVH.mjs → secrets-7VUDXTUZ.mjs} +7 -5
- package/dist/cli/{secrets-J3G5Y43U.js → secrets-ELQSNCTR.js} +16 -14
- package/dist/cli/{sessions-WY7VN4AE.js → sessions-A3FG3AZX.js} +6 -5
- package/dist/cli/{sessions-MDQYY5CB.mjs → sessions-VOIQ62GB.mjs} +5 -4
- package/dist/cli/{settings-4RWZPCT5.mjs → settings-S6N6EFBG.mjs} +14 -11
- package/dist/cli/{settings-HTNTFKCE.js → settings-ZTXQEMZI.js} +80 -77
- package/dist/cli/{setup-P3GYYZWG.mjs → setup-AYPIK4JE.mjs} +12 -10
- package/dist/cli/{setup-QGCAP62X.js → setup-Y3WOIFLS.js} +53 -51
- package/dist/cli/{skills-7NAE4ICL.mjs → skills-5SF5QWNI.mjs} +7 -6
- package/dist/cli/skills-MWFRMG3H.js +31 -0
- package/dist/cli/tools-3XNZ4J64.mjs +55 -0
- package/dist/cli/tools-XEC4OD3R.js +55 -0
- package/dist/cli/{update-GODLRKNB.mjs → update-3U4OVX5R.mjs} +9 -8
- package/dist/cli/update-DWYEYTZE.js +33 -0
- package/dist/cli/{workflow-4BXOUVEO.mjs → workflow-2M5JP7SA.mjs} +10 -8
- package/dist/cli/{workflow-AO3A6LXN.js → workflow-RM7H7555.js} +20 -18
- package/dist/client-DS2IWYZF.d.ts +10 -0
- package/dist/client-DTwnz_AW.d.mts +10 -0
- package/dist/{client-CYqG23K1.d.ts → client-core-B_6HAIBy.d.ts} +385 -12
- package/dist/{client-BbU5_j7n.d.mts → client-core-DzBSlY1U.d.mts} +385 -12
- package/dist/{compiler-manifest-CWz_sNOQ.d.ts → compiler-manifest-Dcyd3-Zd.d.mts} +43 -1
- package/dist/{compiler-manifest-CWz_sNOQ.d.mts → compiler-manifest-Dcyd3-Zd.d.ts} +43 -1
- package/dist/errors-d-sTrZhe.d.mts +142 -0
- package/dist/errors-yQwfgrcX.d.ts +142 -0
- package/dist/{index-BF2JB_Ug.d.mts → index-C6oXchjN.d.mts} +1 -1
- package/dist/{index-4NPXDzlD.d.ts → index-P56zy_z5.d.ts} +1 -1
- package/dist/index.d.mts +11 -147
- package/dist/index.d.ts +11 -147
- package/dist/index.js +16 -12
- package/dist/index.mjs +15 -11
- package/dist/install-integrity.json +141 -104
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +2 -1
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/play-description.js +2 -2
- package/dist/plays/play-description.mjs +1 -1
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/dist/server.d.mts +17 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +76 -0
- package/dist/server.mjs +76 -0
- package/package.json +6 -1
- package/dist/cli/auth-IACERYQH.js +0 -40
- package/dist/cli/chunk-PQUUWFXY.js +0 -95
- package/dist/cli/chunk-YBWAG72P.mjs +0 -95
- package/dist/cli/chunk-YQDUODZW.js +0 -1710
- package/dist/cli/git-JVI36ZFV.js +0 -24
- package/dist/cli/search-75X5LTDE.js +0 -30
- package/dist/cli/skills-BKJ53JOQ.js +0 -30
- package/dist/cli/tools-COWMIEJ6.mjs +0 -45
- package/dist/cli/tools-TASOCE7I.js +0 -45
- package/dist/cli/update-SJIKVME6.js +0 -32
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts
CHANGED
|
@@ -91,7 +91,7 @@ const RUNTIME_EVENT_LOG_POSITION_EXPRESSION = `jsonb_set(
|
|
|
91
91
|
// Migration readiness tracks this projection body independently of scheduler
|
|
92
92
|
// wire and schema versions. Bump when a changed trigger must be reinstalled.
|
|
93
93
|
export const RUNTIME_EVENT_SEARCH_OUTBOX_PROJECTION_MARKER =
|
|
94
|
-
'runtime-event-search-
|
|
94
|
+
'runtime-event-search-legacy-position-resolver-pools';
|
|
95
95
|
/** Trusted trigger-authored state; absent on already-projected legacy rows. */
|
|
96
96
|
export const RUNTIME_EVENT_DEFERRED_PROJECTION_FIELD =
|
|
97
97
|
'_runtimeSearchProjectionPending';
|
|
@@ -1516,6 +1516,12 @@ export async function hasRuntimeEventReaderGrant(
|
|
|
1516
1516
|
);
|
|
1517
1517
|
}
|
|
1518
1518
|
const scope = requiredScope(runtimeScope);
|
|
1519
|
+
// Reject explicit role edges in both directions, including NOINHERIT,
|
|
1520
|
+
// without repeatedly traversing every unrelated role's membership graph.
|
|
1521
|
+
// Keep membership-aware checks for the three exact owners: implicit
|
|
1522
|
+
// pg_database_owner membership has no pg_auth_members edge.
|
|
1523
|
+
// User-created namespaces have indexed pg_depend references; enumerate
|
|
1524
|
+
// their relations without scanning every other Preview namespace's catalog.
|
|
1519
1525
|
const result = await client.query<{ ready: boolean }>(
|
|
1520
1526
|
`SELECT coalesce(roles.rolcanlogin AND NOT roles.rolsuper AND NOT roles.rolbypassrls
|
|
1521
1527
|
AND has_schema_privilege(roles.oid, 'runtime_observability', 'USAGE')
|
|
@@ -1544,36 +1550,35 @@ export async function hasRuntimeEventReaderGrant(
|
|
|
1544
1550
|
AND NOT has_table_privilege(roles.oid, 'runtime_observability.run_log_cursors', 'TRUNCATE')
|
|
1545
1551
|
AND NOT has_table_privilege(roles.oid, 'runtime_observability.run_log_cursors', 'REFERENCES')
|
|
1546
1552
|
AND NOT has_table_privilege(roles.oid, 'runtime_observability.run_log_cursors', 'TRIGGER')
|
|
1547
|
-
AND NOT has_schema_privilege(roles.oid,
|
|
1548
|
-
AND NOT has_schema_privilege(roles.oid,
|
|
1553
|
+
AND NOT has_schema_privilege(roles.oid, runtime_schema.oid, 'USAGE')
|
|
1554
|
+
AND NOT has_schema_privilege(roles.oid, runtime_schema.oid, 'CREATE')
|
|
1549
1555
|
AND NOT EXISTS (SELECT 1 FROM pg_auth_members AS membership
|
|
1550
|
-
WHERE
|
|
1551
|
-
AND NOT
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
AND
|
|
1560
|
-
AND
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
WHERE oid = 'runtime_observability.run_log_cursors'::regclass)
|
|
1565
|
-
AND NOT EXISTS (SELECT 1 FROM pg_class AS scoped_relation
|
|
1566
|
-
JOIN pg_namespace AS scoped_schema ON scoped_schema.oid = scoped_relation.relnamespace
|
|
1567
|
-
WHERE scoped_schema.nspname = $2
|
|
1556
|
+
WHERE membership.member = roles.oid OR membership.roleid = roles.oid)
|
|
1557
|
+
AND NOT pg_has_role(roles.oid, events.relowner, 'USAGE')
|
|
1558
|
+
AND NOT pg_has_role(roles.oid, log_cursors.relowner, 'USAGE')
|
|
1559
|
+
AND events.relrowsecurity
|
|
1560
|
+
AND log_cursors.relrowsecurity
|
|
1561
|
+
AND NOT EXISTS (SELECT 1 FROM pg_depend AS namespace_dependency
|
|
1562
|
+
JOIN pg_class AS scoped_relation ON scoped_relation.oid = namespace_dependency.objid
|
|
1563
|
+
WHERE namespace_dependency.refclassid = 'pg_namespace'::regclass
|
|
1564
|
+
AND namespace_dependency.refobjid = runtime_schema.oid
|
|
1565
|
+
AND namespace_dependency.classid = 'pg_class'::regclass
|
|
1566
|
+
AND namespace_dependency.objsubid = 0
|
|
1567
|
+
AND namespace_dependency.refobjsubid = 0
|
|
1568
|
+
AND namespace_dependency.deptype = 'n'
|
|
1569
|
+
AND scoped_relation.relnamespace = runtime_schema.oid
|
|
1568
1570
|
AND scoped_relation.relkind IN ('r', 'p', 'v', 'm', 'f')
|
|
1569
1571
|
AND (has_table_privilege(roles.oid, scoped_relation.oid, 'SELECT')
|
|
1570
1572
|
OR has_any_column_privilege(roles.oid, scoped_relation.oid, 'SELECT')))
|
|
1571
|
-
AND NOT pg_has_role(roles.oid,
|
|
1572
|
-
(SELECT receipt_function.proowner FROM pg_proc AS receipt_function
|
|
1573
|
-
WHERE receipt_function.oid = 'runtime_observability.fetch_receipt(text,text,text,uuid)'::regprocedure),
|
|
1574
|
-
'USAGE')
|
|
1573
|
+
AND NOT pg_has_role(roles.oid, receipt_function.proowner, 'USAGE')
|
|
1575
1574
|
AND has_function_privilege(roles.oid, 'runtime_observability.fetch_receipt(text,text,text,uuid)', 'EXECUTE'), false) AS ready
|
|
1576
|
-
FROM pg_roles AS roles
|
|
1575
|
+
FROM pg_roles AS roles
|
|
1576
|
+
JOIN pg_namespace AS runtime_schema ON runtime_schema.nspname = $2
|
|
1577
|
+
AND runtime_schema.oid >= 16384::oid
|
|
1578
|
+
JOIN pg_class AS events ON events.oid = 'runtime_observability.events'::regclass
|
|
1579
|
+
JOIN pg_class AS log_cursors ON log_cursors.oid = 'runtime_observability.run_log_cursors'::regclass
|
|
1580
|
+
JOIN pg_proc AS receipt_function ON receipt_function.oid = 'runtime_observability.fetch_receipt(text,text,text,uuid)'::regprocedure
|
|
1581
|
+
WHERE roles.rolname = $1`,
|
|
1577
1582
|
[readerRole, scope],
|
|
1578
1583
|
);
|
|
1579
1584
|
return result.rows[0]?.ready === true;
|
|
@@ -2372,6 +2377,369 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2372
2377
|
${schema}.project_origin_log_batch_with_targets(${schema}.outbox,jsonb,text,text,boolean,boolean,timestamptz,jsonb,boolean)
|
|
2373
2378
|
FROM PUBLIC;
|
|
2374
2379
|
END; $install_fresh_log_sequences$`);
|
|
2380
|
+
// The positional path is used before origin identities are enabled. Keep
|
|
2381
|
+
// its physical lookup contract local, like fresh sequence assignment: a
|
|
2382
|
+
// generic plan warmed on an empty journal must not scan unrelated runs.
|
|
2383
|
+
// VOLATILE preserves visibility of aliases written earlier in this batch.
|
|
2384
|
+
await client.query(`DO $install_legacy_log_access$ BEGIN
|
|
2385
|
+
CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_identity(probe_org text, probe_id text)
|
|
2386
|
+
RETURNS TABLE(runtime_scope text, org_id text, event_id text, run_id text, kind text, source_digest text, search_doc jsonb)
|
|
2387
|
+
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
|
|
2388
|
+
SET enable_seqscan = off SET enable_indexscan = on AS $function$
|
|
2389
|
+
BEGIN RETURN QUERY
|
|
2390
|
+
SELECT candidate.* FROM (
|
|
2391
|
+
SELECT event.runtime_scope, event.org_id, event.event_id, event.run_id,
|
|
2392
|
+
event.kind, event.source_digest, event.search_doc
|
|
2393
|
+
FROM runtime_observability.events AS event
|
|
2394
|
+
WHERE (event.runtime_scope, event.org_id, event.event_id)
|
|
2395
|
+
>= (${quoteLiteral(scope)}, probe_org, probe_id)
|
|
2396
|
+
ORDER BY event.runtime_scope, event.org_id, event.event_id
|
|
2397
|
+
LIMIT 1
|
|
2398
|
+
) AS candidate
|
|
2399
|
+
WHERE candidate.runtime_scope = ${quoteLiteral(scope)}
|
|
2400
|
+
AND candidate.org_id = probe_org AND candidate.event_id = probe_id;
|
|
2401
|
+
END
|
|
2402
|
+
$function$;
|
|
2403
|
+
REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_identity(text,text) FROM PUBLIC;
|
|
2404
|
+
CREATE OR REPLACE FUNCTION ${schema}.update_legacy_log_alias(probe_org text, probe_id text, probe_doc jsonb, probe_run text)
|
|
2405
|
+
RETURNS TABLE(updated_tid tid)
|
|
2406
|
+
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
|
|
2407
|
+
SET enable_seqscan = off SET enable_indexscan = on SET enable_tidscan = on AS $function$
|
|
2408
|
+
DECLARE alias_identity record;
|
|
2409
|
+
alias_target NO SCROLL CURSOR FOR
|
|
2410
|
+
WITH alias_candidate AS MATERIALIZED (
|
|
2411
|
+
SELECT event.ctid AS target_tid
|
|
2412
|
+
FROM runtime_observability.events AS event
|
|
2413
|
+
WHERE (event.runtime_scope, event.org_id, event.event_id)
|
|
2414
|
+
>= (${quoteLiteral(scope)}, probe_org, probe_id)
|
|
2415
|
+
ORDER BY event.runtime_scope, event.org_id, event.event_id
|
|
2416
|
+
LIMIT 1
|
|
2417
|
+
)
|
|
2418
|
+
SELECT event.runtime_scope, event.org_id, event.run_id, event.event_id
|
|
2419
|
+
FROM alias_candidate AS candidate
|
|
2420
|
+
JOIN runtime_observability.events AS event ON event.ctid = candidate.target_tid
|
|
2421
|
+
WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = probe_org
|
|
2422
|
+
AND event.run_id = probe_run AND event.event_id = probe_id
|
|
2423
|
+
FOR UPDATE OF event;
|
|
2424
|
+
BEGIN
|
|
2425
|
+
-- Resolve and lock one exact identity in the same cursor statement.
|
|
2426
|
+
-- Filtering before FOR UPDATE must never lock a neighboring run on EOF.
|
|
2427
|
+
OPEN alias_target;
|
|
2428
|
+
BEGIN
|
|
2429
|
+
FETCH alias_target INTO alias_identity;
|
|
2430
|
+
IF NOT FOUND THEN
|
|
2431
|
+
RAISE EXCEPTION 'Legacy log alias target changed before update' USING ERRCODE = '40001';
|
|
2432
|
+
END IF;
|
|
2433
|
+
IF alias_identity.runtime_scope IS DISTINCT FROM ${quoteLiteral(scope)}
|
|
2434
|
+
OR alias_identity.org_id IS DISTINCT FROM probe_org
|
|
2435
|
+
OR alias_identity.run_id IS DISTINCT FROM probe_run
|
|
2436
|
+
OR alias_identity.event_id IS DISTINCT FROM probe_id THEN
|
|
2437
|
+
RAISE EXCEPTION 'Legacy log alias target changed before update' USING ERRCODE = '40001';
|
|
2438
|
+
END IF;
|
|
2439
|
+
RETURN QUERY
|
|
2440
|
+
UPDATE runtime_observability.events SET search_doc = probe_doc
|
|
2441
|
+
WHERE CURRENT OF alias_target RETURNING ctid;
|
|
2442
|
+
IF NOT FOUND THEN
|
|
2443
|
+
RAISE EXCEPTION 'Legacy log alias target changed before update' USING ERRCODE = '40001';
|
|
2444
|
+
END IF;
|
|
2445
|
+
EXCEPTION WHEN OTHERS THEN
|
|
2446
|
+
-- The cursor predates this exception block, so it remains open after
|
|
2447
|
+
-- rollback of a failed update. Preserve the original SQL error.
|
|
2448
|
+
CLOSE alias_target;
|
|
2449
|
+
RAISE;
|
|
2450
|
+
END;
|
|
2451
|
+
CLOSE alias_target;
|
|
2452
|
+
END
|
|
2453
|
+
$function$;
|
|
2454
|
+
REVOKE ALL ON FUNCTION ${schema}.update_legacy_log_alias(text,text,jsonb,text) FROM PUBLIC;
|
|
2455
|
+
-- These cursors keep a cached, index-ordered lower-bound plan. Stop at the
|
|
2456
|
+
-- first different complete prefix, retaining all equal-prefix occurrences
|
|
2457
|
+
-- before applying the original sequence and identity ordering.
|
|
2458
|
+
CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_position(probe_org text, probe_run text, probe_channel text, probe_alias jsonb)
|
|
2459
|
+
RETURNS TABLE(event_id text, source_digest text, search_doc jsonb)
|
|
2460
|
+
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
|
|
2461
|
+
SET enable_seqscan = off SET enable_indexscan = on AS $function$
|
|
2462
|
+
DECLARE candidate record; active_cursor refcursor;
|
|
2463
|
+
best_id text; best_digest text; best_doc jsonb; best_seq bigint;
|
|
2464
|
+
${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
|
|
2465
|
+
(channel) => `
|
|
2466
|
+
${channel}_positions NO SCROLL CURSOR FOR
|
|
2467
|
+
SELECT ARRAY[event.runtime_scope, event.org_id, event.run_id] AS key_scope,
|
|
2468
|
+
event.search_doc->'producerAttempt' AS key_attempt,
|
|
2469
|
+
event.search_doc->'logPositions'->'${channel}' AS key_position,
|
|
2470
|
+
event.event_id, event.source_digest, event.search_doc, event.log_seq
|
|
2471
|
+
FROM runtime_observability.events AS event
|
|
2472
|
+
WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2473
|
+
AND event.search_doc ? 'producerAttempt' AND event.search_doc ? 'logPositions'
|
|
2474
|
+
AND (event.search_doc->'logPositions') ? '${channel}'
|
|
2475
|
+
AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
|
|
2476
|
+
event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
|
|
2477
|
+
>= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
|
|
2478
|
+
probe_alias->'producerAttempt', probe_alias->'${channel}')
|
|
2479
|
+
AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
|
|
2480
|
+
event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
|
|
2481
|
+
<= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
|
|
2482
|
+
probe_alias->'producerAttempt', probe_alias->'${channel}')
|
|
2483
|
+
ORDER BY ARRAY[event.runtime_scope, event.org_id, event.run_id],
|
|
2484
|
+
event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}';
|
|
2485
|
+
`,
|
|
2486
|
+
).join('')}
|
|
2487
|
+
BEGIN
|
|
2488
|
+
CASE probe_channel
|
|
2489
|
+
${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
|
|
2490
|
+
(channel) => `
|
|
2491
|
+
WHEN '${channel}' THEN OPEN ${channel}_positions; active_cursor := ${channel}_positions;
|
|
2492
|
+
`,
|
|
2493
|
+
).join('')}
|
|
2494
|
+
ELSE RAISE EXCEPTION 'Legacy log read channel is invalid';
|
|
2495
|
+
END CASE;
|
|
2496
|
+
BEGIN
|
|
2497
|
+
LOOP
|
|
2498
|
+
FETCH active_cursor INTO candidate;
|
|
2499
|
+
EXIT WHEN NOT FOUND;
|
|
2500
|
+
EXIT WHEN candidate.key_scope IS DISTINCT FROM ARRAY[${quoteLiteral(scope)}, probe_org, probe_run]
|
|
2501
|
+
OR candidate.key_attempt IS DISTINCT FROM probe_alias->'producerAttempt'
|
|
2502
|
+
OR candidate.key_position IS DISTINCT FROM probe_alias->probe_channel;
|
|
2503
|
+
IF best_id IS NULL OR (candidate.log_seq IS NOT NULL AND best_seq IS NULL)
|
|
2504
|
+
OR candidate.log_seq < best_seq
|
|
2505
|
+
OR (candidate.log_seq IS NOT DISTINCT FROM best_seq AND candidate.event_id < best_id) THEN
|
|
2506
|
+
best_id := candidate.event_id; best_digest := candidate.source_digest;
|
|
2507
|
+
best_doc := candidate.search_doc; best_seq := candidate.log_seq;
|
|
2508
|
+
END IF;
|
|
2509
|
+
END LOOP;
|
|
2510
|
+
EXCEPTION WHEN OTHERS THEN
|
|
2511
|
+
CLOSE active_cursor;
|
|
2512
|
+
RAISE;
|
|
2513
|
+
END;
|
|
2514
|
+
CLOSE active_cursor;
|
|
2515
|
+
IF best_id IS NOT NULL THEN RETURN QUERY SELECT best_id, best_digest, best_doc; END IF;
|
|
2516
|
+
END
|
|
2517
|
+
$function$;
|
|
2518
|
+
REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_position(text,text,text,jsonb) FROM PUBLIC;
|
|
2519
|
+
-- Resolve direct and aliased positions once per line. This intentionally
|
|
2520
|
+
-- retains the old helper signature above for already-installed callers.
|
|
2521
|
+
CREATE OR REPLACE FUNCTION ${schema}.resolve_legacy_log_position(probe_org text, probe_run text, probe_channel text, probe_alias jsonb, probe_position bigint, probe_worker_key text, probe_ids text[])
|
|
2522
|
+
RETURNS TABLE(event_id text, source_digest text, search_doc jsonb, worker_key_reserved boolean)
|
|
2523
|
+
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
|
|
2524
|
+
SET enable_seqscan = off SET enable_indexscan = on AS $function$
|
|
2525
|
+
DECLARE candidate record; active_cursor refcursor;
|
|
2526
|
+
best_id text; best_digest text; best_doc jsonb; best_seq bigint; worker_reserved boolean;
|
|
2527
|
+
${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
|
|
2528
|
+
(channel) => `
|
|
2529
|
+
${channel}_positions NO SCROLL CURSOR FOR
|
|
2530
|
+
SELECT ARRAY[event.runtime_scope, event.org_id, event.run_id] AS key_scope,
|
|
2531
|
+
event.search_doc->'producerAttempt' AS key_attempt,
|
|
2532
|
+
event.search_doc->'logPositions'->'${channel}' AS key_position,
|
|
2533
|
+
event.event_id, event.source_digest, event.search_doc, event.log_seq
|
|
2534
|
+
FROM runtime_observability.events AS event
|
|
2535
|
+
WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2536
|
+
AND event.search_doc ? 'producerAttempt' AND event.search_doc ? 'logPositions'
|
|
2537
|
+
AND (event.search_doc->'logPositions') ? '${channel}'
|
|
2538
|
+
AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
|
|
2539
|
+
event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
|
|
2540
|
+
>= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
|
|
2541
|
+
probe_alias->'producerAttempt', probe_alias->'${channel}')
|
|
2542
|
+
AND ROW(ARRAY[event.runtime_scope, event.org_id, event.run_id],
|
|
2543
|
+
event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}')
|
|
2544
|
+
<= ROW(ARRAY[${quoteLiteral(scope)}, probe_org, probe_run],
|
|
2545
|
+
probe_alias->'producerAttempt', probe_alias->'${channel}')
|
|
2546
|
+
ORDER BY ARRAY[event.runtime_scope, event.org_id, event.run_id],
|
|
2547
|
+
event.search_doc->'producerAttempt', event.search_doc->'logPositions'->'${channel}';
|
|
2548
|
+
`,
|
|
2549
|
+
).join('')}
|
|
2550
|
+
BEGIN
|
|
2551
|
+
IF probe_channel NOT IN ('worker','replay','envelope') OR probe_channel IS NULL THEN
|
|
2552
|
+
RAISE EXCEPTION 'Legacy log read channel is invalid';
|
|
2553
|
+
END IF;
|
|
2554
|
+
-- All historical primary-key candidates share this one planner/security
|
|
2555
|
+
-- boundary. Keep the old complete-key seek and exact equality check;
|
|
2556
|
+
-- never prefetch absence across lines or change positional precedence.
|
|
2557
|
+
WITH identities AS MATERIALIZED (
|
|
2558
|
+
SELECT identity.*
|
|
2559
|
+
FROM unnest(probe_ids) AS keys(event_id)
|
|
2560
|
+
CROSS JOIN LATERAL (
|
|
2561
|
+
SELECT identity_candidate.* FROM (
|
|
2562
|
+
SELECT event.runtime_scope, event.org_id, event.event_id, event.run_id,
|
|
2563
|
+
event.kind, event.source_digest, event.search_doc
|
|
2564
|
+
FROM runtime_observability.events AS event
|
|
2565
|
+
WHERE (event.runtime_scope, event.org_id, event.event_id)
|
|
2566
|
+
>= (${quoteLiteral(scope)}, probe_org, keys.event_id)
|
|
2567
|
+
ORDER BY event.runtime_scope, event.org_id, event.event_id
|
|
2568
|
+
LIMIT 1
|
|
2569
|
+
) AS identity_candidate
|
|
2570
|
+
WHERE identity_candidate.runtime_scope = ${quoteLiteral(scope)}
|
|
2571
|
+
AND identity_candidate.org_id = probe_org AND identity_candidate.event_id = keys.event_id
|
|
2572
|
+
) AS identity
|
|
2573
|
+
)
|
|
2574
|
+
SELECT matched.event_id, matched.source_digest, matched.search_doc,
|
|
2575
|
+
coalesce(reserved.worker_reserved, false)
|
|
2576
|
+
INTO best_id, best_digest, best_doc, worker_reserved
|
|
2577
|
+
FROM (
|
|
2578
|
+
SELECT bool_or(event.event_id = probe_worker_key
|
|
2579
|
+
AND event.search_doc->>'source' = 'coordinator'
|
|
2580
|
+
AND NOT (coalesce(event.search_doc->'logPositions', '{}'::jsonb) ? 'worker')) AS worker_reserved
|
|
2581
|
+
FROM identities AS event
|
|
2582
|
+
) AS reserved
|
|
2583
|
+
LEFT JOIN LATERAL (
|
|
2584
|
+
SELECT event.event_id, event.source_digest, event.search_doc
|
|
2585
|
+
FROM identities AS event
|
|
2586
|
+
WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = probe_org
|
|
2587
|
+
AND event.run_id = probe_run AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2588
|
+
AND (
|
|
2589
|
+
event.search_doc->'logPositions'->>probe_channel = probe_position::text
|
|
2590
|
+
OR (NOT (event.search_doc ? 'logPositions')
|
|
2591
|
+
AND event.event_id = probe_worker_key
|
|
2592
|
+
AND (CASE WHEN event.search_doc->>'source' = 'coordinator'
|
|
2593
|
+
THEN 'replay' ELSE 'worker' END) = probe_channel)
|
|
2594
|
+
)
|
|
2595
|
+
ORDER BY event.event_id LIMIT 1
|
|
2596
|
+
) AS matched ON true;
|
|
2597
|
+
IF best_id IS NOT NULL THEN
|
|
2598
|
+
RETURN QUERY SELECT best_id, best_digest, best_doc, worker_reserved;
|
|
2599
|
+
RETURN;
|
|
2600
|
+
END IF;
|
|
2601
|
+
CASE probe_channel
|
|
2602
|
+
${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
|
|
2603
|
+
(channel) => `
|
|
2604
|
+
WHEN '${channel}' THEN OPEN ${channel}_positions; active_cursor := ${channel}_positions;
|
|
2605
|
+
`,
|
|
2606
|
+
).join('')}
|
|
2607
|
+
ELSE RAISE EXCEPTION 'Legacy log read channel is invalid';
|
|
2608
|
+
END CASE;
|
|
2609
|
+
BEGIN
|
|
2610
|
+
LOOP
|
|
2611
|
+
FETCH active_cursor INTO candidate;
|
|
2612
|
+
EXIT WHEN NOT FOUND;
|
|
2613
|
+
EXIT WHEN candidate.key_scope IS DISTINCT FROM ARRAY[${quoteLiteral(scope)}, probe_org, probe_run]
|
|
2614
|
+
OR candidate.key_attempt IS DISTINCT FROM probe_alias->'producerAttempt'
|
|
2615
|
+
OR candidate.key_position IS DISTINCT FROM probe_alias->probe_channel;
|
|
2616
|
+
IF best_id IS NULL OR (candidate.log_seq IS NOT NULL AND best_seq IS NULL)
|
|
2617
|
+
OR candidate.log_seq < best_seq
|
|
2618
|
+
OR (candidate.log_seq IS NOT DISTINCT FROM best_seq AND candidate.event_id < best_id) THEN
|
|
2619
|
+
best_id := candidate.event_id; best_digest := candidate.source_digest;
|
|
2620
|
+
best_doc := candidate.search_doc; best_seq := candidate.log_seq;
|
|
2621
|
+
END IF;
|
|
2622
|
+
END LOOP;
|
|
2623
|
+
EXCEPTION WHEN OTHERS THEN
|
|
2624
|
+
CLOSE active_cursor;
|
|
2625
|
+
RAISE;
|
|
2626
|
+
END;
|
|
2627
|
+
CLOSE active_cursor;
|
|
2628
|
+
RETURN QUERY SELECT best_id, best_digest, best_doc, worker_reserved;
|
|
2629
|
+
END
|
|
2630
|
+
$function$;
|
|
2631
|
+
REVOKE ALL ON FUNCTION ${schema}.resolve_legacy_log_position(text,text,text,jsonb,bigint,text,text[]) FROM PUBLIC;
|
|
2632
|
+
CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_occurrence(probe_org text, probe_run text, probe_attempt text, probe_digest text, probe_channel text)
|
|
2633
|
+
RETURNS TABLE(event_id text, search_doc jsonb)
|
|
2634
|
+
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
|
|
2635
|
+
SET enable_seqscan = off SET enable_indexscan = on AS $function$
|
|
2636
|
+
DECLARE candidate record; best_id text; best_doc jsonb; best_seq bigint;
|
|
2637
|
+
digest_occurrences NO SCROLL CURSOR FOR
|
|
2638
|
+
SELECT event.runtime_scope, event.org_id, event.run_id,
|
|
2639
|
+
event.search_doc->>'producerAttempt' AS key_attempt,
|
|
2640
|
+
event.source_digest, event.event_id, event.search_doc, event.log_seq
|
|
2641
|
+
FROM runtime_observability.events AS event
|
|
2642
|
+
WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2643
|
+
AND event.source_digest IS NOT NULL AND event.search_doc ? 'producerAttempt'
|
|
2644
|
+
AND event.search_doc ? 'logContentDigest'
|
|
2645
|
+
AND ROW(event.runtime_scope, event.org_id, event.run_id,
|
|
2646
|
+
event.search_doc->>'producerAttempt', event.source_digest)
|
|
2647
|
+
>= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
|
|
2648
|
+
AND ROW(event.runtime_scope, event.org_id, event.run_id,
|
|
2649
|
+
event.search_doc->>'producerAttempt', event.source_digest)
|
|
2650
|
+
<= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
|
|
2651
|
+
ORDER BY event.runtime_scope, event.org_id, event.run_id,
|
|
2652
|
+
event.search_doc->>'producerAttempt', event.source_digest;
|
|
2653
|
+
BEGIN
|
|
2654
|
+
IF probe_channel NOT IN ('worker','replay','envelope') OR probe_channel IS NULL THEN
|
|
2655
|
+
RAISE EXCEPTION 'Legacy log read channel is invalid';
|
|
2656
|
+
END IF;
|
|
2657
|
+
OPEN digest_occurrences;
|
|
2658
|
+
BEGIN
|
|
2659
|
+
LOOP
|
|
2660
|
+
FETCH digest_occurrences INTO candidate;
|
|
2661
|
+
EXIT WHEN NOT FOUND;
|
|
2662
|
+
EXIT WHEN candidate.runtime_scope IS DISTINCT FROM ${quoteLiteral(scope)}
|
|
2663
|
+
OR candidate.org_id IS DISTINCT FROM probe_org OR candidate.run_id IS DISTINCT FROM probe_run
|
|
2664
|
+
OR candidate.key_attempt IS DISTINCT FROM probe_attempt OR candidate.source_digest IS DISTINCT FROM probe_digest;
|
|
2665
|
+
IF NOT (candidate.search_doc ? 'entryId')
|
|
2666
|
+
AND candidate.search_doc @> jsonb_build_object('logContentDigest', probe_digest)
|
|
2667
|
+
AND NOT (coalesce(candidate.search_doc->'logPositions', '{}'::jsonb) ? probe_channel)
|
|
2668
|
+
AND (candidate.search_doc ? 'logPositions' OR probe_channel <>
|
|
2669
|
+
CASE WHEN candidate.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END)
|
|
2670
|
+
AND (best_id IS NULL OR (candidate.log_seq IS NOT NULL AND best_seq IS NULL)
|
|
2671
|
+
OR candidate.log_seq < best_seq
|
|
2672
|
+
OR (candidate.log_seq IS NOT DISTINCT FROM best_seq AND candidate.event_id < best_id)) THEN
|
|
2673
|
+
best_id := candidate.event_id; best_doc := candidate.search_doc; best_seq := candidate.log_seq;
|
|
2674
|
+
END IF;
|
|
2675
|
+
END LOOP;
|
|
2676
|
+
EXCEPTION WHEN OTHERS THEN
|
|
2677
|
+
CLOSE digest_occurrences;
|
|
2678
|
+
RAISE;
|
|
2679
|
+
END;
|
|
2680
|
+
CLOSE digest_occurrences;
|
|
2681
|
+
IF best_id IS NOT NULL THEN RETURN QUERY SELECT best_id, best_doc; END IF;
|
|
2682
|
+
END
|
|
2683
|
+
$function$;
|
|
2684
|
+
REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_occurrence(text,text,text,text,text) FROM PUBLIC;
|
|
2685
|
+
-- A request can consume at most probe_count distinct occurrences. Keep
|
|
2686
|
+
-- only that necessary rank, not the run's whole equal-digest history. The
|
|
2687
|
+
-- inner order preserves the existing complete-prefix access contract;
|
|
2688
|
+
-- the outer top-N sort holds only compact identity/sequence metadata.
|
|
2689
|
+
CREATE OR REPLACE FUNCTION ${schema}.lookup_legacy_log_occurrence_pool(
|
|
2690
|
+
probe_org text, probe_run text, probe_attempt text, probe_digest text,
|
|
2691
|
+
probe_channel text, probe_count bigint)
|
|
2692
|
+
RETURNS TABLE(event_id text, cacheable boolean)
|
|
2693
|
+
LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = pg_catalog
|
|
2694
|
+
SET enable_seqscan = off SET enable_indexscan = on AS $function$
|
|
2695
|
+
DECLARE candidate record; emitted boolean := false;
|
|
2696
|
+
BEGIN
|
|
2697
|
+
IF probe_channel NOT IN ('worker','replay','envelope') OR probe_channel IS NULL
|
|
2698
|
+
OR probe_count IS NULL OR probe_count < 1 THEN
|
|
2699
|
+
RAISE EXCEPTION 'Legacy log occurrence pool requires a channel and positive request rank';
|
|
2700
|
+
END IF;
|
|
2701
|
+
FOR candidate IN
|
|
2702
|
+
SELECT prefix.event_id, prefix.log_seq,
|
|
2703
|
+
(prefix.null_entry OR prefix.null_channel) IS TRUE AS unsafe
|
|
2704
|
+
FROM (
|
|
2705
|
+
SELECT event.event_id, event.log_seq, event.search_doc ? 'entryId' AS has_entry_id,
|
|
2706
|
+
event.search_doc->'entryId' = 'null'::jsonb AS null_entry,
|
|
2707
|
+
event.search_doc @> jsonb_build_object('logContentDigest', probe_digest) AS same_digest,
|
|
2708
|
+
coalesce(event.search_doc->'logPositions', '{}'::jsonb) ? probe_channel AS has_channel,
|
|
2709
|
+
event.search_doc->'logPositions'->probe_channel = 'null'::jsonb AS null_channel,
|
|
2710
|
+
event.search_doc ? 'logPositions' OR probe_channel <>
|
|
2711
|
+
CASE WHEN event.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END AS cross_channel
|
|
2712
|
+
FROM runtime_observability.events AS event
|
|
2713
|
+
WHERE event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2714
|
+
AND event.source_digest IS NOT NULL AND event.search_doc ? 'producerAttempt'
|
|
2715
|
+
AND event.search_doc ? 'logContentDigest'
|
|
2716
|
+
AND ROW(event.runtime_scope, event.org_id, event.run_id,
|
|
2717
|
+
event.search_doc->>'producerAttempt', event.source_digest)
|
|
2718
|
+
>= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
|
|
2719
|
+
AND ROW(event.runtime_scope, event.org_id, event.run_id,
|
|
2720
|
+
event.search_doc->>'producerAttempt', event.source_digest)
|
|
2721
|
+
<= ROW(${quoteLiteral(scope)}, probe_org, probe_run, probe_attempt, probe_digest)
|
|
2722
|
+
ORDER BY event.runtime_scope, event.org_id, event.run_id,
|
|
2723
|
+
event.search_doc->>'producerAttempt', event.source_digest
|
|
2724
|
+
OFFSET 0
|
|
2725
|
+
) AS prefix
|
|
2726
|
+
WHERE (NOT prefix.has_entry_id AND prefix.same_digest
|
|
2727
|
+
AND NOT prefix.has_channel AND prefix.cross_channel)
|
|
2728
|
+
OR prefix.null_entry OR prefix.null_channel
|
|
2729
|
+
ORDER BY unsafe DESC, prefix.log_seq NULLS LAST, prefix.event_id
|
|
2730
|
+
LIMIT probe_count
|
|
2731
|
+
LOOP
|
|
2732
|
+
-- TTL strips null object members without the log mutex. Such legacy
|
|
2733
|
+
-- metadata can become newly eligible, so retain its scalar semantics.
|
|
2734
|
+
IF candidate.unsafe THEN RETURN QUERY SELECT NULL::text, false; RETURN; END IF;
|
|
2735
|
+
emitted := true;
|
|
2736
|
+
RETURN QUERY SELECT candidate.event_id::text, true;
|
|
2737
|
+
END LOOP;
|
|
2738
|
+
IF NOT emitted THEN RETURN QUERY SELECT NULL::text, true; END IF;
|
|
2739
|
+
END
|
|
2740
|
+
$function$;
|
|
2741
|
+
REVOKE ALL ON FUNCTION ${schema}.lookup_legacy_log_occurrence_pool(text,text,text,text,text,bigint) FROM PUBLIC;
|
|
2742
|
+
END; $install_legacy_log_access$`);
|
|
2375
2743
|
const acquireLogCursorSql = `
|
|
2376
2744
|
IF NOT cursor_locked THEN
|
|
2377
2745
|
-- One allocation owner supplies final sequences at INSERT time. The
|
|
@@ -2398,7 +2766,10 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2398
2766
|
doc jsonb; line_doc jsonb; line_context jsonb; line_metadata jsonb; line_at timestamptz;
|
|
2399
2767
|
eid text; existing_digest text; digest text; assigned_seq bigint; terminal_progress_identity boolean;
|
|
2400
2768
|
log_channel text; log_position bigint; matched_event_id text; matched_doc jsonb;
|
|
2401
|
-
legacy_position_prefix text; position_event_ids text[];
|
|
2769
|
+
legacy_position_prefix text; position_event_ids text[]; worker_key_reserved boolean;
|
|
2770
|
+
occurrence_pool_digests text[]; occurrence_pool_ids text[]; occurrence_pool_cacheable boolean[];
|
|
2771
|
+
occurrence_pool_heads integer[]; occurrence_pool_loaded boolean;
|
|
2772
|
+
occurrence_low integer; occurrence_high integer; occurrence_mid integer; occurrence_group integer; occurrence_head integer;
|
|
2402
2773
|
log_alias jsonb; position_alias jsonb; envelope_attempt jsonb;
|
|
2403
2774
|
cursor_created boolean := false; cursor_locked boolean := false; line_count bigint; fresh_event_ids text[] := ARRAY[]::text[];
|
|
2404
2775
|
fresh_tids tid[] := ARRAY[]::tid[]; inserted_tid tid;
|
|
@@ -2537,20 +2908,24 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2537
2908
|
-- unmarked rows otherwise scans the whole attempt for every new line.
|
|
2538
2909
|
IF EXISTS (SELECT 1 FROM jsonb_array_elements(event_batch) AS entry
|
|
2539
2910
|
WHERE entry->>'type' = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended} AND (NOT (entry ? 'lineIds') OR EXISTS (SELECT 1 FROM jsonb_array_elements(CASE WHEN jsonb_typeof(entry->'lineIds') = 'array' THEN entry->'lineIds' ELSE '[]'::jsonb END) id WHERE id = 'null'::jsonb))) THEN
|
|
2911
|
+
-- Replan this once-per-batch legacy normalization with its real run.
|
|
2912
|
+
-- A retained empty-table plan otherwise rereads every run's history.
|
|
2913
|
+
EXECUTE $legacy_normalize$
|
|
2540
2914
|
UPDATE runtime_observability.events AS event SET search_doc = event.search_doc ||
|
|
2541
2915
|
jsonb_build_object('logContentDigest', event.source_digest) ||
|
|
2542
2916
|
CASE WHEN NOT (event.search_doc ? 'logPositions')
|
|
2543
|
-
AND left(event.event_id, length('log:' ||
|
|
2544
|
-
'log:' ||
|
|
2545
|
-
AND substring(event.event_id FROM length('log:' ||
|
|
2917
|
+
AND left(event.event_id, length('log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':')) =
|
|
2918
|
+
'log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':'
|
|
2919
|
+
AND substring(event.event_id FROM length('log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':') + 1) ~ '^[0-9]{1,12}$'
|
|
2546
2920
|
THEN jsonb_build_object('logPositions', jsonb_build_object(
|
|
2547
2921
|
CASE WHEN event.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END,
|
|
2548
|
-
substring(event.event_id FROM length('log:' ||
|
|
2922
|
+
substring(event.event_id FROM length('log:' || $2 || ':' || (event.search_doc->>'producerAttempt') || ':') + 1)::bigint))
|
|
2549
2923
|
ELSE '{}'::jsonb END
|
|
2550
|
-
WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id =
|
|
2551
|
-
AND event.run_id =
|
|
2924
|
+
WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = $1
|
|
2925
|
+
AND event.run_id = $2 AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2552
2926
|
AND event.source_digest IS NOT NULL AND NOT (event.search_doc ? 'logContentDigest') AND NOT (event.search_doc ? 'entryId')
|
|
2553
|
-
AND (event.search_doc->>'producerAttempt') ~ '^[1-9][0-9]{0,5}$'
|
|
2927
|
+
AND (event.search_doc->>'producerAttempt') ~ '^[1-9][0-9]{0,5}$'
|
|
2928
|
+
$legacy_normalize$ USING run_org, observation.run_id;
|
|
2554
2929
|
END IF;
|
|
2555
2930
|
FOR item, ordinal IN SELECT value, ordinality FROM jsonb_array_elements(event_batch) WITH ORDINALITY LOOP
|
|
2556
2931
|
IF jsonb_typeof(item) IS DISTINCT FROM 'object'
|
|
@@ -2613,6 +2988,7 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2613
2988
|
END IF;
|
|
2614
2989
|
END IF;
|
|
2615
2990
|
IF kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended} THEN
|
|
2991
|
+
occurrence_pool_loaded := false;
|
|
2616
2992
|
FOR line, line_ordinal IN SELECT value, ordinality FROM jsonb_array_elements(item->'lines') WITH ORDINALITY LOOP
|
|
2617
2993
|
IF jsonb_typeof(line) IS DISTINCT FROM 'string' THEN
|
|
2618
2994
|
RAISE EXCEPTION 'Search projection requires log line strings';
|
|
@@ -2700,17 +3076,6 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2700
3076
|
eid := CASE WHEN log_channel = 'worker' THEN legacy_position_prefix
|
|
2701
3077
|
ELSE 'log-' || log_channel || ':' || observation.run_id || ':' || (item->>'producerAttempt') || ':' END
|
|
2702
3078
|
|| log_position::text;
|
|
2703
|
-
-- Older coordinator replays used the worker-shaped primary
|
|
2704
|
-
-- key. Do not overwrite it when a delayed worker owns a
|
|
2705
|
-
-- different line at that number; aliases remain authoritative.
|
|
2706
|
-
IF log_channel = 'worker' AND EXISTS (
|
|
2707
|
-
SELECT 1 FROM runtime_observability.events
|
|
2708
|
-
WHERE runtime_scope = ${quoteLiteral(scope)} AND org_id = run_org AND event_id = eid
|
|
2709
|
-
AND search_doc->>'source' = 'coordinator'
|
|
2710
|
-
AND NOT (coalesce(search_doc->'logPositions', '{}'::jsonb) ? 'worker')
|
|
2711
|
-
) THEN
|
|
2712
|
-
eid := 'log-worker:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text;
|
|
2713
|
-
END IF;
|
|
2714
3079
|
log_alias := jsonb_build_object('producerAttempt', (item->>'producerAttempt')::integer,
|
|
2715
3080
|
'logPositions', jsonb_build_object(log_channel, log_position));
|
|
2716
3081
|
position_alias := jsonb_build_object(
|
|
@@ -2723,53 +3088,18 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2723
3088
|
'log-replay:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text,
|
|
2724
3089
|
'log-envelope:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text
|
|
2725
3090
|
];
|
|
2726
|
-
--
|
|
2727
|
-
--
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
INTO matched_event_id, existing_digest, matched_doc
|
|
2731
|
-
FROM
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
AND event.event_id = legacy_position_prefix || log_position::text
|
|
2739
|
-
AND (CASE WHEN event.search_doc->>'source' = 'coordinator'
|
|
2740
|
-
THEN 'replay' ELSE 'worker' END) = log_channel)
|
|
2741
|
-
)
|
|
2742
|
-
ORDER BY event.event_id
|
|
2743
|
-
LIMIT 1;
|
|
2744
|
-
IF matched_event_id IS NULL THEN
|
|
2745
|
-
-- Pack scope, organization and run into one indexed key.
|
|
2746
|
-
-- The materialization keeps generic plans from choosing a
|
|
2747
|
-
-- run-history scan based on the outer identity checks.
|
|
2748
|
-
WITH position_matches AS MATERIALIZED (
|
|
2749
|
-
${RUNTIME_EVENT_LOG_POSITION_CHANNELS.map(
|
|
2750
|
-
(channel) => `
|
|
2751
|
-
SELECT event.event_id, event.source_digest, event.search_doc,
|
|
2752
|
-
event.log_seq, event.runtime_scope, event.org_id, event.run_id
|
|
2753
|
-
FROM runtime_observability.events AS event
|
|
2754
|
-
WHERE log_channel = '${channel}'
|
|
2755
|
-
AND ARRAY[event.runtime_scope, event.org_id, event.run_id]
|
|
2756
|
-
= ARRAY[${quoteLiteral(scope)}, run_org, observation.run_id]
|
|
2757
|
-
AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2758
|
-
AND event.search_doc ? 'producerAttempt'
|
|
2759
|
-
AND event.search_doc ? 'logPositions'
|
|
2760
|
-
AND (event.search_doc->'logPositions') ? '${channel}'
|
|
2761
|
-
AND event.search_doc->'producerAttempt' = position_alias->'producerAttempt'
|
|
2762
|
-
AND event.search_doc->'logPositions'->'${channel}' = position_alias->'${channel}'
|
|
2763
|
-
`,
|
|
2764
|
-
).join(' UNION ALL ')}
|
|
2765
|
-
)
|
|
2766
|
-
SELECT event.event_id, event.source_digest, event.search_doc
|
|
2767
|
-
INTO matched_event_id, existing_digest, matched_doc
|
|
2768
|
-
FROM position_matches AS event
|
|
2769
|
-
WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = run_org
|
|
2770
|
-
AND event.run_id = observation.run_id
|
|
2771
|
-
ORDER BY event.log_seq NULLS LAST, event.event_id
|
|
2772
|
-
LIMIT 1;
|
|
3091
|
+
-- Resolve every direct key and the fallback alias in one
|
|
3092
|
+
-- private scope, preserving the same live per-line decisions.
|
|
3093
|
+
SELECT event.event_id, event.source_digest, event.search_doc,
|
|
3094
|
+
event.worker_key_reserved
|
|
3095
|
+
INTO matched_event_id, existing_digest, matched_doc, worker_key_reserved
|
|
3096
|
+
FROM ${schema}.resolve_legacy_log_position(run_org, observation.run_id,
|
|
3097
|
+
log_channel, position_alias, log_position,
|
|
3098
|
+
legacy_position_prefix || log_position::text, position_event_ids) AS event;
|
|
3099
|
+
-- Older coordinator replays used the worker-shaped primary
|
|
3100
|
+
-- key. Keep that conflict decision even when no position matches.
|
|
3101
|
+
IF log_channel = 'worker' AND worker_key_reserved THEN
|
|
3102
|
+
eid := 'log-worker:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' || log_position::text;
|
|
2773
3103
|
END IF;
|
|
2774
3104
|
IF matched_event_id IS NOT NULL THEN
|
|
2775
3105
|
IF existing_digest IS DISTINCT FROM digest THEN
|
|
@@ -2777,30 +3107,84 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2777
3107
|
END IF;
|
|
2778
3108
|
CONTINUE;
|
|
2779
3109
|
END IF;
|
|
2780
|
-
--
|
|
2781
|
-
--
|
|
2782
|
-
--
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
3110
|
+
-- Positional decisions stay in original line order. Only the
|
|
3111
|
+
-- occurrence candidates are shared within this one item: an
|
|
3112
|
+
-- inserted line already has this channel (or entryId), and an
|
|
3113
|
+
-- alias can only remove eligibility, never add another row.
|
|
3114
|
+
IF NOT occurrence_pool_loaded THEN
|
|
3115
|
+
EXECUTE $legacy_occurrence_pools$
|
|
3116
|
+
WITH requested AS MATERIALIZED (
|
|
3117
|
+
SELECT CASE WHEN NULLIF($2->((entry.ordinality-1)::integer), 'null'::jsonb) IS NULL
|
|
3118
|
+
THEN encode(sha256(convert_to(entry.value #>> '{}','UTF8')),'hex')
|
|
3119
|
+
ELSE encode(sha256(convert_to(jsonb_build_array(entry.value #>> '{}',
|
|
3120
|
+
$2->((entry.ordinality-1)::integer))::text,'UTF8')),'hex') END AS content_digest
|
|
3121
|
+
FROM jsonb_array_elements($1) WITH ORDINALITY AS entry(value, ordinality)
|
|
3122
|
+
WHERE jsonb_typeof(entry.value) = 'string'
|
|
3123
|
+
AND NULLIF($3->((entry.ordinality-1)::integer), 'null'::jsonb) IS NULL
|
|
3124
|
+
), groups AS (
|
|
3125
|
+
SELECT content_digest, count(*) AS request_count FROM requested GROUP BY content_digest
|
|
3126
|
+
)
|
|
3127
|
+
SELECT array_agg(groups.content_digest ORDER BY groups.content_digest COLLATE "C", pool.ordinality),
|
|
3128
|
+
array_agg(pool.event_id ORDER BY groups.content_digest COLLATE "C", pool.ordinality),
|
|
3129
|
+
array_agg(pool.cacheable ORDER BY groups.content_digest COLLATE "C", pool.ordinality)
|
|
3130
|
+
FROM groups CROSS JOIN LATERAL
|
|
3131
|
+
${schema}.lookup_legacy_log_occurrence_pool($4,$5,$6,groups.content_digest,$7,groups.request_count)
|
|
3132
|
+
WITH ORDINALITY AS pool(event_id,cacheable,ordinality)
|
|
3133
|
+
$legacy_occurrence_pools$
|
|
3134
|
+
INTO occurrence_pool_digests, occurrence_pool_ids, occurrence_pool_cacheable
|
|
3135
|
+
USING item->'lines', item->'lineContexts', item->'lineIds', run_org, observation.run_id,
|
|
3136
|
+
((item->>'producerAttempt')::integer)::text, log_channel;
|
|
3137
|
+
occurrence_pool_heads := array_fill(NULL::integer, ARRAY[cardinality(occurrence_pool_digests)]);
|
|
3138
|
+
occurrence_pool_loaded := true;
|
|
3139
|
+
END IF;
|
|
3140
|
+
-- Binary search the flat digest groups; native array element
|
|
3141
|
+
-- assignments retain compact mutable heads without copying a
|
|
3142
|
+
-- growing JSON metadata map for every incoming line.
|
|
3143
|
+
occurrence_low := 1; occurrence_high := cardinality(occurrence_pool_digests);
|
|
3144
|
+
WHILE occurrence_low < occurrence_high LOOP
|
|
3145
|
+
occurrence_mid := (occurrence_low + occurrence_high) / 2;
|
|
3146
|
+
IF occurrence_pool_digests[occurrence_mid] COLLATE "C" < digest COLLATE "C" THEN
|
|
3147
|
+
occurrence_low := occurrence_mid + 1;
|
|
3148
|
+
ELSE occurrence_high := occurrence_mid; END IF;
|
|
3149
|
+
END LOOP;
|
|
3150
|
+
occurrence_group := occurrence_low;
|
|
3151
|
+
IF occurrence_pool_digests[occurrence_group] IS DISTINCT FROM digest THEN
|
|
3152
|
+
RAISE EXCEPTION 'Legacy log occurrence pool omitted an incoming digest';
|
|
3153
|
+
END IF;
|
|
3154
|
+
occurrence_head := coalesce(occurrence_pool_heads[occurrence_group], occurrence_group);
|
|
3155
|
+
matched_event_id := NULL; matched_doc := NULL;
|
|
3156
|
+
IF occurrence_pool_cacheable[occurrence_group]
|
|
3157
|
+
AND occurrence_pool_digests[occurrence_head] IS NOT DISTINCT FROM digest
|
|
3158
|
+
AND occurrence_pool_ids[occurrence_head] IS NOT NULL THEN
|
|
3159
|
+
SELECT event.event_id, event.search_doc INTO matched_event_id, matched_doc
|
|
3160
|
+
FROM ${schema}.lookup_legacy_log_identity(run_org, occurrence_pool_ids[occurrence_head]) AS event
|
|
3161
|
+
WHERE event.run_id = observation.run_id AND event.kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
3162
|
+
AND event.source_digest = digest AND event.search_doc->>'producerAttempt' = ((item->>'producerAttempt')::integer)::text
|
|
3163
|
+
AND NOT (event.search_doc ? 'entryId')
|
|
3164
|
+
AND event.search_doc @> jsonb_build_object('logContentDigest', digest)
|
|
3165
|
+
AND NOT (coalesce(event.search_doc->'logPositions', '{}'::jsonb) ? log_channel)
|
|
3166
|
+
AND (event.search_doc ? 'logPositions' OR log_channel <>
|
|
3167
|
+
CASE WHEN event.search_doc->>'source' = 'coordinator' THEN 'replay' ELSE 'worker' END);
|
|
3168
|
+
IF matched_event_id IS NULL THEN
|
|
3169
|
+
-- A concurrent TTL scrub may remove a null alias. Once
|
|
3170
|
+
-- the snapshot changes, scalar lookup sees the full tail.
|
|
3171
|
+
occurrence_pool_cacheable[occurrence_group] := false;
|
|
3172
|
+
END IF;
|
|
3173
|
+
END IF;
|
|
3174
|
+
IF NOT occurrence_pool_cacheable[occurrence_group] THEN
|
|
3175
|
+
SELECT event.event_id, event.search_doc INTO matched_event_id, matched_doc
|
|
3176
|
+
FROM ${schema}.lookup_legacy_log_occurrence(run_org, observation.run_id,
|
|
3177
|
+
((item->>'producerAttempt')::integer)::text, digest, log_channel) AS event;
|
|
3178
|
+
END IF;
|
|
2798
3179
|
IF matched_event_id IS NOT NULL THEN
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3180
|
+
matched_doc := matched_doc || jsonb_build_object('logContentDigest', digest, 'logPositions',
|
|
3181
|
+
coalesce(matched_doc->'logPositions', '{}'::jsonb) || jsonb_build_object(log_channel, log_position));
|
|
3182
|
+
SELECT updated.updated_tid INTO inserted_tid
|
|
3183
|
+
FROM ${schema}.update_legacy_log_alias(run_org, matched_event_id, matched_doc, observation.run_id) AS updated;
|
|
3184
|
+
IF occurrence_pool_cacheable[occurrence_group]
|
|
3185
|
+
AND (coalesce(matched_doc->'logPositions', '{}'::jsonb) ? log_channel) THEN
|
|
3186
|
+
occurrence_pool_heads[occurrence_group] := occurrence_head + 1;
|
|
3187
|
+
END IF;
|
|
2804
3188
|
-- Aliasing a fresh line moves its tuple within this transaction.
|
|
2805
3189
|
fresh_target_index := array_position(fresh_event_ids, matched_event_id);
|
|
2806
3190
|
IF fresh_target_index IS NOT NULL THEN
|