@capybara-hq/kernel 0.1.0-rc.22 → 0.1.0-rc.24
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/bootstrap.json +25 -25
- package/dist/admin/admin.controller.d.ts +3 -3
- package/dist/admin/admin.controller.js +6 -2
- package/dist/admin/admin.module.d.ts +2 -1
- package/dist/admin/admin.module.js +7 -3
- package/dist/admin/admin.schemas.d.ts +13 -0
- package/dist/admin/outbox-dead.controller.d.ts +23 -0
- package/dist/admin/outbox-dead.controller.js +62 -0
- package/dist/admin/outbox-dead.schemas.d.ts +8 -0
- package/dist/admin/outbox-dead.schemas.js +18 -0
- package/dist/admin/outbox-dead.service.d.ts +66 -0
- package/dist/admin/outbox-dead.service.js +179 -0
- package/dist/admin/overview.service.d.ts +40 -5
- package/dist/admin/overview.service.js +41 -7
- package/dist/agents/from-template.js +1 -1
- package/dist/background/finish.d.ts +5 -2
- package/dist/background/finish.js +14 -3
- package/dist/background/launch.d.ts +44 -5
- package/dist/background/launch.js +92 -9
- package/dist/background/session.d.ts +14 -2
- package/dist/background/session.js +26 -4
- package/dist/background/status.d.ts +1 -1
- package/dist/background/status.js +3 -3
- package/dist/background/stop.d.ts +0 -2
- package/dist/background/stop.js +1 -21
- package/dist/background/store.d.ts +8 -0
- package/dist/background/store.js +24 -0
- package/dist/catalog/admin-catalog.controller.d.ts +21 -2
- package/dist/catalog/admin-catalog.controller.js +45 -6
- package/dist/catalog/admin-catalog.schemas.d.ts +5 -0
- package/dist/catalog/admin-catalog.schemas.js +8 -0
- package/dist/catalog/catalog-content.d.ts +5 -0
- package/dist/catalog/catalog-content.js +1 -0
- package/dist/catalog/catalog.module.d.ts +2 -1
- package/dist/catalog/catalog.module.js +5 -1
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/platform-import-update.d.ts +50 -0
- package/dist/catalog/platform-import-update.js +116 -0
- package/dist/catalog/plugin-import.d.ts +36 -1
- package/dist/catalog/plugin-import.js +23 -1
- package/dist/catalog/plugin-upgrade.d.ts +18 -0
- package/dist/catalog/plugin-upgrade.js +19 -0
- package/dist/catalog/requests.service.js +2 -2
- package/dist/channels/channels.module.d.ts +5 -2
- package/dist/channels/channels.module.js +9 -2
- package/dist/channels/deliver-job.d.ts +25 -0
- package/dist/channels/deliver-job.js +25 -0
- package/dist/channels/inbound.d.ts +1 -1
- package/dist/channels/inbound.js +2 -15
- package/dist/channels/jobs.d.ts +28 -18
- package/dist/channels/jobs.js +63 -26
- package/dist/config/schema.d.ts +3 -6
- package/dist/config/schema.js +20 -27
- package/dist/conversations/agent-tree.d.ts +16 -0
- package/dist/conversations/agent-tree.js +36 -0
- package/dist/conversations/conversations.service.d.ts +44 -14
- package/dist/conversations/conversations.service.js +52 -38
- package/dist/conversations/event-log.d.ts +7 -10
- package/dist/conversations/event-log.js +24 -15
- package/dist/conversations/events.js +2 -1
- package/dist/conversations/queue.service.d.ts +8 -3
- package/dist/conversations/queue.service.js +37 -13
- package/dist/conversations/titles.d.ts +21 -8
- package/dist/conversations/titles.js +42 -15
- package/dist/db/kernel-schema.d.ts +26 -8
- package/dist/devices/devices.service.d.ts +12 -3
- package/dist/devices/devices.service.js +30 -9
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +15 -0
- package/dist/evals/run-replay.js +14 -8
- package/dist/extensions/extensions.module.js +3 -0
- package/dist/extensions/lifecycle.d.ts +6 -1
- package/dist/extensions/lifecycle.js +9 -2
- package/dist/extensions/usage-subscribers.d.ts +43 -0
- package/dist/extensions/usage-subscribers.js +108 -0
- package/dist/http/api.module.js +2 -0
- package/dist/identity/settings.d.ts +53 -3
- package/dist/identity/settings.js +92 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/infra/cli/kernel-cli.module.js +5 -0
- package/dist/infra/config/kernel-config.service.d.ts +7 -0
- package/dist/infra/config/kernel-config.service.js +20 -0
- package/dist/infra/events/kernel-events.d.ts +9 -35
- package/dist/infra/outbox/outbox-relay.module.d.ts +6 -0
- package/dist/infra/outbox/outbox-relay.module.js +18 -0
- package/dist/infra/outbox/outbox.dispatcher.d.ts +103 -0
- package/dist/infra/outbox/outbox.dispatcher.js +310 -0
- package/dist/infra/outbox/outbox.module.d.ts +24 -0
- package/dist/infra/outbox/outbox.module.js +50 -0
- package/dist/infra/outbox/outbox.relay.d.ts +31 -0
- package/dist/infra/outbox/outbox.relay.js +76 -0
- package/dist/infra/outbox/outbox.service.d.ts +51 -0
- package/dist/infra/outbox/outbox.service.js +131 -0
- package/dist/infra/outbox/registry.d.ts +120 -0
- package/dist/infra/outbox/registry.js +108 -0
- package/dist/infra/queue/queue-names.d.ts +8 -0
- package/dist/infra/queue/queue-names.js +16 -0
- package/dist/kernel.module.js +3 -0
- package/dist/local-devices/device-policy.service.d.ts +4 -0
- package/dist/local-devices/device-policy.service.js +61 -3
- package/dist/local-devices/local-device-gateway.d.ts +4 -2
- package/dist/local-devices/local-device-gateway.js +39 -14
- package/dist/local-devices/machines.d.ts +25 -1
- package/dist/local-devices/machines.js +91 -15
- package/dist/local-devices/policy-summary.d.ts +44 -1
- package/dist/local-devices/policy-summary.js +69 -0
- package/dist/models/embeddings.d.ts +9 -9
- package/dist/models/embeddings.js +11 -18
- package/dist/models/models.module.js +3 -0
- package/dist/orgs/orgs.service.js +7 -0
- package/dist/orgs/settings.controller.js +2 -2
- package/dist/orgs/settings.service.d.ts +11 -5
- package/dist/orgs/settings.service.js +28 -14
- package/dist/overrides.d.ts +20 -3
- package/dist/overrides.js +10 -2
- package/dist/platform/exclusions.js +5 -0
- package/dist/platform/ops/admin.ops.js +50 -9
- package/dist/platform/ops/catalog-admin.ops.d.ts +3 -1
- package/dist/platform/ops/catalog-admin.ops.js +32 -4
- package/dist/platform/ops/org-settings.ops.js +3 -3
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/outbox.ops.d.ts +21 -0
- package/dist/platform/ops/outbox.ops.js +125 -0
- package/dist/platform/ops/platform.ops.js +1 -1
- package/dist/platform/ops/schedules.ops.js +40 -1
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +3 -0
- package/dist/platform/route-schemas.js +3 -0
- package/dist/roles/worker.module.js +9 -4
- package/dist/runtime/langgraph-loop.js +13 -5
- package/dist/runtime/limits.d.ts +15 -0
- package/dist/runtime/limits.js +25 -0
- package/dist/runtime/loop.d.ts +8 -3
- package/dist/runtime/loop.js +2 -1
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +17 -2
- package/dist/runtime/model-call.d.ts +14 -16
- package/dist/runtime/model-call.js +14 -24
- package/dist/runtime/queue-lost-jobs.d.ts +24 -0
- package/dist/runtime/queue-lost-jobs.js +51 -0
- package/dist/runtime/run-control.d.ts +42 -5
- package/dist/runtime/run-control.js +66 -12
- package/dist/runtime/run-finish.d.ts +39 -12
- package/dist/runtime/run-finish.js +97 -14
- package/dist/runtime/run-jobs.d.ts +95 -13
- package/dist/runtime/run-jobs.js +199 -28
- package/dist/runtime/run-orphan-check.job.d.ts +142 -0
- package/dist/runtime/run-orphan-check.job.js +339 -0
- package/dist/runtime/run-processors.d.ts +16 -9
- package/dist/runtime/run-processors.js +1 -1
- package/dist/runtime/run-queue.d.ts +64 -55
- package/dist/runtime/run-queue.js +147 -284
- package/dist/runtime/run-steps.d.ts +1 -2
- package/dist/runtime/run-steps.js +8 -11
- package/dist/runtime/run-worker.d.ts +6 -17
- package/dist/runtime/run-worker.js +32 -34
- package/dist/runtime/runtime.module.d.ts +2 -3
- package/dist/runtime/runtime.module.js +5 -6
- package/dist/runtime/step-log.d.ts +16 -4
- package/dist/runtime/step-log.js +26 -6
- package/dist/runtime/stream.controller.d.ts +2 -4
- package/dist/runtime/stream.controller.js +5 -11
- package/dist/runtime/subagents/child.js +1 -1
- package/dist/runtime/subagents/definition.d.ts +2 -1
- package/dist/runtime/subagents/definition.js +4 -2
- package/dist/runtime/subagents/deliveries.d.ts +6 -3
- package/dist/runtime/subagents/deliveries.js +16 -7
- package/dist/runtime/subagents/dispatch.d.ts +12 -12
- package/dist/runtime/subagents/dispatch.js +13 -38
- package/dist/runtime/subagents/messages.d.ts +5 -1
- package/dist/runtime/subagents/messages.js +11 -3
- package/dist/runtime/subagents/skill-fork.d.ts +3 -3
- package/dist/runtime/subagents/skill-fork.js +5 -5
- package/dist/runtime/subagents/subagents.service.js +1 -1
- package/dist/runtime/subagents/tree-jobs.d.ts +61 -0
- package/dist/runtime/subagents/tree-jobs.js +86 -0
- package/dist/runtime/usage-report-jobs.d.ts +23 -48
- package/dist/runtime/usage-report-jobs.js +67 -119
- package/dist/runtime/usage-report.d.ts +28 -77
- package/dist/runtime/usage-report.js +35 -213
- package/dist/runtime/waits.d.ts +48 -198
- package/dist/runtime/waits.js +103 -805
- package/dist/sandbox/platform-tiers.d.ts +86 -0
- package/dist/sandbox/platform-tiers.js +97 -0
- package/dist/sandbox/sandbox.service.d.ts +18 -5
- package/dist/sandbox/sandbox.service.js +75 -20
- package/dist/sandbox/tiers.d.ts +14 -2
- package/dist/sandbox/tiers.js +8 -0
- package/dist/schedules/calendar.d.ts +134 -0
- package/dist/schedules/calendar.js +410 -0
- package/dist/schedules/fire.d.ts +1 -3
- package/dist/schedules/fire.js +5 -10
- package/dist/schedules/run-tracker.d.ts +0 -5
- package/dist/schedules/run-tracker.js +0 -13
- package/dist/schedules/scan.job.js +15 -20
- package/dist/schedules/schedule-math.d.ts +42 -0
- package/dist/schedules/schedule-math.js +52 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +16 -0
- package/dist/schedules/scheduled-tasks.service.js +53 -0
- package/dist/schedules/schedules.controller.d.ts +5 -1
- package/dist/schedules/schedules.controller.js +15 -1
- package/dist/schedules/schedules.schemas.d.ts +35 -0
- package/dist/schedules/schedules.schemas.js +27 -0
- package/dist/schedules/store.d.ts +5 -0
- package/dist/schedules/store.js +20 -0
- package/dist/tools/approvals.service.d.ts +26 -7
- package/dist/tools/approvals.service.js +88 -10
- package/dist/tools/builtin-names.d.ts +5 -3
- package/dist/tools/builtin-names.js +12 -4
- package/dist/tools/builtins/builtin-tools.d.ts +1 -2
- package/dist/tools/builtins/builtin-tools.js +21 -17
- package/dist/tools/builtins/sandbox/bash.js +9 -3
- package/dist/tools/builtins/sandbox/common.d.ts +18 -1
- package/dist/tools/builtins/sandbox/common.js +14 -1
- package/dist/tools/builtins/sandbox/index.d.ts +2 -1
- package/dist/tools/builtins/sandbox/index.js +4 -1
- package/dist/tools/builtins/sandbox/task-list.d.ts +12 -0
- package/dist/tools/builtins/sandbox/task-list.js +130 -0
- package/dist/tools/builtins/sandbox/task-output.d.ts +8 -1
- package/dist/tools/builtins/sandbox/task-output.js +21 -3
- package/dist/tools/builtins/web/extract.d.ts +2 -4
- package/dist/tools/builtins/web/extract.js +2 -5
- package/dist/tools/pipeline.d.ts +1 -1
- package/dist/tools/pipeline.js +1 -1
- package/dist/tools/questions.service.d.ts +15 -6
- package/dist/tools/questions.service.js +20 -8
- package/dist/tools/registry.d.ts +4 -2
- package/dist/tools/registry.js +4 -3
- package/dist/tools/tools.module.js +4 -3
- package/package.json +3 -3
- package/src/migrations/0118_device_policy_ops.sql +6 -0
- package/src/migrations/0119_outbox.sql +22 -0
- package/src/migrations/0120_drop_usage_report_sweep.sql +7 -0
package/bootstrap.json
CHANGED
|
@@ -3,103 +3,103 @@
|
|
|
3
3
|
"schemaVersion": 1,
|
|
4
4
|
"marketplace": {
|
|
5
5
|
"url": "https://github.com/capybara-hq/plugins.git",
|
|
6
|
-
"commit": "
|
|
6
|
+
"commit": "4bfd588739e5cec6f2177d4e8f72e43a4dae50f3"
|
|
7
7
|
},
|
|
8
8
|
"plugins": [
|
|
9
9
|
{
|
|
10
10
|
"name": "openai-compatible",
|
|
11
11
|
"source": "npm",
|
|
12
12
|
"npm": "@capybara-hq/plugin-openai-compatible",
|
|
13
|
-
"version": "0.1.0-rc.
|
|
14
|
-
"integrity": "sha512-
|
|
13
|
+
"version": "0.1.0-rc.8",
|
|
14
|
+
"integrity": "sha512-IDINuU0r2JONeoEneACLhqnIeDCHX0AICaUJd8TeVmCbzsjMPlchTXngFQin66UN3jqi92yhFDGMKixLsArVCA==",
|
|
15
15
|
"required": true
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"name": "object-store-s3",
|
|
19
19
|
"source": "npm",
|
|
20
20
|
"npm": "@capybara-hq/plugin-object-store-s3",
|
|
21
|
-
"version": "0.1.0-rc.
|
|
22
|
-
"integrity": "sha512-
|
|
21
|
+
"version": "0.1.0-rc.7",
|
|
22
|
+
"integrity": "sha512-7HHh45e2CiMxQVfMEKexdRkT7k2iUqznNWMEVazzd+rhT4tguLVY8TkWClv4EK246fqVXvnj48rmmL6Dd6oTvw==",
|
|
23
23
|
"required": true
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"name": "anthropic",
|
|
27
27
|
"source": "npm",
|
|
28
28
|
"npm": "@capybara-hq/plugin-anthropic",
|
|
29
|
-
"version": "0.1.0-rc.
|
|
30
|
-
"integrity": "sha512-
|
|
29
|
+
"version": "0.1.0-rc.7",
|
|
30
|
+
"integrity": "sha512-yjUyDqJppihZmhgLVomFbhf1Iek31xyJ4W4+It4Dy3K4wsyZV9khhWrm9x1xxtcb1RvDIGgUxRmvLgoTIeUTYQ==",
|
|
31
31
|
"required": false
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"name": "openai",
|
|
35
35
|
"source": "npm",
|
|
36
36
|
"npm": "@capybara-hq/plugin-openai",
|
|
37
|
-
"version": "0.1.0-rc.
|
|
38
|
-
"integrity": "sha512-
|
|
37
|
+
"version": "0.1.0-rc.8",
|
|
38
|
+
"integrity": "sha512-n8IRL9u+yxmtd/aEntgSdTswjTDdhn2tjXTN9FWARGI+dTQnsbkX9108P4T31kmOBVcuwPYzNB09NG+im2LQIg==",
|
|
39
39
|
"required": false
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"name": "deepseek",
|
|
43
43
|
"source": "npm",
|
|
44
44
|
"npm": "@capybara-hq/plugin-deepseek",
|
|
45
|
-
"version": "0.1.0-rc.
|
|
46
|
-
"integrity": "sha512-
|
|
45
|
+
"version": "0.1.0-rc.7",
|
|
46
|
+
"integrity": "sha512-f0kYjYzvwxPtT2bnpf7fYkggMHvlLTJX7bacaWnIoR1cHeTxiNKuvOv8ptkztpkgTmKadjKqllI5b9AOhhILRg==",
|
|
47
47
|
"required": false
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"name": "bailian",
|
|
51
51
|
"source": "npm",
|
|
52
52
|
"npm": "@capybara-hq/plugin-bailian",
|
|
53
|
-
"version": "0.1.0-rc.
|
|
54
|
-
"integrity": "sha512-
|
|
53
|
+
"version": "0.1.0-rc.7",
|
|
54
|
+
"integrity": "sha512-VqTq6mjzka+iEW5BdcZspBdkWSQ1mLsLueg/XABaZzNDEAE/a6ErDE10GadzOTzorqAttXebTLJDjJebgLmtwA==",
|
|
55
55
|
"required": false
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"name": "ark",
|
|
59
59
|
"source": "npm",
|
|
60
60
|
"npm": "@capybara-hq/plugin-ark",
|
|
61
|
-
"version": "0.1.0-rc.
|
|
62
|
-
"integrity": "sha512-
|
|
61
|
+
"version": "0.1.0-rc.7",
|
|
62
|
+
"integrity": "sha512-Ml/HS3w3fD4x0gh/Yh0jbz8Riv8x7Jkd5phPZUsKDtuE4pvr+hllRYOxs9p0/Lax11BDvbUK9EFzRkCa+xAQeQ==",
|
|
63
63
|
"required": false
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"name": "connector-mcp",
|
|
67
67
|
"source": "npm",
|
|
68
68
|
"npm": "@capybara-hq/plugin-connector-mcp",
|
|
69
|
-
"version": "0.1.0-rc.
|
|
70
|
-
"integrity": "sha512-
|
|
69
|
+
"version": "0.1.0-rc.7",
|
|
70
|
+
"integrity": "sha512-hJlW+u1iLt/mKJ9iPBbGT6tbpGevPVTS+8dvLtPbpf2fFRhM2eLrQy6+zuKUhuVQCcJYBrpz4vu5vh1ZBkqNZg==",
|
|
71
71
|
"required": false
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
74
|
"name": "connector-openapi",
|
|
75
75
|
"source": "npm",
|
|
76
76
|
"npm": "@capybara-hq/plugin-connector-openapi",
|
|
77
|
-
"version": "0.1.0-rc.
|
|
78
|
-
"integrity": "sha512-
|
|
77
|
+
"version": "0.1.0-rc.8",
|
|
78
|
+
"integrity": "sha512-2WU6sU0yAeWDy10DZ2I45uv2I6Q1FQDKvok2W0r6dfIO11G9iTsRNIMbtNsdVO2OUWY8nhAgh95BXBrpUELELQ==",
|
|
79
79
|
"required": false
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"name": "jina",
|
|
83
83
|
"source": "npm",
|
|
84
84
|
"npm": "@capybara-hq/plugin-jina",
|
|
85
|
-
"version": "0.1.0-rc.
|
|
86
|
-
"integrity": "sha512-
|
|
85
|
+
"version": "0.1.0-rc.7",
|
|
86
|
+
"integrity": "sha512-rpr59xbQJg+DuzhnAjn7Ql0rW9Cw9gKWHpER9nKvILvEYjEurmhniJkkqeHMnMlPba8lNUeQRGzmxdmLfKA10g==",
|
|
87
87
|
"required": false
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
"name": "sandbox-docker",
|
|
91
91
|
"source": "npm",
|
|
92
92
|
"npm": "@capybara-hq/plugin-sandbox-docker",
|
|
93
|
-
"version": "0.1.0-rc.
|
|
94
|
-
"integrity": "sha512-
|
|
93
|
+
"version": "0.1.0-rc.12",
|
|
94
|
+
"integrity": "sha512-c1iTAu/ifkwfnvVOsxEDfxEJNU7HDVewDtX4vdibwpodIhBvxz8tGjGYJ0HXDL3ipGEodiiIgJsVpabnMQ6cBQ==",
|
|
95
95
|
"required": false
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
"name": "todo",
|
|
99
99
|
"source": "npm",
|
|
100
100
|
"npm": "@capybara-hq/plugin-todo",
|
|
101
|
-
"version": "0.1.0-rc.
|
|
102
|
-
"integrity": "sha512-
|
|
101
|
+
"version": "0.1.0-rc.8",
|
|
102
|
+
"integrity": "sha512-xNdzvAmOQmBaDj29hsvbhMJINy2xe+ILTqG+cQhUfsyar7gUJaVOehseufvIq+cVbTjkI2tW7XlwGrtP3E3NtA==",
|
|
103
103
|
"required": false
|
|
104
104
|
},
|
|
105
105
|
{
|
|
@@ -5,7 +5,7 @@ import { PluginIcons } from "../extensions/plugin-icons.js";
|
|
|
5
5
|
import { type Account, AccountsService } from "../identity/accounts.js";
|
|
6
6
|
import { type Principal } from "../identity/principal.js";
|
|
7
7
|
import { SessionService } from "../identity/sessions.js";
|
|
8
|
-
import { type
|
|
8
|
+
import { type DeploymentSettingsView, SettingsService } from "../identity/settings.js";
|
|
9
9
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
10
10
|
import { type ModelDisabledPatch, type ModelProviderParams } from "../models/enablement.controller.js";
|
|
11
11
|
import { type ModelDisableResult, ModelEnablement } from "../models/enablement.js";
|
|
@@ -67,8 +67,8 @@ export declare class AdminController {
|
|
|
67
67
|
orgMembers({ orgId }: z.infer<typeof AdminOrgParams>): Promise<{
|
|
68
68
|
members: Member[];
|
|
69
69
|
}>;
|
|
70
|
-
getSettings(): Promise<
|
|
71
|
-
putSettings(principal: Principal, body: z.infer<typeof DeploymentSettingsBody>): Promise<
|
|
70
|
+
getSettings(): Promise<DeploymentSettingsView>;
|
|
71
|
+
putSettings(principal: Principal, body: z.infer<typeof DeploymentSettingsBody>): Promise<DeploymentSettingsView>;
|
|
72
72
|
/**
|
|
73
73
|
* 模型供应商与模型(后台「模型」页):每个供应商带状态,列模型失败的标 `error`,不影响其他供应商;
|
|
74
74
|
* 一并返回价格表与币种(改价仍走 `PUT /admin/model-prices`)。Each provider carries its extension's
|
|
@@ -142,11 +142,15 @@ let AdminController = class AdminController {
|
|
|
142
142
|
return { members: await this.members.list(orgId) };
|
|
143
143
|
}
|
|
144
144
|
async getSettings() {
|
|
145
|
-
return this.settings.
|
|
145
|
+
return this.settings.view();
|
|
146
146
|
}
|
|
147
147
|
async putSettings(principal, body) {
|
|
148
148
|
const actor = requireUser(principal);
|
|
149
|
-
|
|
149
|
+
const tokenId = patTokenId(actor);
|
|
150
|
+
// an API token may lower the platform's sandbox tiers, never raise them (dev tiers spec §2)
|
|
151
|
+
return this.settings.update(body, actor.account.id, tokenId, undefined, {
|
|
152
|
+
onlyNarrows: tokenId !== undefined,
|
|
153
|
+
});
|
|
150
154
|
}
|
|
151
155
|
/**
|
|
152
156
|
* 模型供应商与模型(后台「模型」页):每个供应商带状态,列模型失败的标 `error`,不影响其他供应商;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Deployment administration: the setup wizard, the platform-level audit log and the admin overview
|
|
3
|
-
* with its health read
|
|
3
|
+
* with its health read, seven-day usage aggregate and dead outbox rows (its controllers are the api
|
|
4
|
+
* role's, `ApiModule`).
|
|
4
5
|
*/
|
|
5
6
|
export declare class AdminModule {
|
|
6
7
|
}
|
|
@@ -16,8 +16,9 @@ import { ModelsModule } from "../models/models.module.js";
|
|
|
16
16
|
import { OrgsModule } from "../orgs/orgs.module.js";
|
|
17
17
|
import { ProvidersModule } from "../runtime/providers.js";
|
|
18
18
|
import { RunJobsModule } from "../runtime/run-jobs.js";
|
|
19
|
-
import {
|
|
19
|
+
import { UsageReportModule } from "../runtime/usage-report.js";
|
|
20
20
|
import { AdminHealthService } from "./health.service.js";
|
|
21
|
+
import { OutboxDeadService } from "./outbox-dead.service.js";
|
|
21
22
|
import { AdminOverviewService } from "./overview.service.js";
|
|
22
23
|
import { PlatformAuditService } from "./platform-audit.service.js";
|
|
23
24
|
import { SetupService } from "./setup.service.js";
|
|
@@ -25,7 +26,8 @@ import { SetupLockModule } from "./setup-lock.js";
|
|
|
25
26
|
import { AdminUsageService } from "./usage.service.js";
|
|
26
27
|
/**
|
|
27
28
|
* Deployment administration: the setup wizard, the platform-level audit log and the admin overview
|
|
28
|
-
* with its health read
|
|
29
|
+
* with its health read, seven-day usage aggregate and dead outbox rows (its controllers are the api
|
|
30
|
+
* role's, `ApiModule`).
|
|
29
31
|
*/
|
|
30
32
|
let AdminModule = class AdminModule {
|
|
31
33
|
};
|
|
@@ -44,7 +46,7 @@ AdminModule = __decorate([
|
|
|
44
46
|
RunJobsModule,
|
|
45
47
|
ChannelsModule,
|
|
46
48
|
TitlesModule,
|
|
47
|
-
|
|
49
|
+
UsageReportModule,
|
|
48
50
|
EvalsModule,
|
|
49
51
|
// the price table of the usage aggregate
|
|
50
52
|
ModelsModule,
|
|
@@ -55,6 +57,7 @@ AdminModule = __decorate([
|
|
|
55
57
|
AdminOverviewService,
|
|
56
58
|
AdminHealthService,
|
|
57
59
|
AdminUsageService,
|
|
60
|
+
OutboxDeadService,
|
|
58
61
|
],
|
|
59
62
|
exports: [
|
|
60
63
|
SetupService,
|
|
@@ -62,6 +65,7 @@ AdminModule = __decorate([
|
|
|
62
65
|
AdminOverviewService,
|
|
63
66
|
AdminHealthService,
|
|
64
67
|
AdminUsageService,
|
|
68
|
+
OutboxDeadService,
|
|
65
69
|
],
|
|
66
70
|
})
|
|
67
71
|
], AdminModule);
|
|
@@ -58,6 +58,19 @@ export declare const DeploymentSettingsBody: z.ZodObject<{
|
|
|
58
58
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
59
59
|
disabled: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
60
60
|
}, z.core.$strict>>;
|
|
61
|
+
sandboxTiers: z.ZodOptional<z.ZodObject<{
|
|
62
|
+
max: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
63
|
+
dev: "dev";
|
|
64
|
+
open: "open";
|
|
65
|
+
strict: "strict";
|
|
66
|
+
}>>>;
|
|
67
|
+
default: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
68
|
+
dev: "dev";
|
|
69
|
+
open: "open";
|
|
70
|
+
strict: "strict";
|
|
71
|
+
}>>>;
|
|
72
|
+
allowUnsandboxed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
73
|
+
}, z.core.$strict>>;
|
|
61
74
|
}, z.core.$strict>;
|
|
62
75
|
export declare const PurposeParams: z.ZodObject<{
|
|
63
76
|
purpose: z.ZodString;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import { type Principal } from "../identity/principal.js";
|
|
3
|
+
import { OutboxDeadParams } from "./outbox-dead.schemas.js";
|
|
4
|
+
import { type OutboxDeadRow, OutboxDeadService, type OutboxRetryOutcome } from "./outbox-dead.service.js";
|
|
5
|
+
/**
|
|
6
|
+
* Dead outbox rows (`/api/v1/admin/outbox/dead*`, transactional outbox spec §3.4): background work
|
|
7
|
+
* the kernel could not queue after its last attempt. Super admins only; service tokens 403. Retry
|
|
8
|
+
* and discard are audited (`outbox.retried`, `outbox.discarded`); the list is not (decision D5).
|
|
9
|
+
*/
|
|
10
|
+
export declare class OutboxDeadController {
|
|
11
|
+
private readonly dead;
|
|
12
|
+
constructor(dead: OutboxDeadService);
|
|
13
|
+
/** The dead rows, oldest first (at most 200). */
|
|
14
|
+
list(): Promise<{
|
|
15
|
+
items: OutboxDeadRow[];
|
|
16
|
+
}>;
|
|
17
|
+
/** Makes the row due again, or discards it when the same job is owed already (`already_owed`). */
|
|
18
|
+
retry(principal: Principal, { id }: z.infer<typeof OutboxDeadParams>): Promise<{
|
|
19
|
+
outcome: OutboxRetryOutcome;
|
|
20
|
+
}>;
|
|
21
|
+
/** Deletes the row: its job is never delivered. */
|
|
22
|
+
discard(principal: Principal, { id }: z.infer<typeof OutboxDeadParams>): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { Controller, Delete, Get, HttpCode, Inject, Post } from "@nestjs/common";
|
|
11
|
+
import { CurrentPrincipal, SuperAdmin } from "../identity/principal.js";
|
|
12
|
+
import { writeActorOf } from "../identity/write-actor.js";
|
|
13
|
+
import { createZodDto } from "../infra/validation/create-zod-dto.js";
|
|
14
|
+
import { ZParam } from "../infra/validation/zod-params.js";
|
|
15
|
+
import { OutboxDeadParams } from "./outbox-dead.schemas.js";
|
|
16
|
+
import { OutboxDeadService, } from "./outbox-dead.service.js";
|
|
17
|
+
class OutboxDeadParamsDto extends createZodDto(OutboxDeadParams, "OutboxDeadParams") {
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Dead outbox rows (`/api/v1/admin/outbox/dead*`, transactional outbox spec §3.4): background work
|
|
21
|
+
* the kernel could not queue after its last attempt. Super admins only; service tokens 403. Retry
|
|
22
|
+
* and discard are audited (`outbox.retried`, `outbox.discarded`); the list is not (decision D5).
|
|
23
|
+
*/
|
|
24
|
+
let OutboxDeadController = class OutboxDeadController {
|
|
25
|
+
dead;
|
|
26
|
+
constructor(dead) {
|
|
27
|
+
this.dead = dead;
|
|
28
|
+
}
|
|
29
|
+
/** The dead rows, oldest first (at most 200). */
|
|
30
|
+
list() {
|
|
31
|
+
return this.dead.list();
|
|
32
|
+
}
|
|
33
|
+
/** Makes the row due again, or discards it when the same job is owed already (`already_owed`). */
|
|
34
|
+
retry(principal, { id }) {
|
|
35
|
+
return this.dead.retry(id, writeActorOf(principal));
|
|
36
|
+
}
|
|
37
|
+
/** Deletes the row: its job is never delivered. */
|
|
38
|
+
async discard(principal, { id }) {
|
|
39
|
+
await this.dead.discard(id, writeActorOf(principal));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
__decorate([
|
|
43
|
+
Get()
|
|
44
|
+
], OutboxDeadController.prototype, "list", null);
|
|
45
|
+
__decorate([
|
|
46
|
+
Post(":id/retry"),
|
|
47
|
+
HttpCode(200),
|
|
48
|
+
__param(0, CurrentPrincipal()),
|
|
49
|
+
__param(1, ZParam(OutboxDeadParamsDto))
|
|
50
|
+
], OutboxDeadController.prototype, "retry", null);
|
|
51
|
+
__decorate([
|
|
52
|
+
Delete(":id"),
|
|
53
|
+
HttpCode(204),
|
|
54
|
+
__param(0, CurrentPrincipal()),
|
|
55
|
+
__param(1, ZParam(OutboxDeadParamsDto))
|
|
56
|
+
], OutboxDeadController.prototype, "discard", null);
|
|
57
|
+
OutboxDeadController = __decorate([
|
|
58
|
+
Controller("api/v1/admin/outbox/dead"),
|
|
59
|
+
SuperAdmin(),
|
|
60
|
+
__param(0, Inject(OutboxDeadService))
|
|
61
|
+
], OutboxDeadController);
|
|
62
|
+
export { OutboxDeadController };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { RouteSchemas } from "../platform/route-schemas.js";
|
|
3
|
+
/** A dead outbox row by id (`bigint` identity, read as a string; 400 when not digits). */
|
|
4
|
+
export declare const OutboxDeadParams: z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
/** The super admin's dead outbox rows (transactional outbox spec §3.4). */
|
|
8
|
+
export declare const OUTBOX_DEAD_ROUTES: readonly RouteSchemas[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** The largest `bigint` id; a larger one would make PG refuse the comparison. */
|
|
3
|
+
const MAX_BIGINT = 9223372036854775807n;
|
|
4
|
+
/** A dead outbox row by id (`bigint` identity, read as a string; 400 when not digits). */
|
|
5
|
+
export const OutboxDeadParams = z.object({
|
|
6
|
+
id: z
|
|
7
|
+
.string()
|
|
8
|
+
.regex(/^\d{1,19}$/, "id must be an outbox row id (digits)")
|
|
9
|
+
// checks do not abort: only digits reach BigInt
|
|
10
|
+
.refine((v) => !/^\d{1,19}$/.test(v) || BigInt(v) <= MAX_BIGINT, "id must be an outbox row id")
|
|
11
|
+
.describe("The dead row's id, as admin.outbox-list-dead lists it."),
|
|
12
|
+
});
|
|
13
|
+
/** The super admin's dead outbox rows (transactional outbox spec §3.4). */
|
|
14
|
+
export const OUTBOX_DEAD_ROUTES = [
|
|
15
|
+
{ route: "GET /api/v1/admin/outbox/dead" },
|
|
16
|
+
{ route: "POST /api/v1/admin/outbox/dead/:id/retry", params: OutboxDeadParams },
|
|
17
|
+
{ route: "DELETE /api/v1/admin/outbox/dead/:id", params: OutboxDeadParams },
|
|
18
|
+
];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { WriteActor } from "../identity/write-actor.js";
|
|
2
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
3
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
4
|
+
import { type OutboxFastPath } from "../infra/outbox/outbox.service.js";
|
|
5
|
+
/** The most dead rows `GET /api/v1/admin/outbox/dead` returns, oldest first. */
|
|
6
|
+
export declare const OUTBOX_DEAD_LIST_MAX = 200;
|
|
7
|
+
/** A dead outbox row as the super admin sees it (transactional outbox spec §3.4). */
|
|
8
|
+
export interface OutboxDeadRow {
|
|
9
|
+
id: string;
|
|
10
|
+
queue: string;
|
|
11
|
+
jobName: string;
|
|
12
|
+
jobId: string;
|
|
13
|
+
/** The org the work belongs to; null for platform work (or an org deleted since). */
|
|
14
|
+
orgId: string | null;
|
|
15
|
+
attempts: number;
|
|
16
|
+
lastError: string | null;
|
|
17
|
+
deadAt: string;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
}
|
|
20
|
+
/** Dead rows in all: how many and since when (the overview's `outbox_dead` attention item). */
|
|
21
|
+
export interface OutboxDeadSummary {
|
|
22
|
+
count: number;
|
|
23
|
+
oldestAt: Date | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* What a retry did: `retried` (the row is due again, the relay delivers it) or `already_owed`
|
|
27
|
+
* (the same job is owed by a pending row already, so the dead copy was discarded: ruling R8).
|
|
28
|
+
*/
|
|
29
|
+
export type OutboxRetryOutcome = "retried" | "already_owed";
|
|
30
|
+
/**
|
|
31
|
+
* The super admin's dead outbox rows (transactional outbox spec §3.4): the rows the dispatcher
|
|
32
|
+
* gave up on after its last attempt. Nothing is dropped silently: a row stays until a super admin
|
|
33
|
+
* retries it (it is due again with fresh attempts) or discards it, each audited at platform level
|
|
34
|
+
* (`outbox.retried`, `outbox.discarded`). A retry does not look at what the job is about: every
|
|
35
|
+
* job name added through the outbox is harmless when its work is gone or done (spec §3.5).
|
|
36
|
+
*/
|
|
37
|
+
export declare class OutboxDeadService {
|
|
38
|
+
readonly txHost: TransactionHost;
|
|
39
|
+
private readonly db;
|
|
40
|
+
private readonly fastPath;
|
|
41
|
+
constructor(txHost: TransactionHost, db: KernelDb, fastPath: OutboxFastPath);
|
|
42
|
+
/** The dead rows, oldest first, at most {@link OUTBOX_DEAD_LIST_MAX}. */
|
|
43
|
+
list(): Promise<{
|
|
44
|
+
items: OutboxDeadRow[];
|
|
45
|
+
}>;
|
|
46
|
+
/** How many rows are dead, and the oldest one's `dead_at`. */
|
|
47
|
+
summary(): Promise<OutboxDeadSummary>;
|
|
48
|
+
/**
|
|
49
|
+
* Makes a dead row due again (`dead_at` cleared, no attempts, next attempt now) and hands it to
|
|
50
|
+
* the fast path after the commit; the relay delivers it otherwise. When the same (queue, job id)
|
|
51
|
+
* is owed by a pending row already, the dead row is deleted instead (`already_owed`). A pending
|
|
52
|
+
* row added between the check and the update fails the update on the unique index: the retry
|
|
53
|
+
* then runs once more and takes the `already_owed` branch. `outbox.not_found` (404) when no dead
|
|
54
|
+
* row has the id.
|
|
55
|
+
*/
|
|
56
|
+
retry(id: string, actor: WriteActor, detail?: Record<string, unknown>): Promise<{
|
|
57
|
+
outcome: OutboxRetryOutcome;
|
|
58
|
+
}>;
|
|
59
|
+
private retryOnce;
|
|
60
|
+
/** Deletes a dead row: its job is never delivered. `outbox.not_found` (404) when none. */
|
|
61
|
+
discard(id: string, actor: WriteActor, detail?: Record<string, unknown>): Promise<void>;
|
|
62
|
+
/** The dead row `id`, locked for the transaction; `outbox.not_found` when it is not dead. */
|
|
63
|
+
private lockDead;
|
|
64
|
+
/** A platform-level audit event (no org: the outbox is the deployment's), naming the job. */
|
|
65
|
+
private audit;
|
|
66
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
11
|
+
import { sql } from "kysely";
|
|
12
|
+
import { ApiError } from "../errors.js";
|
|
13
|
+
import { audit } from "../identity/audit.js";
|
|
14
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
15
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
16
|
+
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
17
|
+
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
18
|
+
import { OUTBOX_FAST_PATH } from "../infra/outbox/outbox.service.js";
|
|
19
|
+
/** The most dead rows `GET /api/v1/admin/outbox/dead` returns, oldest first. */
|
|
20
|
+
export const OUTBOX_DEAD_LIST_MAX = 200;
|
|
21
|
+
/** The unique index of pending rows (0119): one pending row per (queue, job_id). */
|
|
22
|
+
const PENDING_UNIQUE = "outbox_job_uniq";
|
|
23
|
+
const isPendingConflict = (e) => typeof e === "object" &&
|
|
24
|
+
e !== null &&
|
|
25
|
+
e.code === "23505" &&
|
|
26
|
+
e.constraint === PENDING_UNIQUE;
|
|
27
|
+
const notFound = (id) => new ApiError("outbox.not_found", `No dead outbox row ${id}; list them with GET /api/v1/admin/outbox/dead`);
|
|
28
|
+
/**
|
|
29
|
+
* The super admin's dead outbox rows (transactional outbox spec §3.4): the rows the dispatcher
|
|
30
|
+
* gave up on after its last attempt. Nothing is dropped silently: a row stays until a super admin
|
|
31
|
+
* retries it (it is due again with fresh attempts) or discards it, each audited at platform level
|
|
32
|
+
* (`outbox.retried`, `outbox.discarded`). A retry does not look at what the job is about: every
|
|
33
|
+
* job name added through the outbox is harmless when its work is gone or done (spec §3.5).
|
|
34
|
+
*/
|
|
35
|
+
let OutboxDeadService = class OutboxDeadService {
|
|
36
|
+
txHost;
|
|
37
|
+
db;
|
|
38
|
+
fastPath;
|
|
39
|
+
constructor(txHost, db, fastPath) {
|
|
40
|
+
this.txHost = txHost;
|
|
41
|
+
this.db = db;
|
|
42
|
+
this.fastPath = fastPath;
|
|
43
|
+
}
|
|
44
|
+
/** The dead rows, oldest first, at most {@link OUTBOX_DEAD_LIST_MAX}. */
|
|
45
|
+
async list() {
|
|
46
|
+
const rows = await this.db.db
|
|
47
|
+
.selectFrom("outbox")
|
|
48
|
+
.select([
|
|
49
|
+
"id",
|
|
50
|
+
"queue",
|
|
51
|
+
"job_name",
|
|
52
|
+
"job_id",
|
|
53
|
+
"org_id",
|
|
54
|
+
"attempts",
|
|
55
|
+
"last_error",
|
|
56
|
+
"dead_at",
|
|
57
|
+
"created_at",
|
|
58
|
+
])
|
|
59
|
+
.where("dead_at", "is not", null)
|
|
60
|
+
.orderBy("dead_at")
|
|
61
|
+
.orderBy("id")
|
|
62
|
+
.limit(OUTBOX_DEAD_LIST_MAX)
|
|
63
|
+
.execute();
|
|
64
|
+
return {
|
|
65
|
+
items: rows.map((r) => ({
|
|
66
|
+
id: String(r.id),
|
|
67
|
+
queue: r.queue,
|
|
68
|
+
jobName: r.job_name,
|
|
69
|
+
jobId: r.job_id,
|
|
70
|
+
orgId: r.org_id,
|
|
71
|
+
attempts: r.attempts,
|
|
72
|
+
lastError: r.last_error,
|
|
73
|
+
deadAt: r.dead_at.toISOString(),
|
|
74
|
+
createdAt: r.created_at.toISOString(),
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** How many rows are dead, and the oldest one's `dead_at`. */
|
|
79
|
+
async summary() {
|
|
80
|
+
const row = await this.db.db
|
|
81
|
+
.selectFrom("outbox")
|
|
82
|
+
.select([sql `count(*)`.as("count"), sql `min(dead_at)`.as("oldest")])
|
|
83
|
+
.where("dead_at", "is not", null)
|
|
84
|
+
.executeTakeFirstOrThrow();
|
|
85
|
+
return { count: Number(row.count), oldestAt: row.oldest };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Makes a dead row due again (`dead_at` cleared, no attempts, next attempt now) and hands it to
|
|
89
|
+
* the fast path after the commit; the relay delivers it otherwise. When the same (queue, job id)
|
|
90
|
+
* is owed by a pending row already, the dead row is deleted instead (`already_owed`). A pending
|
|
91
|
+
* row added between the check and the update fails the update on the unique index: the retry
|
|
92
|
+
* then runs once more and takes the `already_owed` branch. `outbox.not_found` (404) when no dead
|
|
93
|
+
* row has the id.
|
|
94
|
+
*/
|
|
95
|
+
async retry(id, actor, detail = {}) {
|
|
96
|
+
try {
|
|
97
|
+
return await this.retryOnce(id, actor, detail);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
if (!isPendingConflict(e))
|
|
101
|
+
throw e;
|
|
102
|
+
return this.retryOnce(id, actor, detail);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async retryOnce(id, actor, detail) {
|
|
106
|
+
const row = await this.lockDead(id);
|
|
107
|
+
const owed = await this.db.db
|
|
108
|
+
.selectFrom("outbox")
|
|
109
|
+
.select("id")
|
|
110
|
+
.where("queue", "=", row.queue)
|
|
111
|
+
.where("job_id", "=", row.job_id)
|
|
112
|
+
.where("dead_at", "is", null)
|
|
113
|
+
.executeTakeFirst();
|
|
114
|
+
let outcome;
|
|
115
|
+
if (owed) {
|
|
116
|
+
await this.db.db.deleteFrom("outbox").where("id", "=", id).execute();
|
|
117
|
+
outcome = "already_owed";
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
await this.db.db
|
|
121
|
+
.updateTable("outbox")
|
|
122
|
+
.set({ dead_at: null, attempts: 0, next_attempt_at: sql `now()` })
|
|
123
|
+
.where("id", "=", id)
|
|
124
|
+
.execute();
|
|
125
|
+
outcome = "retried";
|
|
126
|
+
afterCommit(() => this.fastPath([id]));
|
|
127
|
+
}
|
|
128
|
+
await this.audit("outbox.retried", id, row, actor, { outcome, ...detail });
|
|
129
|
+
return { outcome };
|
|
130
|
+
}
|
|
131
|
+
/** Deletes a dead row: its job is never delivered. `outbox.not_found` (404) when none. */
|
|
132
|
+
async discard(id, actor, detail = {}) {
|
|
133
|
+
const row = await this.lockDead(id);
|
|
134
|
+
await this.db.db.deleteFrom("outbox").where("id", "=", id).execute();
|
|
135
|
+
await this.audit("outbox.discarded", id, row, actor, detail);
|
|
136
|
+
}
|
|
137
|
+
/** The dead row `id`, locked for the transaction; `outbox.not_found` when it is not dead. */
|
|
138
|
+
async lockDead(id) {
|
|
139
|
+
const row = await this.db.db
|
|
140
|
+
.selectFrom("outbox")
|
|
141
|
+
.select(["queue", "job_name", "job_id", "org_id", "attempts", "last_error"])
|
|
142
|
+
.where("id", "=", id)
|
|
143
|
+
.where("dead_at", "is not", null)
|
|
144
|
+
.forUpdate()
|
|
145
|
+
.executeTakeFirst();
|
|
146
|
+
if (!row)
|
|
147
|
+
throw notFound(id);
|
|
148
|
+
return row;
|
|
149
|
+
}
|
|
150
|
+
/** A platform-level audit event (no org: the outbox is the deployment's), naming the job. */
|
|
151
|
+
audit(action, id, row, actor, detail) {
|
|
152
|
+
return audit(this.db.db, {
|
|
153
|
+
actorAccountId: actor.accountId,
|
|
154
|
+
...(actor.tokenId !== undefined && { actorTokenId: actor.tokenId }),
|
|
155
|
+
action,
|
|
156
|
+
target: id,
|
|
157
|
+
detail: {
|
|
158
|
+
queue: row.queue,
|
|
159
|
+
jobName: row.job_name,
|
|
160
|
+
jobId: row.job_id,
|
|
161
|
+
...(row.org_id !== null && { orgId: row.org_id }),
|
|
162
|
+
...detail,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
__decorate([
|
|
168
|
+
Transactional()
|
|
169
|
+
], OutboxDeadService.prototype, "retryOnce", null);
|
|
170
|
+
__decorate([
|
|
171
|
+
Transactional()
|
|
172
|
+
], OutboxDeadService.prototype, "discard", null);
|
|
173
|
+
OutboxDeadService = __decorate([
|
|
174
|
+
Injectable(),
|
|
175
|
+
__param(0, Inject(TransactionHost)),
|
|
176
|
+
__param(1, Inject(KernelDb)),
|
|
177
|
+
__param(2, Inject(OUTBOX_FAST_PATH))
|
|
178
|
+
], OutboxDeadService);
|
|
179
|
+
export { OutboxDeadService };
|