@sema-agent/server 7.146.0 → 7.147.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/MIGRATION.md +384 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +170 -66
- package/deploy/facts/lanes.json +7 -0
- package/deploy/sema-up/README.md +2 -2
- package/deploy/sema-up/chart/templates/_helpers.tpl +22 -0
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
- package/deploy/sema-up/chart/templates/server.yaml +5 -4
- package/deploy/sema-up/chart/values.yaml +1 -1
- package/deploy/sema-up/cluster-up.sh +2 -1
- package/deploy/sema-up/lib/flagshape.sh +4 -0
- package/deploy/sema-up/lib/lanes.json +2 -5
- package/deploy/sema-up/sema-up.sh +12 -9
- package/deploy/sema-up/stack/compose.yaml +5 -4
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -3
- package/dist/approval-card.d.ts +4 -4
- package/dist/approval.d.ts +3 -3
- package/dist/audit.js +2 -2
- package/dist/bench/s1/live-deps.js +3 -1
- package/dist/boot/crash-last.js +2 -1
- package/dist/boot/device-lane.js +5 -5
- package/dist/boot/engine-lease.d.ts +12 -11
- package/dist/boot/execution-env.d.ts +2 -1
- package/dist/boot/execution-env.js +45 -33
- package/dist/boot/execution-lane.d.ts +37 -9
- package/dist/boot/execution-lane.js +74 -20
- package/dist/boot/exit-boundary.d.ts +1 -1
- package/dist/boot/exit-last.js +2 -1
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/leader.js +1 -1
- package/dist/boot/memory-boundary.d.ts +11 -11
- package/dist/boot/memory-boundary.js +3 -3
- package/dist/boot/memory-consolidation.d.ts +13 -24
- package/dist/boot/memory-consolidation.js +0 -13
- package/dist/boot/org-memory.js +3 -2
- package/dist/boot/parked-revive-gate.d.ts +1 -1
- package/dist/boot/parked-revive-gate.js +1 -1
- package/dist/boot/reapers.js +1 -1
- package/dist/boot/resolve-spec.js +91 -111
- package/dist/boot/retention-lane.d.ts +4 -42
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +8 -2
- package/dist/boot/stage-01-config.d.ts +1 -1
- package/dist/boot/stage-01-config.js +6 -2
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -1
- package/dist/boot/stage-02-web-admin-pull.js +10 -8
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +2 -2
- package/dist/boot/stage-05-execution-env.js +3 -3
- package/dist/boot/stage-06-runners.d.ts +3 -3
- package/dist/boot/stage-06-runners.js +1 -3
- package/dist/boot/stage-07-capability-layer.d.ts +3 -3
- package/dist/boot/stage-07-capability-layer.js +4 -9
- package/dist/boot/stage-08-reapers.d.ts +3 -3
- package/dist/boot/stage-09-leader.d.ts +4 -3
- package/dist/boot/stage-10-http-server.d.ts +4 -3
- package/dist/boot/stage-10-http-server.js +2 -1
- package/dist/boot/stores.d.ts +9 -0
- package/dist/boot/stores.js +18 -7
- package/dist/boot/web-admin.js +3 -3
- package/dist/capabilities/center-plugins.d.ts +2 -0
- package/dist/capabilities/center-plugins.js +6 -2
- package/dist/capabilities/composite-members.d.ts +1 -0
- package/dist/capabilities/composite-members.js +1 -0
- package/dist/capabilities/execution-lane.d.ts +7 -7
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +1 -1
- package/dist/capabilities/scenarios.d.ts +32 -18
- package/dist/capabilities/scenarios.js +13 -9
- package/dist/capabilities/settings-contract.d.ts +29 -0
- package/dist/capabilities/settings-contract.js +14 -0
- package/dist/capabilities/skills.d.ts +5 -5
- package/dist/capability-facts.d.ts +38 -0
- package/dist/capability-facts.js +34 -1
- package/dist/center-credential-renewer.js +3 -2
- package/dist/config-catalog.js +6 -5
- package/dist/config-invariants.d.ts +18 -3
- package/dist/config-invariants.js +36 -19
- package/dist/config-lkg.d.ts +1 -1
- package/dist/config-lkg.js +5 -6
- package/dist/config-provider.js +2 -0
- package/dist/config-types.d.ts +190 -186
- package/dist/config.d.ts +68 -5
- package/dist/config.js +80 -54
- package/dist/degenerate-instrument.js +1 -1
- package/dist/deploy-facts.js +3 -2
- package/dist/deployment-shape.d.ts +21 -12
- package/dist/deployment-shape.js +24 -6
- package/dist/env-facts.d.ts +7 -5
- package/dist/env-facts.js +10 -6
- package/dist/execution-config-root.d.ts +5 -5
- package/dist/execution-config-root.js +5 -5
- package/dist/execution-env-purpose.d.ts +14 -0
- package/dist/execution-env-purpose.js +29 -0
- package/dist/execution-lane-caps.d.ts +49 -86
- package/dist/execution-lane-caps.js +52 -62
- package/dist/execution-placement.d.ts +18 -2
- package/dist/execution-placement.js +19 -0
- package/dist/file-history-disclosure.d.ts +2 -2
- package/dist/fleet/drain-entry.d.ts +17 -10
- package/dist/fleet/drain-entry.js +1 -1
- package/dist/fleet/serving-lease.js +3 -4
- package/dist/history-anchor.d.ts +22 -0
- package/dist/history-anchor.js +14 -0
- package/dist/hooks/command-spawn.d.ts +1 -4
- package/dist/hooks/command-spawn.js +0 -11
- package/dist/hooks/hook-runner.d.ts +52 -8
- package/dist/hooks/hook-runner.js +160 -36
- package/dist/http/approval-sweeps.d.ts +2 -5
- package/dist/http/approval-sweeps.js +3 -2
- package/dist/http/checkpoint-ctx.d.ts +17 -0
- package/dist/http/checkpoint-ctx.js +6 -0
- package/dist/http/claim-latency.d.ts +10 -0
- package/dist/http/claim-latency.js +12 -0
- package/dist/http/dispatch.js +1 -1
- package/dist/http/durable-run-leg.js +2 -1
- package/dist/http/execution-context.d.ts +3 -1
- package/dist/http/execution-context.js +4 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.js +3 -0
- package/dist/http/memory-store-refusal-reply.d.ts +3 -3
- package/dist/http/memory-store-refusal-reply.js +3 -0
- package/dist/http/owner-access.d.ts +11 -0
- package/dist/http/owner-access.js +7 -4
- package/dist/http/principal-gate.d.ts +3 -14
- package/dist/http/principal-gate.js +0 -13
- package/dist/http/request-guards.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +7 -10
- package/dist/http/resume-legs.js +79 -50
- package/dist/http/rewind-files-reply.d.ts +34 -0
- package/dist/http/rewind-files-reply.js +36 -0
- package/dist/http/route-ctx.d.ts +32 -16
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/approvals-assistant.js +5 -25
- package/dist/http/routes/capabilities.js +8 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -1
- package/dist/http/routes/projects.d.ts +70 -0
- package/dist/http/routes/projects.js +86 -0
- package/dist/http/routes/rules.js +30 -2
- package/dist/http/routes/runs.js +8 -8
- package/dist/http/routes/session-sync.js +27 -10
- package/dist/http/routes/sessions.d.ts +7 -1
- package/dist/http/routes/sessions.js +104 -2
- package/dist/http/routes/tasks.js +9 -3
- package/dist/http/server.d.ts +24 -10
- package/dist/http/server.js +17 -6
- package/dist/http/stored-body-replay.d.ts +5 -3
- package/dist/http/stored-body-replay.js +10 -1
- package/dist/http/wire-types.d.ts +19 -10
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/instruction-source-notice.d.ts +1 -1
- package/dist/memory-embedder-reembed.d.ts +38 -0
- package/dist/memory-embedder-reembed.js +20 -0
- package/dist/memory-incident-sink.d.ts +0 -28
- package/dist/memory-incident-sink.js +5 -0
- package/dist/memory-scope.d.ts +2 -2
- package/dist/memory-scope.js +1 -1
- package/dist/memory-store-refusal.d.ts +17 -4
- package/dist/memory-store-refusal.js +1 -1
- package/dist/memory-sync-client.d.ts +2 -0
- package/dist/memory-sync-client.js +13 -11
- package/dist/memory-sync.js +1 -1
- package/dist/model-compat.d.ts +35 -21
- package/dist/model-compat.js +49 -21
- package/dist/model-entry-refusal.d.ts +11 -1
- package/dist/model-entry-refusal.js +7 -0
- package/dist/namespaced-rule-name.d.ts +18 -1
- package/dist/namespaced-rule-name.js +12 -0
- package/dist/observability/fail-open.d.ts +17 -9
- package/dist/observability/fail-open.js +17 -9
- package/dist/observability/metrics.d.ts +2 -0
- package/dist/observability/metrics.js +2 -0
- package/dist/observability/secret-env-scrub.d.ts +30 -4
- package/dist/observability/secret-env-scrub.js +15 -3
- package/dist/orchestration/workflow-agent-session-index.d.ts +7 -12
- package/dist/orchestration/workflow-agent-session-index.js +1 -6
- package/dist/orchestration/workflow-completion-inbox.d.ts +26 -6
- package/dist/orchestration/workflow-completion-inbox.js +63 -45
- package/dist/org-memory-admission.d.ts +5 -2
- package/dist/org-memory-admission.js +25 -10
- package/dist/parked-decide.d.ts +33 -26
- package/dist/parked-decide.js +36 -44
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +37 -4
- package/dist/plugins/approval-ask-store-memory.d.ts +5 -3
- package/dist/plugins/approval-ask-store-memory.js +11 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +3 -0
- package/dist/plugins/approval-ask-store-sql.js +3 -1
- package/dist/plugins/blob-backend.d.ts +38 -195
- package/dist/plugins/blob-backend.js +33 -229
- package/dist/plugins/caching-session-store.d.ts +9 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +1 -1
- package/dist/plugins/checkpoint-index-columns.js +3 -2
- package/dist/plugins/checkpoint-store-face.d.ts +1 -1
- package/dist/plugins/device-store-sql.d.ts +2 -2
- package/dist/plugins/device-store-sql.js +5 -10
- package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
- package/dist/plugins/execution-lane-rename-m40.js +10 -0
- package/dist/plugins/execution-placement-sql.d.ts +63 -88
- package/dist/plugins/execution-placement-sql.js +94 -54
- package/dist/plugins/file-run-store.d.ts +26 -12
- package/dist/plugins/file-run-store.js +63 -63
- package/dist/plugins/imported-layer-root-retirement.d.ts +17 -8
- package/dist/plugins/imported-layer-root-retirement.js +4 -8
- package/dist/plugins/inbox-payload-column.d.ts +14 -0
- package/dist/plugins/inbox-payload-column.js +13 -0
- package/dist/plugins/local-checkpoint-store.d.ts +5 -0
- package/dist/plugins/local-checkpoint-store.js +11 -7
- package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
- package/dist/plugins/local-data-dir-modes-m39.js +182 -0
- package/dist/plugins/local-engine-high-water.d.ts +11 -0
- package/dist/plugins/local-engine-high-water.js +59 -0
- package/dist/plugins/local-session-store.d.ts +91 -25
- package/dist/plugins/local-session-store.js +124 -45
- package/dist/plugins/local-task-attachment-store.d.ts +2 -0
- package/dist/plugins/local-task-attachment-store.js +10 -11
- package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
- package/dist/plugins/memory-embedder-fingerprint.js +52 -12
- package/dist/plugins/memory-embedder.d.ts +1 -1
- package/dist/plugins/memory-embedder.js +2 -2
- package/dist/plugins/memory-engine-pg.d.ts +4 -3
- package/dist/plugins/memory-engine-pg.js +4 -4
- package/dist/plugins/memory-engine-sql-apply.d.ts +13 -4
- package/dist/plugins/memory-engine-sql-apply.js +1 -1
- package/dist/plugins/memory-engine-tidb.d.ts +8 -5
- package/dist/plugins/memory-engine-tidb.js +7 -8
- package/dist/plugins/one-time-migrations.d.ts +145 -35
- package/dist/plugins/one-time-migrations.js +272 -120
- package/dist/plugins/owner-only-file-mode.d.ts +29 -0
- package/dist/plugins/owner-only-file-mode.js +141 -0
- package/dist/plugins/permission-rule-store-file.d.ts +8 -8
- package/dist/plugins/permission-rule-store-file.js +14 -2
- package/dist/plugins/pg-pool.d.ts +2 -1
- package/dist/plugins/pg-pool.js +11 -4
- package/dist/plugins/release-version.d.ts +20 -0
- package/dist/plugins/release-version.js +28 -0
- package/dist/plugins/remote-env-adb.d.ts +20 -4
- package/dist/plugins/remote-env-adb.js +39 -11
- package/dist/plugins/remote-env-e2b.d.ts +12 -3
- package/dist/plugins/remote-env-e2b.js +6 -4
- package/dist/plugins/remote-env-host.d.ts +9 -1
- package/dist/plugins/remote-env-host.js +6 -5
- package/dist/plugins/remote-env-k8s.d.ts +5 -2
- package/dist/plugins/remote-env-k8s.js +15 -4
- package/dist/plugins/remote-env-local-docker.d.ts +4 -1
- package/dist/plugins/remote-env-local-docker.js +3 -3
- package/dist/plugins/remote-env-ssh.d.ts +8 -2
- package/dist/plugins/remote-env-ssh.js +26 -24
- package/dist/plugins/remote-shell.d.ts +59 -30
- package/dist/plugins/remote-shell.js +175 -62
- package/dist/plugins/retention-declaration.d.ts +37 -0
- package/dist/plugins/retention-declaration.js +9 -0
- package/dist/plugins/retention-deployment.d.ts +126 -0
- package/dist/plugins/retention-deployment.js +88 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
- package/dist/plugins/retention-lane-store-sql.js +103 -1
- package/dist/plugins/retention-sql.d.ts +29 -0
- package/dist/plugins/retention-sql.js +8 -0
- package/dist/plugins/schema-consistency.d.ts +0 -6
- package/dist/plugins/schema-consistency.js +1 -2
- package/dist/plugins/schema-ensure-legs.d.ts +1 -1
- package/dist/plugins/schema-ensure-legs.js +11 -1
- package/dist/plugins/session-ext-table.d.ts +74 -0
- package/dist/plugins/session-ext-table.js +121 -0
- package/dist/plugins/session-fork.d.ts +1 -1
- package/dist/plugins/session-row-sql.d.ts +8 -7
- package/dist/plugins/session-row-sql.js +15 -7
- package/dist/plugins/session-store-sql.d.ts +131 -0
- package/dist/plugins/session-store-sql.js +298 -0
- package/dist/plugins/session-workspace-cell.d.ts +2 -2
- package/dist/plugins/session-workspace-cell.js +2 -2
- package/dist/plugins/shared-memory-store-sql.d.ts +10 -0
- package/dist/plugins/shared-memory-store-sql.js +13 -13
- package/dist/plugins/snapshot-bucket-presence.js +1 -1
- package/dist/plugins/sql-driver.d.ts +23 -7
- package/dist/plugins/sql-driver.js +41 -8
- package/dist/plugins/sql-errors.d.ts +5 -2
- package/dist/plugins/sql-errors.js +4 -0
- package/dist/plugins/store-backend.d.ts +35 -8
- package/dist/plugins/store-backend.js +184 -62
- package/dist/plugins/store-contracts.d.ts +9 -2
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/task-attachment-store.d.ts +6 -8
- package/dist/plugins/task-attachment-store.js +15 -10
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/text-column-capacity.d.ts +21 -0
- package/dist/plugins/text-column-capacity.js +5 -0
- package/dist/plugins/tidb-pool.d.ts +3 -2
- package/dist/plugins/tidb-pool.js +19 -31
- package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
- package/dist/read-face-posture.d.ts +6 -6
- package/dist/read-face-posture.js +2 -2
- package/dist/request-value-closure.d.ts +5 -5
- package/dist/request-value-closure.js +1 -1
- package/dist/rules-consent.d.ts +41 -13
- package/dist/rules-consent.js +101 -53
- package/dist/run-local.js +17 -13
- package/dist/runs.d.ts +48 -30
- package/dist/runs.js +26 -16
- package/dist/runtime-caps-resolver.d.ts +15 -8
- package/dist/runtime-caps-resolver.js +14 -10
- package/dist/sealed-key-layout.d.ts +2 -3
- package/dist/sealed-key-layout.js +0 -1
- package/dist/sealed-key.js +7 -5
- package/dist/security.d.ts +5 -3
- package/dist/sema-config-dir.js +2 -2
- package/dist/server-secret-env.d.ts +2 -0
- package/dist/service-version.d.ts +2 -1
- package/dist/service-version.js +2 -2
- package/dist/session-error-wire.d.ts +1 -1
- package/dist/session-incarnation.d.ts +8 -5
- package/dist/session-resident-background.d.ts +85 -32
- package/dist/session-resident-background.js +75 -7
- package/dist/session-row.d.ts +1 -1
- package/dist/session-sync-kernel.d.ts +1 -1
- package/dist/session-workspace.d.ts +11 -2
- package/dist/session-workspace.js +5 -0
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/store-posture.d.ts +2 -1
- package/dist/stored-request-hooks-m20.d.ts +3 -2
- package/dist/stored-request-hooks-m20.js +19 -14
- package/dist/stores-sql/blob-index-sql.d.ts +148 -0
- package/dist/stores-sql/blob-index-sql.js +154 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
- package/dist/stores-sql/checkpoint-store-sql.js +11 -27
- package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
- package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
- package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +23 -76
- package/dist/{plugins → stores-sql}/pg-session-storage.js +80 -209
- package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +123 -217
- package/dist/{plugins → stores-sql}/retention-store-sql.js +66 -190
- package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
- package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
- package/dist/stores-sql/session-policy-store-sql.d.ts +1 -1
- package/dist/stores-sql/session-write-hooks.d.ts +59 -0
- package/dist/stores-sql/session-write-hooks.js +2 -0
- package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +10 -11
- package/dist/{plugins → stores-sql}/tidb-session-storage.js +10 -21
- package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +32 -122
- package/dist/{plugins → stores-sql}/tidb-session-store.js +71 -171
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +1 -1
- package/dist/stores-sql/windowed-session-storage.d.ts +56 -0
- package/dist/stores-sql/windowed-session-storage.js +61 -0
- package/dist/task-a2a.d.ts +7 -1
- package/dist/task-a2a.js +15 -14
- package/dist/task-cwd.d.ts +11 -3
- package/dist/task-cwd.js +17 -1
- package/dist/task-mcp.d.ts +10 -2
- package/dist/task-mcp.js +13 -16
- package/dist/task-settings.d.ts +9 -4
- package/dist/task-settings.js +17 -6
- package/dist/tool-approval.d.ts +21 -8
- package/dist/tool-approval.js +10 -6
- package/dist/trace/core-keyset-guard.d.ts +9 -3
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +23 -1
- package/dist/trace/exit-seat.js +3 -0
- package/dist/trace/project.d.ts +33 -16
- package/dist/trace/project.js +12 -9
- package/dist/trace/redact.d.ts +1 -1
- package/dist/trace/redact.js +61 -73
- package/dist/trace/self-minted-wire.d.ts +263 -10
- package/dist/trace/self-minted-wire.js +90 -2
- package/dist/trace/sema-provenance.d.ts +45 -41
- package/dist/trace/sema-provenance.js +81 -10
- package/dist/trace/task-notification-facets.d.ts +70 -2
- package/dist/trace/task-notification-facets.js +71 -1
- package/dist/trace/wire-projection-faces.d.ts +38 -2
- package/dist/trace/wire-projection-faces.js +26 -1
- package/dist/unread-request-members.d.ts +66 -0
- package/dist/unread-request-members.js +41 -0
- package/dist/user-input-ledger.d.ts +2 -2
- package/dist/web-admin-client/apply-effective.js +22 -26
- package/dist/web-admin-client/candidate-gate.d.ts +35 -3
- package/dist/web-admin-client/candidate-gate.js +53 -5
- package/dist/web-admin-client/center-request.d.ts +4 -1
- package/dist/web-admin-client/center-request.js +2 -1
- package/dist/web-admin-client/effective-keys.js +0 -1
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/http-client.d.ts +1 -0
- package/dist/web-admin-client/http-client.js +17 -9
- package/dist/web-admin-client/restart-signal.js +5 -2
- package/dist/web-admin-client/skills-mcp.d.ts +20 -6
- package/dist/web-admin-client/skills-mcp.js +26 -21
- package/dist/web-admin-client/types.d.ts +34 -49
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +2 -2
- package/package.json +13 -12
- package/scripts/drain-check-local.mjs +2 -28
- package/scripts/drain-check.mysql.sql +2 -18
- package/scripts/drain-check.pg.sql +2 -18
- package/wire-changes/server@7.147.0.json +813 -0
|
@@ -1,57 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { presignS3Url, presignS3ListUrl } from "./s3-presign.js";
|
|
3
3
|
import { isNoSuchBucketAnswer } from "./s3-answer.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return Math.floor(packetWallStatementBytes(maxPacketBytes) / SQL_TEXT_PROTOCOL_BLOB_INFLATION);
|
|
10
|
-
}
|
|
11
|
-
export function sqlBlobDefaultCapBytes(walls) {
|
|
12
|
-
return sqlBlobDefaultCapOf(walls)?.capBytes;
|
|
13
|
-
}
|
|
14
|
-
export function sqlBlobDefaultCapOf(walls) {
|
|
15
|
-
const legs = [];
|
|
16
|
-
if (walls.maxRowBytes !== null)
|
|
17
|
-
legs.push({ capBytes: rowWallPayloadBytes(walls.maxRowBytes, "blob"), source: walls.sources.maxRowBytes });
|
|
18
|
-
if (walls.maxPacketBytes !== null)
|
|
19
|
-
legs.push({ capBytes: packetWallBlobCap(walls.maxPacketBytes), source: walls.sources.maxPacketBytes });
|
|
20
|
-
return legs.reduce((best, leg) => (best === undefined || leg.capBytes < best.capBytes ? leg : best), undefined);
|
|
21
|
-
}
|
|
22
|
-
export function sqlBlobCapOf(explicitCapBytes, connection) {
|
|
23
|
-
return explicitCapBytes !== undefined ? { capBytes: explicitCapBytes, source: "operator" } : sqlBlobDefaultCapOf(sqlWallsOf(connection));
|
|
24
|
-
}
|
|
25
|
-
export function sqlBlobCapBytes(explicitCapBytes, connection) {
|
|
26
|
-
return sqlBlobCapOf(explicitCapBytes, connection)?.capBytes;
|
|
27
|
-
}
|
|
28
|
-
export function capBoundByPacketWall(cap, walls) {
|
|
29
|
-
return cap.source !== "operator" && walls.maxPacketBytes !== null && packetWallBlobCap(walls.maxPacketBytes) === cap.capBytes;
|
|
30
|
-
}
|
|
31
|
-
export function sqlBlobCapRefusalText(byteLen, cap) {
|
|
32
|
-
const objectStorage = "configure MinIO object storage (MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY) for large snapshot blobs";
|
|
33
|
-
const head = `blob of ${byteLen} bytes exceeds this deployment's SQL snapshot-blob cap (${cap.capBytes} bytes — `;
|
|
34
|
-
switch (cap.source) {
|
|
35
|
-
case "operator":
|
|
36
|
-
return `${head}set by the operator's SNAPSHOT_BLOB_SQL_MAX_BYTES) — ${objectStorage}, or raise SNAPSHOT_BLOB_SQL_MAX_BYTES if the database allows larger writes`;
|
|
37
|
-
case "reported":
|
|
38
|
-
return `${head}the smaller of the database's single-row limit (TiDB txn-entry-size-limit, 6MiB by default) and about half its max_allowed_packet (the text protocol doubles a blob inside the statement)) — ${objectStorage}, or raise SNAPSHOT_BLOB_SQL_MAX_BYTES if your deployment lifted those limits`;
|
|
39
|
-
case "assumed":
|
|
40
|
-
return `${head}the database's limits were not read — engine facts not read yet, or a limit could not be read — so the smallest documented default wall applies) — retry shortly, ${objectStorage}, or set SNAPSHOT_BLOB_SQL_MAX_BYTES to the limit your deployment actually has`;
|
|
41
|
-
default: {
|
|
42
|
-
const unhandled = cap.source;
|
|
43
|
-
throw new Error(`blob cap refusal without a sentence: ${String(unhandled)}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
export class BlobTooLargeError extends Error {
|
|
48
|
-
cap;
|
|
49
|
-
code = "blob_too_large_for_sql";
|
|
50
|
-
constructor(byteLen, cap) {
|
|
51
|
-
super(sqlBlobCapRefusalText(byteLen, cap));
|
|
52
|
-
this.cap = cap;
|
|
53
|
-
this.name = "BlobTooLargeError";
|
|
54
|
-
}
|
|
4
|
+
export async function readAtAddress(port, hash) {
|
|
5
|
+
const bytes = await port.get(hash);
|
|
6
|
+
if (bytes === undefined)
|
|
7
|
+
return undefined;
|
|
8
|
+
return createHash("sha256").update(bytes).digest("hex") === hash ? bytes : undefined;
|
|
55
9
|
}
|
|
56
10
|
const MINIO_OP_CONCURRENCY = 16;
|
|
57
11
|
async function mapBounded(items, limit, fn) {
|
|
@@ -64,143 +18,24 @@ async function mapBounded(items, limit, fn) {
|
|
|
64
18
|
});
|
|
65
19
|
await Promise.all(workers);
|
|
66
20
|
}
|
|
67
|
-
export class SqlBlobBackend {
|
|
68
|
-
dialect;
|
|
69
|
-
pool;
|
|
70
|
-
explicitCapBytes;
|
|
71
|
-
table;
|
|
72
|
-
db;
|
|
73
|
-
log;
|
|
74
|
-
constructor(dialect, pool, maxBytes, table = "snapshot_blob", log) {
|
|
75
|
-
this.dialect = dialect;
|
|
76
|
-
this.pool = pool;
|
|
77
|
-
this.explicitCapBytes = maxBytes;
|
|
78
|
-
this.table = table;
|
|
79
|
-
this.db = dialect === "mysql" ? mysqlDriver(pool) : pgDriver(pool);
|
|
80
|
-
this.log = log ?? createLogger();
|
|
81
|
-
}
|
|
82
|
-
async putBlob(hash, bytes) {
|
|
83
|
-
const judged = await connectJudged(this.db, (facts) => {
|
|
84
|
-
const connection = { dialect: this.dialect, facts };
|
|
85
|
-
const cap = sqlBlobCapOf(this.explicitCapBytes, connection);
|
|
86
|
-
if (cap === undefined || bytes.byteLength <= cap.capBytes)
|
|
87
|
-
return undefined;
|
|
88
|
-
return { cap, packetBound: capBoundByPacketWall(cap, sqlWallsOf(connection)) };
|
|
89
|
-
}, (refusal) => refusal.packetBound, this.log);
|
|
90
|
-
if (judged.refusal !== undefined)
|
|
91
|
-
throw new BlobTooLargeError(bytes.byteLength, judged.refusal.cap);
|
|
92
|
-
try {
|
|
93
|
-
await judged.conn.query(this.dialect === "mysql"
|
|
94
|
-
? `INSERT INTO ${this.table} (blob_hash, byte_len, bytes, created_at) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE created_at = VALUES(created_at)`
|
|
95
|
-
: `INSERT INTO ${this.table} (blob_hash, byte_len, bytes, created_at) VALUES ($1,$2,$3,$4) ON CONFLICT (blob_hash) DO UPDATE SET created_at = EXCLUDED.created_at`, [hash, bytes.byteLength, Buffer.from(bytes), new Date()]);
|
|
96
|
-
}
|
|
97
|
-
finally {
|
|
98
|
-
judged.conn.release();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
async getBlob(hash) {
|
|
102
|
-
if (this.dialect === "mysql") {
|
|
103
|
-
const [rows] = await this.pool.query(`SELECT bytes FROM ${this.table} WHERE blob_hash = ?`, [hash]);
|
|
104
|
-
return rows[0]?.bytes != null ? new Uint8Array(rows[0].bytes) : undefined;
|
|
105
|
-
}
|
|
106
|
-
const b = await this.pool.query(`SELECT bytes FROM ${this.table} WHERE blob_hash = $1`, [hash]);
|
|
107
|
-
return b.rows[0]?.bytes != null ? new Uint8Array(b.rows[0].bytes) : undefined;
|
|
108
|
-
}
|
|
109
|
-
async hasBlobs(hashes) {
|
|
110
|
-
return sqlHasBlobs(this.dialect, this.pool, hashes, this.table);
|
|
111
|
-
}
|
|
112
|
-
async deleteBlobs(hashes) {
|
|
113
|
-
const deleted = await sqlDeleteIndexRowsPastGrace(this.dialect, this.pool, hashes, this.table);
|
|
114
|
-
return deleted.length;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
async function sqlHasBlobs(dialect, pool, hashes, table = "snapshot_blob") {
|
|
118
|
-
if (hashes.length === 0)
|
|
119
|
-
return new Set();
|
|
120
|
-
const distinct = [...new Set(hashes)];
|
|
121
|
-
if (dialect === "mysql") {
|
|
122
|
-
const ph = distinct.map(() => "?").join(",");
|
|
123
|
-
const [rows] = await pool.query(`SELECT blob_hash FROM ${table} WHERE blob_hash IN (${ph})`, distinct);
|
|
124
|
-
return new Set(rows.map((r) => String(r.blob_hash)));
|
|
125
|
-
}
|
|
126
|
-
const ph = distinct.map((_, i) => `$${i + 1}`).join(",");
|
|
127
|
-
const r = await pool.query(`SELECT blob_hash FROM ${table} WHERE blob_hash IN (${ph})`, distinct);
|
|
128
|
-
return new Set(r.rows.map((row) => row.blob_hash));
|
|
129
|
-
}
|
|
130
|
-
export async function sqlBlobSizes(dialect, pool, hashes) {
|
|
131
|
-
if (hashes.length === 0)
|
|
132
|
-
return new Map();
|
|
133
|
-
const distinct = [...new Set(hashes)];
|
|
134
|
-
const CHUNK = 1000;
|
|
135
|
-
const out = new Map();
|
|
136
|
-
for (let i = 0; i < distinct.length; i += CHUNK) {
|
|
137
|
-
const part = distinct.slice(i, i + CHUNK);
|
|
138
|
-
if (dialect === "mysql") {
|
|
139
|
-
const ph = part.map(() => "?").join(",");
|
|
140
|
-
const [rows] = await pool.query(`SELECT blob_hash, byte_len FROM snapshot_blob WHERE blob_hash IN (${ph})`, part);
|
|
141
|
-
for (const r of rows)
|
|
142
|
-
out.set(String(r.blob_hash), Number(r.byte_len));
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
const ph = part.map((_, j) => `$${j + 1}`).join(",");
|
|
146
|
-
const r = await pool.query(`SELECT blob_hash, byte_len FROM snapshot_blob WHERE blob_hash IN (${ph})`, part);
|
|
147
|
-
for (const row of r.rows)
|
|
148
|
-
out.set(row.blob_hash, Number(row.byte_len));
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return out;
|
|
152
|
-
}
|
|
153
|
-
async function sqlDeleteIndexRowsPastGrace(dialect, pool, hashes, table = "snapshot_blob") {
|
|
154
|
-
if (hashes.length === 0)
|
|
155
|
-
return [];
|
|
156
|
-
const distinct = [...new Set(hashes)];
|
|
157
|
-
const cutoff = new Date(Date.now() - BLOB_GC_GRACE_MS);
|
|
158
|
-
if (dialect === "mysql") {
|
|
159
|
-
const ph = distinct.map(() => "?").join(",");
|
|
160
|
-
const grace = await pool
|
|
161
|
-
.query(`SELECT blob_hash FROM ${table} WHERE created_at < ? AND blob_hash IN (${ph})`, [cutoff, ...distinct])
|
|
162
|
-
.then(([rows]) => rows.map((r) => String(r.blob_hash)))
|
|
163
|
-
.catch(() => []);
|
|
164
|
-
if (grace.length === 0)
|
|
165
|
-
return [];
|
|
166
|
-
const gph = grace.map(() => "?").join(",");
|
|
167
|
-
await pool
|
|
168
|
-
.query(`DELETE FROM ${table} WHERE created_at < ? AND blob_hash IN (${gph})`, [cutoff, ...grace])
|
|
169
|
-
.catch(() => undefined);
|
|
170
|
-
return grace;
|
|
171
|
-
}
|
|
172
|
-
const ph = distinct.map((_, i) => `$${i + 2}`).join(",");
|
|
173
|
-
const r = await pool
|
|
174
|
-
.query(`DELETE FROM ${table} WHERE created_at < $1 AND blob_hash IN (${ph}) RETURNING blob_hash`, [cutoff, ...distinct])
|
|
175
|
-
.catch(() => undefined);
|
|
176
|
-
return (r?.rows ?? []).map((row) => row.blob_hash);
|
|
177
|
-
}
|
|
178
21
|
export const OBJECT_STORE_IO_TIMEOUT_MS = 120_000;
|
|
179
22
|
export class MinioBlobBackend {
|
|
180
23
|
cfg;
|
|
181
24
|
keyPrefix;
|
|
182
25
|
ttl;
|
|
183
|
-
|
|
184
|
-
indexDialect;
|
|
185
|
-
indexTable;
|
|
186
|
-
constructor(cfg, index) {
|
|
26
|
+
constructor(cfg) {
|
|
187
27
|
this.cfg = cfg;
|
|
188
28
|
this.keyPrefix = cfg.keyPrefix ?? "blobs/";
|
|
189
29
|
this.ttl = cfg.presignTtlSec ?? 3600;
|
|
190
|
-
this.indexTable = index?.table ?? "snapshot_blob";
|
|
191
|
-
if (index) {
|
|
192
|
-
this.indexDialect = index.dialect;
|
|
193
|
-
this.indexPool = index.pool;
|
|
194
|
-
}
|
|
195
30
|
}
|
|
196
|
-
objectKey(
|
|
197
|
-
return `${this.keyPrefix}${
|
|
31
|
+
objectKey(key) {
|
|
32
|
+
return `${this.keyPrefix}${key}`;
|
|
198
33
|
}
|
|
199
|
-
presign(
|
|
34
|
+
presign(key, method) {
|
|
200
35
|
return presignS3Url({
|
|
201
36
|
endpoint: this.cfg.endpoint,
|
|
202
37
|
bucket: this.cfg.bucket,
|
|
203
|
-
key: this.objectKey(
|
|
38
|
+
key: this.objectKey(key),
|
|
204
39
|
method: method,
|
|
205
40
|
accessKey: this.cfg.accessKey,
|
|
206
41
|
secretKey: this.cfg.secretKey,
|
|
@@ -208,57 +43,50 @@ export class MinioBlobBackend {
|
|
|
208
43
|
expiresSec: this.ttl,
|
|
209
44
|
});
|
|
210
45
|
}
|
|
211
|
-
async
|
|
212
|
-
const url = this.presign(
|
|
46
|
+
async put(key, bytes) {
|
|
47
|
+
const url = this.presign(key, "PUT");
|
|
213
48
|
const res = await (this.cfg.fetchImpl ?? fetch)(url, { method: "PUT", body: bytes, signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
|
|
214
49
|
if (!res.ok) {
|
|
215
50
|
const detail = await res.text().catch(() => "");
|
|
216
|
-
throw new Error(`MinioBlobBackend.
|
|
217
|
-
}
|
|
218
|
-
if (this.indexPool && this.indexDialect) {
|
|
219
|
-
if (this.indexDialect === "mysql") {
|
|
220
|
-
await this.indexPool.query(`INSERT INTO ${this.indexTable} (blob_hash, byte_len, bytes, created_at) VALUES (?,?,NULL,?) ON DUPLICATE KEY UPDATE created_at = VALUES(created_at)`, [hash, bytes.byteLength, new Date()]);
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
await this.indexPool.query(`INSERT INTO ${this.indexTable} (blob_hash, byte_len, bytes, created_at) VALUES ($1,$2,NULL,$3) ON CONFLICT (blob_hash) DO UPDATE SET created_at = EXCLUDED.created_at`, [hash, bytes.byteLength, new Date()]);
|
|
224
|
-
}
|
|
51
|
+
throw new Error(`MinioBlobBackend.put ${key}: HTTP ${res.status} ${detail.slice(0, 200)}`);
|
|
225
52
|
}
|
|
226
53
|
}
|
|
227
|
-
async
|
|
228
|
-
const url = this.presign(
|
|
54
|
+
async get(key) {
|
|
55
|
+
const url = this.presign(key, "GET");
|
|
229
56
|
let res;
|
|
230
57
|
try {
|
|
231
58
|
res = await (this.cfg.fetchImpl ?? fetch)(url, { method: "GET", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
|
|
232
59
|
}
|
|
233
60
|
catch (err) {
|
|
234
|
-
throw new Error(`MinioBlobBackend.
|
|
61
|
+
throw new Error(`MinioBlobBackend.get ${key}: transient fetch failure: ${err.message}`);
|
|
235
62
|
}
|
|
236
63
|
if (res.status === 404)
|
|
237
64
|
return undefined;
|
|
238
65
|
if (!res.ok) {
|
|
239
66
|
const detail = await res.text().catch(() => "");
|
|
240
|
-
throw new Error(`MinioBlobBackend.
|
|
67
|
+
throw new Error(`MinioBlobBackend.get ${key}: transient HTTP ${res.status} ${detail.slice(0, 200)}`);
|
|
241
68
|
}
|
|
242
|
-
|
|
243
|
-
if (createHash("sha256").update(buf).digest("hex") !== hash)
|
|
244
|
-
return undefined;
|
|
245
|
-
return buf;
|
|
69
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
246
70
|
}
|
|
247
|
-
async
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
await mapBounded(distinct, MINIO_OP_CONCURRENCY, async (hash) => {
|
|
71
|
+
async delete(keys) {
|
|
72
|
+
const distinct = [...new Set(keys)];
|
|
73
|
+
let failed = 0;
|
|
74
|
+
let firstFailure;
|
|
75
|
+
await mapBounded(distinct, MINIO_OP_CONCURRENCY, async (key) => {
|
|
253
76
|
try {
|
|
254
|
-
const res = await (this.cfg.fetchImpl ?? fetch)(this.presign(
|
|
255
|
-
if (res.ok)
|
|
256
|
-
|
|
77
|
+
const res = await (this.cfg.fetchImpl ?? fetch)(this.presign(key, "DELETE"), { method: "DELETE", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
|
|
78
|
+
if (res.ok || res.status === 404)
|
|
79
|
+
return;
|
|
80
|
+
failed++;
|
|
81
|
+
firstFailure ??= `${key}: HTTP ${res.status}`;
|
|
257
82
|
}
|
|
258
|
-
catch {
|
|
83
|
+
catch (err) {
|
|
84
|
+
failed++;
|
|
85
|
+
firstFailure ??= `${key}: ${err instanceof Error ? err.message : String(err)}`;
|
|
259
86
|
}
|
|
260
87
|
});
|
|
261
|
-
|
|
88
|
+
if (failed > 0)
|
|
89
|
+
throw new Error(`MinioBlobBackend.delete: ${failed} of ${distinct.length} object(s) could not be deleted (first: ${firstFailure})`);
|
|
262
90
|
}
|
|
263
91
|
async *listObjects() {
|
|
264
92
|
const f = this.cfg.fetchImpl ?? fetch;
|
|
@@ -333,29 +161,5 @@ export class MinioBlobBackend {
|
|
|
333
161
|
return { state: "missing" };
|
|
334
162
|
return { state: "unknown", detail: `HTTP ${res.status}` };
|
|
335
163
|
}
|
|
336
|
-
async deleteBlobs(hashes) {
|
|
337
|
-
if (hashes.length === 0)
|
|
338
|
-
return 0;
|
|
339
|
-
let toDelete;
|
|
340
|
-
if (this.indexPool && this.indexDialect) {
|
|
341
|
-
toDelete = await sqlDeleteIndexRowsPastGrace(this.indexDialect, this.indexPool, hashes, this.indexTable);
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
toDelete = [...new Set(hashes)];
|
|
345
|
-
}
|
|
346
|
-
if (toDelete.length === 0)
|
|
347
|
-
return 0;
|
|
348
|
-
let okCount = 0;
|
|
349
|
-
await mapBounded(toDelete, MINIO_OP_CONCURRENCY, async (hash) => {
|
|
350
|
-
try {
|
|
351
|
-
const res = await (this.cfg.fetchImpl ?? fetch)(this.presign(hash, "DELETE"), { method: "DELETE", signal: AbortSignal.timeout(OBJECT_STORE_IO_TIMEOUT_MS) });
|
|
352
|
-
if (res.ok || res.status === 404)
|
|
353
|
-
okCount++;
|
|
354
|
-
}
|
|
355
|
-
catch {
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
return okCount;
|
|
359
|
-
}
|
|
360
164
|
}
|
|
361
165
|
//# sourceMappingURL=blob-backend.js.map
|
|
@@ -24,12 +24,17 @@ export type SessionHeadReader = Required<Pick<SessionStore, "headOf">>;
|
|
|
24
24
|
*
|
|
25
25
|
* **One rule: a warm entry is served only while the store's head for that session still names the occupant and the leaf
|
|
26
26
|
* the entry holds.** Every hit reads the head first (`headOf` — one primary-key row read on the SQL twins); head gone, another
|
|
27
|
-
* occupant (core `compareOccupants` — anything but `same
|
|
27
|
+
* occupant (core `compareOccupants` — anything but `same`), or leaf moved ⇒ the entry is dropped and the
|
|
28
28
|
* session is woken from the store again ({@link CachingOptions.onStaleHit}). The leaf is half the token because it is exactly
|
|
29
29
|
* what the stores' conditional writes compare (`expectedLeafId`): a handle this cache hands out is never behind the store's
|
|
30
30
|
* leaf, so those writes fail only on a genuinely concurrent write — two runs writing one session at the same time. The
|
|
31
31
|
* occupant is the other half: a row another replica deleted and created again under the same id can stand at the leaf the
|
|
32
|
-
* entry holds (both empty — `null`), and serving the old view would hand a run the previous occupant's token.
|
|
32
|
+
* entry holds (both empty — `null`), and serving the old view would hand a run the previous occupant's token. Whether two
|
|
33
|
+
* cells name one occupant is core's one reading (7.65.0): a token on both sides and equal ⇒ `same`; no token on either side (absent,
|
|
34
|
+
* `""`, a non-string) ⇒ `same` too — every store write that creates a row mints a token, so two token-less readings of one id are one
|
|
35
|
+
* row generation, and the leaf still has to match; a token on one side only ⇒ `different` (no token is never a wildcard). A run handed
|
|
36
|
+
* a token-less view still cannot write through it: the write path takes its token from `sessionFaceOfHead`, which refuses a token-less
|
|
37
|
+
* head (`SessionIncarnationMissingError`). Any number of
|
|
33
38
|
* replicas may share one store under any routing; session affinity only raises the hit rate.
|
|
34
39
|
*
|
|
35
40
|
* Open item (the same before this rule): a write that rewrites history while leaving the final leaf id where it was —
|
|
@@ -84,12 +89,12 @@ export declare class CachingSessionStore implements SessionStore {
|
|
|
84
89
|
/** The auto-titler's NULL-only title write (SQL twins + local sidecar carry it; pure pass-through). */
|
|
85
90
|
readonly setTitleIfNull?: (sessionId: string, title: string) => Promise<boolean>;
|
|
86
91
|
readonly probeTitle?: (sessionId: string) => Promise<"none" | "untitled" | "titled">;
|
|
87
|
-
/** [ref] —— 换源通告的基线面(`
|
|
92
|
+
/** [ref] —— 换源通告的基线面(`session_ext.instruction_source` / local sidecar),纯转发、不经暖缓存。
|
|
88
93
|
* 🔴 必须转发(与 retention / placements 同一条教训):默认 `SESSION_CACHE_TTL_SEC=300` 把真店包进本类,
|
|
89
94
|
* 而装配点按「店上两个方法都在」判席 —— 不转发 = 默认部署上换源通告**静默不发**,且没有任何一处报错。 */
|
|
90
95
|
readonly readInstructionSource?: InstructionSourceStore["readInstructionSource"];
|
|
91
96
|
readonly recordInstructionSource?: InstructionSourceStore["recordInstructionSource"];
|
|
92
|
-
/** 会话行的位置与项目那一格(`
|
|
97
|
+
/** 会话行的位置与项目那一格(`session_ext.workspace` / local sidecar;`session-workspace.ts`),纯转发、不经暖缓存。
|
|
93
98
|
* 🔴 必须转发(同上一条教训):装配点与 resolveSpec 按「店上两个方法都在」判这一面 —— 不转发 = 默认部署上不记行、续跑腿不续声明项目,且没有任何一处报错。 */
|
|
94
99
|
readonly readSessionWorkspace?: SessionWorkspaceStore["readSessionWorkspace"];
|
|
95
100
|
readonly recordSessionWorkspace?: SessionWorkspaceStore["recordSessionWorkspace"];
|
|
@@ -60,7 +60,7 @@ export declare function buildCheckpointIndexCells(cp: Checkpoint): CheckpointInd
|
|
|
60
60
|
/**
|
|
61
61
|
* `approval_card` 列放得下的卡词**字节数**(UTF-8 字节,不是字符数),按方言各一格(键表对 {@link SqlDialect} 闭合:加一种方言 ⇒ 编译红)。
|
|
62
62
|
* MySQL 协议(TiDB / MySQL)的列型是 `TEXT`,上限 65,535 字节 —— 严格模式下超长写入抛 `Data too long`,非严格模式静默截成半只卡词;PG 的 `TEXT` 没有这个上限。
|
|
63
|
-
* 列型的属主是中央 DDL(`tidb-pool.ts` / `pg-pool.ts` 的 `approval_card`)
|
|
63
|
+
* 列型的属主是中央 DDL(`tidb-pool.ts` / `pg-pool.ts` 的 `approval_card`),本表按那个列型读类型容量表(`text-column-capacity.ts`,容量数字不在这里另抄;`test/checkpoint-index-columns.test.ts` 把列型与本表同读,换列型 ⇒ 红)。
|
|
64
64
|
* 引擎照存集外词、长度不由本仓定,但引擎铸得出的卡词是闭集短词 —— 超出容量的只会是手改 / 外来写者写下的文档;读这张表的只有 {@link judgeCheckpointIndexCells}
|
|
65
65
|
* (写口超出 ⇒ 类型化拒,M29 超出 ⇒ 计数 + 点名跳过、不挡起服)。
|
|
66
66
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CARD_FACET_OVERRIDES, PAUSE_REGISTRY, checkpointIndexFacts } from "@sema-agent/core";
|
|
2
|
+
import { TEXT_COLUMN_TYPE_MAX_BYTES } from "./text-column-capacity.js";
|
|
2
3
|
export const CHECKPOINT_INDEX_COLUMNS = {
|
|
3
4
|
token: "token",
|
|
4
5
|
scope: "scope",
|
|
@@ -33,8 +34,8 @@ export function buildCheckpointIndexCells(cp) {
|
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
export const APPROVAL_CARD_COLUMN_MAX_BYTES = {
|
|
36
|
-
mysql:
|
|
37
|
-
pg:
|
|
37
|
+
mysql: TEXT_COLUMN_TYPE_MAX_BYTES.mysql.TEXT,
|
|
38
|
+
pg: TEXT_COLUMN_TYPE_MAX_BYTES.pg.TEXT,
|
|
38
39
|
};
|
|
39
40
|
export function judgeCheckpointIndexCells(cp, dialect) {
|
|
40
41
|
const gate = cp.gate;
|
|
@@ -290,7 +290,7 @@ export declare function boundedRuleOffers(raw: unknown, opts?: {
|
|
|
290
290
|
/**
|
|
291
291
|
* {@link SqlCheckpointStore.get} 读到的 `checkpoint` 列字节读不成一只检查点(JSON 字面 `null` / 标量 / 数组 / 非 JSON)时抛的拒 —— 就是店的拒绝契约类
|
|
292
292
|
* {@link StoreCorruptError}(`kind:"corrupt"` + 坐标,所有认它的读口原样认它),外加**引擎判官对这一格原样字节的判决**:列表面对同一格答的就是它
|
|
293
|
-
* ({@link verdictOfUnreadableBody},`rowVerdict`),所以决断口("行自己拒")
|
|
293
|
+
* ({@link verdictOfUnreadableBody},`rowVerdict`),所以决断口("行自己拒")答的码与出路句取这一只判决的 `code` / `sentence`、不另铸(决断口 `rowRefusalAnswer`)。
|
|
294
294
|
* 判决在抛的这一拍现算(纯函数、全函数,不读钟不读库);店自己的诊断(`message`:坐标 + 体的问题)原样保留。
|
|
295
295
|
*/
|
|
296
296
|
export declare class UnreadableCheckpointRowError extends StoreCorruptError {
|
|
@@ -86,7 +86,7 @@ export declare function ensurePgDeviceSchema(q: PgQuery): Promise<void>;
|
|
|
86
86
|
* (读侧 `parseDeviceAuditEvent`),CHECK 只是纵深 —— 所以给运维的是**手工**约束级重建语句
|
|
87
87
|
* (drop + 按当前闭集 add),历史一行不丢,纵深回到当前词表。
|
|
88
88
|
*
|
|
89
|
-
* 调用点:`boot/stores.ts`,**只在 device 车道真会装配时探**(`config.remoteExec
|
|
89
|
+
* 调用点:`boot/stores.ts`,**只在 device 车道真会装配时探**(`config.remoteExec.provider ===
|
|
90
90
|
* "device"`,与 main.ts 的 `createDeviceLane` 谓词同源)——非 device 部署零审计写点,为它拒启是纯误伤
|
|
91
91
|
* ([ref] round2 的同一条收窄)。
|
|
92
92
|
*/
|
|
@@ -142,7 +142,7 @@ export declare class SqlDeviceStore implements DeviceStore {
|
|
|
142
142
|
private lockDeviceStatus;
|
|
143
143
|
/**
|
|
144
144
|
* §4.3.2 首绑(§3.3 转换表 place / bind 两行)—— **一只事务**:锁设备行(active ∧ 属主)→ 锁定读根会话行的执行格 → 判官
|
|
145
|
-
* {@link settledDeviceBindOutcome}(与内存参照实现同一只)→ absent 用 place 语句、writer(device, ∅) 用 bind
|
|
145
|
+
* {@link settledDeviceBindOutcome}(与内存参照实现同一只)→ 补旁表行 + absent 用 place 语句、writer(device, ∅) 用 bind 语句(住客由根行的锁钉住,写按格谓词定址)。
|
|
146
146
|
*
|
|
147
147
|
* 不读认领:这是认领持有者自己的初始放置写(读写序律唯一的例外,`execution-placement-sql.ts` 头注)。锁序:设备行 → 根 `session_meta`。
|
|
148
148
|
* 持着根行的锁判过「可写」之后那句 UPDATE 不可能 0 行 —— 0 行即驱动 / 引擎异常,响亮抛,不折成业务分支([ref])。
|
|
@@ -2,7 +2,7 @@ import { mysqlDriver, pgDriver, dialectJsonEncoder } from "./sql-driver.js";
|
|
|
2
2
|
import { isDupKeyError, isCheckViolationError } from "./sql-errors.js";
|
|
3
3
|
import { DEVICE_AUDIT_EVENTS, assertAcquireShape, assertDeviceIdShape, assertDeviceOwnerShape, assertEnrollTokenHashShape, assertIssueTokenShape, assertNewDeviceShape, assertPlaceDeviceShape, assertRebindShape, assertRevokeShape, assertWholeSeconds, parseDeviceAuditEvent, parseDevicePlatformOs, parseDeviceStatus, } from "../device-store.js";
|
|
4
4
|
import { WRITABLE, boundDeviceOf, settledDeviceBindOutcome, settledDeviceRebindOutcome } from "../execution-placement.js";
|
|
5
|
-
import { bindDeviceStatement, countDeviceBindingsOn, lockRootAndReadClaim, placeWriterStatement, readPlacementOn, rebindDeviceStatement, rowsOnSqlExec } from "./execution-placement-sql.js";
|
|
5
|
+
import { bindDeviceStatement, countDeviceBindingsOn, lockRootAndReadClaim, placeWriterStatement, readPlacementOn, rebindDeviceStatement, rowsOnSqlExec, writeCellOn } from "./execution-placement-sql.js";
|
|
6
6
|
import { ensureIndexes } from "./ensure-index.js";
|
|
7
7
|
import { decodeJsonColumn, foldJsonColumn, jsonColumnText, readJsonObjectColumn } from "./sql-json-column.js";
|
|
8
8
|
export const DEVICES_TABLE = "device";
|
|
@@ -520,11 +520,9 @@ export class SqlDeviceStore {
|
|
|
520
520
|
const now = new Date();
|
|
521
521
|
const device = { id: input.deviceId, owner: input.owner };
|
|
522
522
|
const stmt = reading.cell.role === "absent"
|
|
523
|
-
? placeWriterStatement(this.db.dialect, input.root,
|
|
524
|
-
: bindDeviceStatement(this.db.dialect, input.root,
|
|
525
|
-
|
|
526
|
-
if (res.affected !== 1)
|
|
527
|
-
throw new Error(`device-store: first bind of session ${input.root} affected ${res.affected} rows under a held row lock — engine anomaly, refusing to guess`);
|
|
523
|
+
? placeWriterStatement(this.db.dialect, input.root, { lane: "device", device }, now)
|
|
524
|
+
: bindDeviceStatement(this.db.dialect, input.root, device, now);
|
|
525
|
+
await writeCellOn(conn, this.db.dialect, input.root, stmt);
|
|
528
526
|
await conn.commit();
|
|
529
527
|
const placed = { id: input.deviceId, owner: { tenant: input.owner.tenant, subject: input.owner.subject }, rev: 0, placedAt: now.toISOString() };
|
|
530
528
|
return { outcome: "bound", device: placed };
|
|
@@ -564,10 +562,7 @@ export class SqlDeviceStore {
|
|
|
564
562
|
}
|
|
565
563
|
const from = boundDeviceOf(reading.cell).id;
|
|
566
564
|
const now = new Date();
|
|
567
|
-
|
|
568
|
-
const cas = await conn.query(stmt.text, [...stmt.values]);
|
|
569
|
-
if (cas.affected !== 1)
|
|
570
|
-
throw new Error(`device-store: rebind CAS affected ${cas.affected} rows under a held row lock — engine anomaly, refusing to guess`);
|
|
565
|
+
await writeCellOn(conn, this.db.dialect, input.root, rebindDeviceStatement(this.db.dialect, input.root, input.owner, input.expectedRev, input.targetDeviceId, now));
|
|
571
566
|
const rev = input.expectedRev + 1;
|
|
572
567
|
await this.insertAuditOn(conn, { event: "session_rebound", deviceId: input.targetDeviceId, owner: input.owner, detail: { from, to: input.targetDeviceId, rev } });
|
|
573
568
|
await conn.commit();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔴 一次性迁移 **M40**(窗口见 `plugins/one-time-migrations.ts` 登记表 M40 行;头注 M40 段):没有执行环境的那条车道的存词由退役名改成 `none`。
|
|
3
|
+
*
|
|
4
|
+
* 本文件是那一对词与「读到退役词时补哪一句」的**唯一属主**:SQL 腿(`one-time-migrations.ts` 的 M40 步,两方言两张表)、local 两腿(会话元数据边档 ——
|
|
5
|
+
* `LocalSessionStore.renameRetiredExecutionLaneWordM40`,排在严格边档对账之前;问账日志 —— `FileApprovalAskStore.renameRetiredExecutionLaneWordM40`,
|
|
6
|
+
* 排在 M32 回填之前)与两只 SQL 读口的拒句(`approval-ask-store-sql.ts` / `execution-placement-sql.ts`)都读这里。窗关删码 = 删这只文件与上面那几处调用。
|
|
7
|
+
*
|
|
8
|
+
* 本文件只 import 类型(零运行期依赖)⇒ 被一次性迁移段与它 import 的店文件同时读,不成环。
|
|
9
|
+
*/
|
|
10
|
+
import type { ExecutionLane } from "../execution-lane-caps.js";
|
|
11
|
+
/** 退役的存词(本版之前的部署在没有声明车道时铸下的那一个)。本版的车道闭集里没有它,任何读口读到都响亮拒。 */
|
|
12
|
+
export declare const RETIRED_EXECUTION_LANE_WORD_M40 = "in-process";
|
|
13
|
+
/** 它的新名:声明「这一部署没有执行环境」的那条车道。 */
|
|
14
|
+
export declare const RENAMED_EXECUTION_LANE_M40: ExecutionLane;
|
|
15
|
+
/**
|
|
16
|
+
* 读口拒句的补句:读到的词就是退役词 ⇒ 说清它是什么、为什么还在(迁移之后又被写下 = 有一只更早版本的副本还在服务)与出路;别的词 ⇒ 空串(拒句不变)。
|
|
17
|
+
* 起服的迁移改完之后,只有混跑的旧副本还会写下它(版本围栏见登记表 M40 行与 MIGRATION 本版节)。
|
|
18
|
+
*/
|
|
19
|
+
export declare function retiredExecutionLaneHintM40(word: string): string;
|
|
20
|
+
//# sourceMappingURL=execution-lane-rename-m40.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const RETIRED_EXECUTION_LANE_WORD_M40 = "in-process";
|
|
2
|
+
export const RENAMED_EXECUTION_LANE_M40 = "none";
|
|
3
|
+
export function retiredExecutionLaneHintM40(word) {
|
|
4
|
+
if (word !== RETIRED_EXECUTION_LANE_WORD_M40)
|
|
5
|
+
return "";
|
|
6
|
+
return (` — "${RETIRED_EXECUTION_LANE_WORD_M40}" is the name an earlier version gave the lane with no execution environment, which this version calls "${RENAMED_EXECUTION_LANE_M40}"; ` +
|
|
7
|
+
"the one-time migration M40 at boot renames every stored copy, so this row was written afterwards by a replica of an earlier version that is still serving. " +
|
|
8
|
+
"Stop every replica of the earlier version, then restart this version once (its boot renames what they wrote)");
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=execution-lane-rename-m40.js.map
|