@capybara-hq/kernel 0.1.0-rc.1 → 0.1.0-rc.2
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/admin/admin.controller.d.ts +17 -17
- package/dist/admin/admin.controller.js +43 -26
- package/dist/admin/admin.module.d.ts +3 -0
- package/dist/admin/admin.module.js +22 -0
- package/dist/admin/extensions.controller.d.ts +14 -14
- package/dist/admin/extensions.controller.js +30 -17
- package/dist/admin/setup-lock.d.ts +16 -0
- package/dist/admin/setup-lock.js +47 -0
- package/dist/admin/setup.controller.d.ts +8 -8
- package/dist/admin/setup.controller.js +27 -25
- package/dist/admin/setup.service.d.ts +19 -27
- package/dist/admin/setup.service.js +61 -61
- package/dist/agents/agent-lookup.d.ts +53 -0
- package/dist/agents/agent-lookup.js +179 -0
- package/dist/agents/agents.controller.d.ts +1 -1
- package/dist/agents/agents.controller.js +14 -8
- package/dist/agents/agents.module.d.ts +7 -0
- package/dist/agents/agents.module.js +41 -0
- package/dist/agents/agents.service.d.ts +39 -58
- package/dist/agents/agents.service.js +261 -329
- package/dist/agents/definition.d.ts +8 -0
- package/dist/agents/definition.js +8 -0
- package/dist/agents/models.controller.d.ts +1 -1
- package/dist/agents/models.controller.js +2 -2
- package/dist/agents/templates.controller.d.ts +1 -1
- package/dist/agents/templates.controller.js +2 -2
- package/dist/agents/templates.d.ts +6 -8
- package/dist/agents/templates.js +20 -4
- package/dist/app.d.ts +93 -0
- package/dist/app.js +150 -0
- package/dist/catalog/admin-catalog.controller.d.ts +3 -3
- package/dist/catalog/admin-catalog.controller.js +27 -13
- package/dist/catalog/catalog-content.d.ts +185 -0
- package/dist/catalog/catalog-content.js +323 -0
- package/dist/catalog/catalog-items.d.ts +186 -0
- package/dist/catalog/catalog-items.js +410 -0
- package/dist/catalog/catalog.module.d.ts +14 -0
- package/dist/catalog/catalog.module.js +71 -0
- package/dist/catalog/catalog.service.d.ts +34 -188
- package/dist/catalog/catalog.service.js +155 -489
- package/dist/catalog/cli.d.ts +3 -2
- package/dist/catalog/cli.js +13 -31
- package/dist/catalog/job-ids.d.ts +15 -0
- package/dist/catalog/job-ids.js +15 -0
- package/dist/catalog/jobs.d.ts +27 -0
- package/dist/catalog/jobs.js +70 -0
- package/dist/catalog/locks.d.ts +24 -0
- package/dist/catalog/locks.js +63 -0
- package/dist/catalog/marketplaces.controller.d.ts +4 -4
- package/dist/catalog/marketplaces.controller.js +22 -11
- package/dist/catalog/marketplaces.service.d.ts +30 -13
- package/dist/catalog/marketplaces.service.js +330 -256
- package/dist/catalog/org-catalog.controller.d.ts +4 -3
- package/dist/catalog/org-catalog.controller.js +29 -14
- package/dist/catalog/org-catalog.service.d.ts +32 -198
- package/dist/catalog/org-catalog.service.js +159 -400
- package/dist/catalog/plugin-import.d.ts +73 -34
- package/dist/catalog/plugin-import.js +356 -217
- package/dist/catalog/plugin-install.d.ts +83 -41
- package/dist/catalog/plugin-install.js +421 -269
- package/dist/catalog/plugin-upgrade.d.ts +59 -4
- package/dist/catalog/plugin-upgrade.js +407 -282
- package/dist/catalog/requests.service.d.ts +27 -15
- package/dist/catalog/requests.service.js +201 -145
- package/dist/catalog/upgrade-targets.d.ts +4 -7
- package/dist/channels/actions.d.ts +6 -4
- package/dist/channels/actions.js +1 -1
- package/dist/channels/cards.d.ts +2 -2
- package/dist/channels/channels.module.d.ts +40 -0
- package/dist/channels/channels.module.js +128 -0
- package/dist/channels/connections.controller.d.ts +1 -1
- package/dist/channels/connections.controller.js +11 -6
- package/dist/channels/connections.service.d.ts +43 -21
- package/dist/channels/connections.service.js +236 -131
- package/dist/channels/inbound.d.ts +34 -38
- package/dist/channels/inbound.js +107 -41
- package/dist/channels/job-ids.d.ts +10 -0
- package/dist/channels/job-ids.js +10 -0
- package/dist/channels/jobs.d.ts +85 -0
- package/dist/channels/jobs.js +157 -0
- package/dist/channels/outbound.d.ts +60 -82
- package/dist/channels/outbound.js +165 -194
- package/dist/channels/supervisor.d.ts +88 -46
- package/dist/channels/supervisor.js +230 -132
- package/dist/channels/threads.d.ts +29 -8
- package/dist/channels/threads.js +71 -13
- package/dist/channels/webhook.d.ts +20 -14
- package/dist/channels/webhook.js +51 -20
- package/dist/config/load.d.ts +3 -2
- package/dist/config/load.js +3 -2
- package/dist/config/nacos-source.js +11 -2
- package/dist/config/schema.d.ts +1 -0
- package/dist/config/schema.js +10 -4
- package/dist/conversations/access.d.ts +29 -0
- package/dist/conversations/access.js +86 -0
- package/dist/conversations/artifacts.d.ts +10 -10
- package/dist/conversations/artifacts.js +35 -9
- package/dist/conversations/attachments.controller.d.ts +1 -1
- package/dist/conversations/attachments.controller.js +8 -6
- package/dist/conversations/attachments.module.d.ts +7 -0
- package/dist/conversations/attachments.module.js +25 -0
- package/dist/conversations/attachments.service.d.ts +30 -22
- package/dist/conversations/attachments.service.js +119 -46
- package/dist/conversations/conversations.controller.d.ts +8 -7
- package/dist/conversations/conversations.controller.js +59 -29
- package/dist/conversations/conversations.module.d.ts +8 -0
- package/dist/conversations/conversations.module.js +69 -0
- package/dist/conversations/conversations.service.d.ts +40 -38
- package/dist/conversations/conversations.service.js +130 -140
- package/dist/conversations/event-log.d.ts +28 -18
- package/dist/conversations/event-log.js +74 -27
- package/dist/conversations/files.d.ts +10 -10
- package/dist/conversations/files.js +37 -11
- package/dist/conversations/idem-keys.d.ts +5 -0
- package/dist/conversations/idem-keys.js +5 -0
- package/dist/conversations/job-ids.d.ts +6 -0
- package/dist/conversations/job-ids.js +6 -0
- package/dist/conversations/outputs-read.d.ts +11 -11
- package/dist/conversations/outputs-read.js +31 -7
- package/dist/conversations/queue.d.ts +48 -56
- package/dist/conversations/queue.js +13 -289
- package/dist/conversations/queue.service.d.ts +60 -0
- package/dist/conversations/queue.service.js +343 -0
- package/dist/conversations/sandbox-status.d.ts +13 -10
- package/dist/conversations/sandbox-status.js +36 -8
- package/dist/conversations/titles.d.ts +71 -24
- package/dist/conversations/titles.js +159 -63
- package/dist/ctx/bus.js +9 -3
- package/dist/ctx/create-ctx.d.ts +6 -0
- package/dist/ctx/create-ctx.js +7 -9
- package/dist/ctx/lock.d.ts +7 -3
- package/dist/ctx/lock.js +9 -20
- package/dist/ctx/secrets.d.ts +10 -2
- package/dist/ctx/secrets.js +7 -3
- package/dist/db/kernel-schema.d.ts +2 -2
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +1 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.js +1 -0
- package/dist/evals/budget.d.ts +42 -21
- package/dist/evals/budget.js +114 -62
- package/dist/evals/evals.module.d.ts +31 -0
- package/dist/evals/evals.module.js +114 -0
- package/dist/evals/jobs.d.ts +20 -0
- package/dist/evals/jobs.js +45 -0
- package/dist/evals/run-replay.d.ts +56 -8
- package/dist/evals/run-replay.js +140 -80
- package/dist/evals/runs.controller.d.ts +1 -1
- package/dist/evals/runs.controller.js +17 -8
- package/dist/evals/runs.service.d.ts +23 -45
- package/dist/evals/runs.service.js +245 -234
- package/dist/evals/sets.controller.d.ts +1 -1
- package/dist/evals/sets.controller.js +17 -8
- package/dist/evals/sets.service.d.ts +22 -6
- package/dist/evals/sets.service.js +248 -194
- package/dist/evals/snapshot.d.ts +2 -2
- package/dist/evals/step-replay.d.ts +2 -2
- package/dist/evals/step-replay.js +1 -1
- package/dist/evals/trajectory.controller.d.ts +1 -1
- package/dist/evals/trajectory.controller.js +11 -7
- package/dist/evals/trajectory.service.d.ts +5 -4
- package/dist/evals/trajectory.service.js +30 -7
- package/dist/evals/worker.d.ts +44 -27
- package/dist/evals/worker.js +220 -121
- package/dist/extensions/admin-ops.d.ts +61 -33
- package/dist/extensions/admin-ops.js +248 -154
- package/dist/extensions/admin-view.d.ts +38 -27
- package/dist/extensions/admin-view.js +126 -55
- package/dist/extensions/approvals.d.ts +12 -8
- package/dist/extensions/approvals.js +73 -46
- package/dist/extensions/blobs.d.ts +27 -10
- package/dist/extensions/blobs.js +111 -45
- package/dist/extensions/bootstrap.d.ts +58 -31
- package/dist/extensions/bootstrap.js +175 -121
- package/dist/extensions/cli.d.ts +20 -10
- package/dist/extensions/cli.js +41 -96
- package/dist/extensions/config-issues.d.ts +7 -0
- package/dist/extensions/config-issues.js +31 -0
- package/dist/extensions/deployment-config-store.d.ts +49 -0
- package/dist/extensions/deployment-config-store.js +133 -0
- package/dist/extensions/deployment-config.d.ts +58 -67
- package/dist/extensions/deployment-config.js +202 -230
- package/dist/extensions/enabled.d.ts +5 -5
- package/dist/extensions/extensions.module.d.ts +8 -0
- package/dist/extensions/extensions.module.js +77 -0
- package/dist/extensions/hooks.d.ts +3 -2
- package/dist/extensions/hooks.js +1 -1
- package/dist/extensions/host.d.ts +72 -68
- package/dist/extensions/host.js +191 -152
- package/dist/extensions/installs.d.ts +49 -16
- package/dist/extensions/installs.js +128 -32
- package/dist/extensions/job-ids.d.ts +6 -0
- package/dist/extensions/job-ids.js +6 -0
- package/dist/extensions/lifecycle-topics.d.ts +18 -0
- package/dist/extensions/lifecycle-topics.js +18 -0
- package/dist/extensions/lifecycle.d.ts +35 -47
- package/dist/extensions/lifecycle.js +103 -39
- package/dist/extensions/locks.d.ts +33 -0
- package/dist/extensions/locks.js +86 -0
- package/dist/extensions/migrate-lock.d.ts +3 -4
- package/dist/extensions/org-config.controller.d.ts +1 -1
- package/dist/extensions/org-config.controller.js +8 -5
- package/dist/extensions/org-config.d.ts +48 -46
- package/dist/extensions/org-config.js +284 -226
- package/dist/extensions/registry.d.ts +50 -2
- package/dist/extensions/registry.js +89 -4
- package/dist/extensions/sources.d.ts +12 -8
- package/dist/extensions/sources.js +34 -13
- package/dist/files/files.module.d.ts +3 -0
- package/dist/files/files.module.js +22 -0
- package/dist/files/previewers.controller.d.ts +7 -2
- package/dist/files/previewers.controller.js +17 -9
- package/dist/files/previewers.d.ts +13 -18
- package/dist/files/previewers.js +83 -36
- package/dist/http/adapter.d.ts +3 -0
- package/dist/http/adapter.js +25 -0
- package/dist/http/api.module.d.ts +3 -110
- package/dist/http/api.module.js +47 -355
- package/dist/http/app.d.ts +11 -15
- package/dist/http/app.js +17 -62
- package/dist/http/error-filter.module.d.ts +5 -0
- package/dist/http/error-filter.module.js +18 -0
- package/dist/http/error.filter.js +2 -2
- package/dist/identity/accounts.d.ts +82 -29
- package/dist/identity/accounts.js +294 -175
- package/dist/identity/api-tokens.d.ts +11 -7
- package/dist/identity/api-tokens.js +71 -44
- package/dist/identity/audit.d.ts +7 -4
- package/dist/identity/audit.js +5 -1
- package/dist/identity/auth.controller.d.ts +11 -10
- package/dist/identity/auth.controller.js +31 -25
- package/dist/identity/auth.guard.d.ts +3 -3
- package/dist/identity/auth.guard.js +6 -4
- package/dist/identity/binding.d.ts +9 -11
- package/dist/identity/binding.js +41 -13
- package/dist/identity/enterprise-admin.d.ts +18 -12
- package/dist/identity/enterprise-admin.js +67 -13
- package/dist/identity/external-identity-lock.d.ts +17 -0
- package/dist/identity/external-identity-lock.js +39 -0
- package/dist/identity/external.d.ts +19 -15
- package/dist/identity/external.js +163 -125
- package/dist/identity/identity.module.d.ts +6 -0
- package/dist/identity/identity.module.js +56 -0
- package/dist/identity/me.controller.d.ts +16 -15
- package/dist/identity/me.controller.js +37 -31
- package/dist/identity/sessions.d.ts +12 -10
- package/dist/identity/sessions.js +74 -42
- package/dist/identity/settings.d.ts +20 -14
- package/dist/identity/settings.js +85 -57
- package/dist/identity/sso.controller.d.ts +7 -7
- package/dist/identity/sso.controller.js +13 -9
- package/dist/identity/sso.d.ts +9 -12
- package/dist/identity/sso.js +54 -24
- package/dist/inbox/inbox.module.d.ts +3 -0
- package/dist/inbox/inbox.module.js +22 -0
- package/dist/inbox/inbox.service.d.ts +7 -9
- package/dist/inbox/inbox.service.js +32 -11
- package/dist/index.d.ts +16 -11
- package/dist/index.js +9 -6
- package/dist/infra/cache/cache.module.d.ts +3 -0
- package/dist/infra/cache/cache.module.js +16 -0
- package/dist/infra/cache/cache.service.d.ts +21 -0
- package/dist/infra/cache/cache.service.js +80 -0
- package/dist/infra/cache/cacheable.decorator.d.ts +32 -0
- package/dist/infra/cache/cacheable.decorator.js +83 -0
- package/dist/infra/cli/kernel-cli.module.d.ts +66 -0
- package/dist/infra/cli/kernel-cli.module.js +165 -0
- package/dist/infra/close-within.d.ts +15 -0
- package/dist/infra/close-within.js +36 -0
- package/dist/infra/config/config.module.d.ts +13 -0
- package/dist/infra/config/config.module.js +39 -0
- package/dist/infra/config/kernel-config.service.d.ts +25 -0
- package/dist/infra/config/kernel-config.service.js +126 -0
- package/dist/infra/database/after-commit.d.ts +6 -0
- package/dist/infra/database/after-commit.js +9 -0
- package/dist/infra/database/database.module.d.ts +25 -0
- package/dist/infra/database/database.module.js +90 -0
- package/dist/infra/database/kernel-db.d.ts +22 -0
- package/dist/infra/database/kernel-db.js +65 -0
- package/dist/infra/database/transaction-host.d.ts +50 -0
- package/dist/infra/database/transaction-host.js +125 -0
- package/dist/infra/database/transactional.decorator.d.ts +15 -0
- package/dist/infra/database/transactional.decorator.js +27 -0
- package/dist/infra/database/xact-lock.d.ts +17 -0
- package/dist/infra/database/xact-lock.js +43 -0
- package/dist/infra/events/kernel-events.d.ts +96 -0
- package/dist/infra/events/kernel-events.js +65 -0
- package/dist/infra/health/health.controller.d.ts +26 -0
- package/dist/infra/health/health.controller.js +104 -0
- package/dist/infra/health/health.module.d.ts +9 -0
- package/dist/infra/health/health.module.js +24 -0
- package/dist/infra/health/health.options.d.ts +10 -0
- package/dist/infra/health/health.options.js +15 -0
- package/dist/infra/health/shutdown-state.d.ts +6 -0
- package/dist/infra/health/shutdown-state.js +2 -0
- package/dist/infra/lifecycle/graceful-shutdown.module.d.ts +6 -0
- package/dist/infra/lifecycle/graceful-shutdown.module.js +23 -0
- package/dist/infra/lifecycle/graceful-shutdown.service.d.ts +70 -0
- package/dist/infra/lifecycle/graceful-shutdown.service.js +135 -0
- package/dist/infra/lifecycle/process-guards.d.ts +52 -0
- package/dist/infra/lifecycle/process-guards.js +86 -0
- package/dist/infra/lifecycle/shutdown-signals.d.ts +30 -0
- package/dist/infra/lifecycle/shutdown-signals.js +48 -0
- package/dist/infra/lock/key-template.d.ts +13 -0
- package/dist/infra/lock/key-template.js +46 -0
- package/dist/infra/lock/lock.module.d.ts +3 -0
- package/dist/infra/lock/lock.module.js +16 -0
- package/dist/infra/lock/lock.service.d.ts +120 -0
- package/dist/infra/lock/lock.service.js +343 -0
- package/dist/infra/lock/shared-lease.d.ts +44 -0
- package/dist/infra/lock/shared-lease.js +121 -0
- package/dist/infra/lock/with-lock.decorator.d.ts +28 -0
- package/dist/infra/lock/with-lock.decorator.js +49 -0
- package/dist/infra/logging/logging.module.d.ts +16 -0
- package/dist/infra/logging/logging.module.js +34 -0
- package/dist/infra/queue/configured-processor.d.ts +18 -0
- package/dist/infra/queue/configured-processor.js +23 -0
- package/dist/infra/queue/job-failure.d.ts +18 -0
- package/dist/infra/queue/job-failure.js +26 -0
- package/dist/infra/queue/queue-shutdown.d.ts +27 -0
- package/dist/infra/queue/queue-shutdown.js +81 -0
- package/dist/infra/queue/queue.module.d.ts +16 -0
- package/dist/infra/queue/queue.module.js +61 -0
- package/dist/infra/queue/redis-connection.d.ts +7 -0
- package/dist/infra/queue/redis-connection.js +18 -0
- package/dist/infra/queue/retired-schedulers.d.ts +7 -0
- package/dist/infra/queue/retired-schedulers.js +9 -0
- package/dist/infra/queue/run-job.d.ts +16 -0
- package/dist/infra/queue/run-job.js +19 -0
- package/dist/infra/redis/redis.module.d.ts +24 -0
- package/dist/infra/redis/redis.module.js +87 -0
- package/dist/infra/schedule/cron-tick.d.ts +12 -0
- package/dist/infra/schedule/cron-tick.js +25 -0
- package/dist/infra/schedule/locked-cron.decorator.d.ts +27 -0
- package/dist/infra/schedule/locked-cron.decorator.js +53 -0
- package/dist/infra/schedule/locked-interval.d.ts +69 -0
- package/dist/infra/schedule/locked-interval.js +190 -0
- package/dist/infra/schedule/locked-tick.d.ts +90 -0
- package/dist/infra/schedule/locked-tick.js +137 -0
- package/dist/infra/schedule/schedule.module.d.ts +8 -0
- package/dist/infra/schedule/schedule.module.js +27 -0
- package/dist/infra/schedule/scheduled-runs.d.ts +69 -0
- package/dist/infra/schedule/scheduled-runs.js +163 -0
- package/dist/infra/swagger/swagger.d.ts +16 -0
- package/dist/infra/swagger/swagger.js +31 -0
- package/dist/infra/throttler/credential-throttler.d.ts +35 -0
- package/dist/infra/throttler/credential-throttler.js +77 -0
- package/dist/infra/throttler/named-throttlers.d.ts +31 -0
- package/dist/infra/throttler/named-throttlers.js +119 -0
- package/dist/infra/throttler/redis-throttler-storage.d.ts +38 -0
- package/dist/infra/throttler/redis-throttler-storage.js +130 -0
- package/dist/infra/throttler/throttler.guard.d.ts +23 -0
- package/dist/infra/throttler/throttler.guard.js +68 -0
- package/dist/infra/throttler/throttler.module.d.ts +15 -0
- package/dist/infra/throttler/throttler.module.js +53 -0
- package/dist/infra/tokens.d.ts +15 -0
- package/dist/infra/tokens.js +15 -0
- package/dist/infra/validation/create-zod-dto.d.ts +23 -0
- package/dist/infra/validation/create-zod-dto.js +35 -0
- package/dist/infra/validation/parse-with-zod.d.ts +7 -0
- package/dist/infra/validation/parse-with-zod.js +12 -0
- package/dist/infra/validation/validation.module.d.ts +3 -0
- package/dist/infra/validation/validation.module.js +16 -0
- package/dist/infra/validation/zod-params.d.ts +7 -0
- package/dist/infra/validation/zod-params.js +42 -0
- package/dist/infra/validation/zod-validation.pipe.d.ts +11 -0
- package/dist/infra/validation/zod-validation.pipe.js +31 -0
- package/dist/kernel.d.ts +9 -244
- package/dist/kernel.js +8 -1305
- package/dist/kernel.module.d.ts +17 -0
- package/dist/kernel.module.js +136 -0
- package/dist/lifecycle/kernel-lifecycle.d.ts +140 -0
- package/dist/lifecycle/kernel-lifecycle.js +451 -0
- package/dist/lifecycle/tokens.d.ts +3 -0
- package/dist/lifecycle/tokens.js +3 -0
- package/dist/log-context.d.ts +2 -0
- package/dist/log-context.js +4 -0
- package/dist/models/models.module.d.ts +3 -0
- package/dist/models/models.module.js +24 -0
- package/dist/models/prices.d.ts +8 -2
- package/dist/models/prices.js +65 -37
- package/dist/models/purposes.controller.d.ts +1 -1
- package/dist/models/purposes.controller.js +5 -6
- package/dist/models/purposes.d.ts +35 -13
- package/dist/models/purposes.js +101 -51
- package/dist/orgs/directory-sync.controller.d.ts +1 -1
- package/dist/orgs/directory-sync.controller.js +2 -2
- package/dist/orgs/directory-sync.d.ts +61 -31
- package/dist/orgs/directory-sync.js +212 -125
- package/dist/orgs/invitations.controller.d.ts +8 -8
- package/dist/orgs/invitations.controller.js +27 -26
- package/dist/orgs/invitations.service.d.ts +12 -9
- package/dist/orgs/invitations.service.js +130 -92
- package/dist/orgs/job-ids.d.ts +8 -0
- package/dist/orgs/job-ids.js +8 -0
- package/dist/orgs/members.service.d.ts +19 -12
- package/dist/orgs/members.service.js +161 -117
- package/dist/orgs/offboarding.d.ts +54 -57
- package/dist/orgs/offboarding.js +161 -71
- package/dist/orgs/org-lock.d.ts +28 -19
- package/dist/orgs/org-lock.js +81 -35
- package/dist/orgs/org.guard.d.ts +1 -1
- package/dist/orgs/org.guard.js +2 -2
- package/dist/orgs/orgs.controller.d.ts +13 -13
- package/dist/orgs/orgs.controller.js +29 -17
- package/dist/orgs/orgs.module.d.ts +6 -0
- package/dist/orgs/orgs.module.js +68 -0
- package/dist/orgs/orgs.service.d.ts +30 -19
- package/dist/orgs/orgs.service.js +139 -86
- package/dist/orgs/settings.controller.d.ts +1 -1
- package/dist/orgs/settings.controller.js +8 -6
- package/dist/orgs/settings.service.d.ts +14 -8
- package/dist/orgs/settings.service.js +75 -46
- package/dist/overrides.d.ts +56 -0
- package/dist/overrides.js +30 -0
- package/dist/roles/gateway-role.d.ts +43 -0
- package/dist/roles/gateway-role.js +98 -0
- package/dist/roles/gateway.module.d.ts +8 -0
- package/dist/roles/gateway.module.js +28 -0
- package/dist/roles/worker-role.d.ts +63 -0
- package/dist/roles/worker-role.js +144 -0
- package/dist/roles/worker.module.d.ts +14 -0
- package/dist/roles/worker.module.js +90 -0
- package/dist/runtime/abort.js +19 -2
- package/dist/runtime/checkpointer.d.ts +8 -3
- package/dist/runtime/checkpointer.js +87 -55
- package/dist/runtime/conversation-lock.d.ts +20 -11
- package/dist/runtime/conversation-lock.js +62 -72
- package/dist/runtime/hook-calls.d.ts +3 -3
- package/dist/runtime/hook-calls.js +1 -6
- package/dist/runtime/job-ids.d.ts +10 -0
- package/dist/runtime/job-ids.js +10 -0
- package/dist/runtime/langgraph-loop.js +1 -1
- package/dist/runtime/loop.d.ts +7 -0
- package/dist/runtime/loop.js +14 -0
- package/dist/runtime/maintenance-queue.d.ts +10 -0
- package/dist/runtime/maintenance-queue.js +10 -0
- package/dist/runtime/maintenance.d.ts +45 -74
- package/dist/runtime/maintenance.js +139 -137
- package/dist/runtime/model-call.d.ts +7 -4
- package/dist/runtime/model-call.js +24 -57
- package/dist/runtime/providers.d.ts +17 -6
- package/dist/runtime/providers.js +66 -25
- package/dist/runtime/quota.d.ts +17 -3
- package/dist/runtime/quota.js +27 -2
- package/dist/runtime/retired-schedulers.d.ts +7 -0
- package/dist/runtime/retired-schedulers.js +31 -0
- package/dist/runtime/run-control.d.ts +33 -0
- package/dist/runtime/run-control.js +77 -0
- package/dist/runtime/run-finish.d.ts +26 -17
- package/dist/runtime/run-finish.js +98 -51
- package/dist/runtime/run-jobs.d.ts +48 -0
- package/dist/runtime/run-jobs.js +95 -0
- package/dist/runtime/run-processors.d.ts +60 -0
- package/dist/runtime/run-processors.js +185 -0
- package/dist/runtime/run-queue.d.ts +32 -57
- package/dist/runtime/run-queue.js +291 -295
- package/dist/runtime/run-steps.d.ts +39 -0
- package/dist/runtime/run-steps.js +96 -0
- package/dist/runtime/run-worker.d.ts +121 -75
- package/dist/runtime/run-worker.js +340 -226
- package/dist/runtime/runtime.module.d.ts +10 -0
- package/dist/runtime/runtime.module.js +112 -0
- package/dist/runtime/step-log.d.ts +40 -0
- package/dist/runtime/step-log.js +94 -0
- package/dist/runtime/stream.controller.d.ts +5 -8
- package/dist/runtime/stream.controller.js +14 -12
- package/dist/runtime/stream.d.ts +24 -6
- package/dist/runtime/stream.js +78 -7
- package/dist/runtime/subagents/child.d.ts +3 -44
- package/dist/runtime/subagents/child.js +0 -79
- package/dist/runtime/subagents/definition.d.ts +4 -4
- package/dist/runtime/subagents/definition.js +2 -2
- package/dist/runtime/subagents/dispatch.d.ts +87 -6
- package/dist/runtime/subagents/dispatch.js +135 -140
- package/dist/runtime/subagents/limits.d.ts +9 -4
- package/dist/runtime/subagents/limits.js +4 -2
- package/dist/runtime/subagents/org-agents.d.ts +4 -4
- package/dist/runtime/subagents/org-agents.js +1 -1
- package/dist/runtime/subagents/progress.d.ts +2 -2
- package/dist/runtime/subagents/roster.d.ts +3 -3
- package/dist/runtime/subagents/roster.js +1 -1
- package/dist/runtime/subagents/skill-fork.d.ts +6 -7
- package/dist/runtime/subagents/skill-fork.js +16 -5
- package/dist/runtime/subagents/subagents.service.d.ts +40 -0
- package/dist/runtime/subagents/subagents.service.js +101 -0
- package/dist/runtime/usage-report.d.ts +94 -52
- package/dist/runtime/usage-report.js +200 -100
- package/dist/runtime/waits.d.ts +125 -57
- package/dist/runtime/waits.js +431 -208
- package/dist/sandbox/job-ids.d.ts +10 -0
- package/dist/sandbox/job-ids.js +10 -0
- package/dist/sandbox/jobs.d.ts +41 -0
- package/dist/sandbox/jobs.js +113 -0
- package/dist/sandbox/leases.d.ts +39 -31
- package/dist/sandbox/leases.js +117 -257
- package/dist/sandbox/providers.d.ts +19 -0
- package/dist/sandbox/providers.js +38 -0
- package/dist/sandbox/sandbox.module.d.ts +8 -0
- package/dist/sandbox/sandbox.module.js +30 -0
- package/dist/sandbox/sandbox.service.d.ts +24 -29
- package/dist/sandbox/sandbox.service.js +106 -75
- package/dist/skills/catalog.d.ts +33 -20
- package/dist/skills/catalog.js +96 -53
- package/dist/skills/changes.controller.d.ts +4 -4
- package/dist/skills/changes.controller.js +15 -9
- package/dist/skills/changes.service.d.ts +28 -18
- package/dist/skills/changes.service.js +421 -364
- package/dist/skills/invocable.controller.d.ts +1 -1
- package/dist/skills/invocable.controller.js +8 -5
- package/dist/skills/invoke.d.ts +16 -15
- package/dist/skills/invoke.js +48 -17
- package/dist/skills/skills.controller.d.ts +1 -1
- package/dist/skills/skills.controller.js +11 -6
- package/dist/skills/skills.module.d.ts +6 -0
- package/dist/skills/skills.module.js +30 -0
- package/dist/skills/skills.service.d.ts +47 -30
- package/dist/skills/skills.service.js +221 -158
- package/dist/storage/job-ids.d.ts +6 -0
- package/dist/storage/job-ids.js +6 -0
- package/dist/storage/purge.d.ts +22 -7
- package/dist/storage/purge.js +55 -3
- package/dist/storage/storage.module.d.ts +6 -0
- package/dist/storage/storage.module.js +23 -0
- package/dist/storage/storage.service.d.ts +18 -4
- package/dist/storage/storage.service.js +44 -3
- package/dist/tools/approvals.controller.d.ts +1 -1
- package/dist/tools/approvals.controller.js +12 -8
- package/dist/tools/approvals.service.d.ts +27 -25
- package/dist/tools/approvals.service.js +324 -258
- package/dist/tools/breaker.d.ts +2 -2
- package/dist/tools/breaker.js +21 -3
- package/dist/tools/builtins/ask-user.d.ts +2 -2
- package/dist/tools/builtins/ask-user.js +1 -1
- package/dist/tools/builtins/builtin-tools.d.ts +21 -0
- package/dist/tools/builtins/builtin-tools.js +80 -0
- package/dist/tools/builtins/read-tool-output.d.ts +2 -2
- package/dist/tools/builtins/read-tool-output.js +1 -1
- package/dist/tools/builtins/sandbox/bash.js +2 -2
- package/dist/tools/builtins/sandbox/common.d.ts +2 -1
- package/dist/tools/builtins/sandbox/deliver.js +2 -2
- package/dist/tools/builtins/sandbox/edit.js +1 -1
- package/dist/tools/builtins/sandbox/glob.js +2 -2
- package/dist/tools/builtins/sandbox/grep.js +2 -2
- package/dist/tools/builtins/sandbox/read.js +1 -1
- package/dist/tools/builtins/sandbox/write.js +1 -1
- package/dist/tools/builtins/skill-load.d.ts +3 -3
- package/dist/tools/builtins/skill-load.js +1 -1
- package/dist/tools/canonical-json.d.ts +6 -0
- package/dist/tools/canonical-json.js +16 -0
- package/dist/tools/connector-content.controller.d.ts +1 -1
- package/dist/tools/connector-content.controller.js +11 -6
- package/dist/tools/connector-content.d.ts +12 -15
- package/dist/tools/connector-content.js +53 -18
- package/dist/tools/connectors.controller.d.ts +1 -1
- package/dist/tools/connectors.controller.js +21 -10
- package/dist/tools/connectors.service.d.ts +31 -13
- package/dist/tools/connectors.service.js +434 -344
- package/dist/tools/credentials.d.ts +17 -20
- package/dist/tools/credentials.js +55 -34
- package/dist/tools/drift.d.ts +29 -41
- package/dist/tools/drift.js +111 -79
- package/dist/tools/info.d.ts +12 -9
- package/dist/tools/info.js +33 -7
- package/dist/tools/job-ids.d.ts +13 -0
- package/dist/tools/job-ids.js +15 -0
- package/dist/tools/jobs.d.ts +24 -0
- package/dist/tools/jobs.js +69 -0
- package/dist/tools/oauth/flow-paths.d.ts +16 -0
- package/dist/tools/oauth/flow-paths.js +38 -0
- package/dist/tools/oauth/flow.d.ts +30 -30
- package/dist/tools/oauth/flow.js +109 -81
- package/dist/tools/oauth/oauth.controller.d.ts +3 -3
- package/dist/tools/oauth/oauth.controller.js +12 -9
- package/dist/tools/oauth/tokens.d.ts +11 -3
- package/dist/tools/oauth/tokens.js +15 -14
- package/dist/tools/outputs.d.ts +13 -4
- package/dist/tools/outputs.js +47 -3
- package/dist/tools/pipeline.d.ts +62 -46
- package/dist/tools/pipeline.js +145 -64
- package/dist/tools/policy.d.ts +2 -2
- package/dist/tools/questions.controller.d.ts +1 -1
- package/dist/tools/questions.controller.js +8 -5
- package/dist/tools/questions.service.d.ts +25 -24
- package/dist/tools/questions.service.js +201 -142
- package/dist/tools/registry.d.ts +30 -20
- package/dist/tools/registry.js +73 -37
- package/dist/tools/specs.d.ts +5 -4
- package/dist/tools/specs.js +3 -1
- package/dist/tools/tools.module.d.ts +10 -0
- package/dist/tools/tools.module.js +91 -0
- package/dist/ui/call-extension.d.ts +16 -0
- package/dist/ui/call-extension.js +38 -0
- package/dist/ui/embed-token.d.ts +9 -5
- package/dist/ui/embed-token.js +34 -6
- package/dist/ui/ui-stream.d.ts +22 -17
- package/dist/ui/ui-stream.js +72 -12
- package/dist/ui/ui.module.d.ts +7 -0
- package/dist/ui/ui.module.js +28 -0
- package/dist/ui/views.controller.d.ts +14 -12
- package/dist/ui/views.controller.js +32 -25
- package/dist/ui/views.d.ts +9 -57
- package/dist/ui/views.js +43 -45
- package/package.json +9 -2
- package/dist/http/health.controller.d.ts +0 -26
- package/dist/http/health.controller.js +0 -79
- package/dist/http/tokens.d.ts +0 -131
- package/dist/http/tokens.js +0 -131
- package/dist/http/zod.pipe.d.ts +0 -8
- package/dist/http/zod.pipe.js +0 -14
- package/dist/identity/rate-limit.d.ts +0 -55
- package/dist/identity/rate-limit.js +0 -121
- package/dist/sandbox/lifecycle.d.ts +0 -21
- package/dist/sandbox/lifecycle.js +0 -68
- /package/dist/http/{gateway.module.d.ts → gateway-routes.d.ts} +0 -0
- /package/dist/http/{gateway.module.js → gateway-routes.js} +0 -0
|
@@ -1,8 +1,28 @@
|
|
|
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
|
+
};
|
|
1
10
|
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { CHANNEL_EXTENSION_POINT, } from "@capybara-hq/plugin-sdk";
|
|
12
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
2
13
|
import { secretValues } from "../config/fields.js";
|
|
3
14
|
import { enabledExtensionsByOrg } from "../extensions/enabled.js";
|
|
15
|
+
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
16
|
+
import { ReplicaStatusStore } from "../extensions/sources.js";
|
|
17
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
18
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
19
|
+
import { LockService } from "../infra/lock/lock.service.js";
|
|
20
|
+
import { LockedCron } from "../infra/schedule/locked-cron.decorator.js";
|
|
21
|
+
import { KERNEL_BUS, KERNEL_LOGGER, REDIS } from "../infra/tokens.js";
|
|
4
22
|
import { createRedactor } from "../log.js";
|
|
5
|
-
import { CHANNEL_CHANGED_TOPIC, channelBackoffKey, channelFailsKey, } from "./connections.service.js";
|
|
23
|
+
import { CHANNEL_CHANGED_TOPIC, ChannelConnections, channelBackoffKey, channelFailsKey, } from "./connections.service.js";
|
|
24
|
+
import { ChannelInbound } from "./inbound.js";
|
|
25
|
+
import { GATEWAY_CHECK_JOB } from "./job-ids.js";
|
|
6
26
|
/** 长连接租约键(内核锁):值为持有方的随机 token。 */
|
|
7
27
|
export const channelLeaseKey = (connectionId) => `capk:channel-lease:${connectionId}`;
|
|
8
28
|
/**
|
|
@@ -43,12 +63,6 @@ const FAILS_TTL_SECONDS = 3600;
|
|
|
43
63
|
const SETTLE_MS = 5_000;
|
|
44
64
|
/** `last_error` 的最大长度。 */
|
|
45
65
|
const MAX_ERROR_CHARS = 1000;
|
|
46
|
-
const RENEW = `
|
|
47
|
-
if redis.call('GET', KEYS[1]) == ARGV[1] then
|
|
48
|
-
return redis.call('PEXPIRE', KEYS[1], ARGV[2])
|
|
49
|
-
end
|
|
50
|
-
return 0
|
|
51
|
-
`;
|
|
52
66
|
/**
|
|
53
67
|
* Heartbeat with the Redis server clock (replica wall clocks may drift): for each key, ZADD the
|
|
54
68
|
* member, trim members older than one TTL and refresh the key's expiry. KEYS = heartbeat keys to
|
|
@@ -92,39 +106,42 @@ export async function liveGateways(redis, plugins, ttlMs) {
|
|
|
92
106
|
});
|
|
93
107
|
return out;
|
|
94
108
|
}
|
|
95
|
-
const RELEASE = `
|
|
96
|
-
if redis.call('GET', KEYS[1]) == ARGV[1] then
|
|
97
|
-
return redis.call('DEL', KEYS[1])
|
|
98
|
-
end
|
|
99
|
-
return 0
|
|
100
|
-
`;
|
|
101
109
|
const errMsg = (e) => (e instanceof Error ? e.message : String(e));
|
|
102
110
|
/**
|
|
103
|
-
* 渠道长连接选主(runs only on the gateway role
|
|
104
|
-
*
|
|
105
|
-
*
|
|
111
|
+
* 渠道长连接选主(runs only on the gateway role: a provider of `GatewayModule`, started and stopped by
|
|
112
|
+
* `KernelLifecycle` through `GatewayRole` after the extension load)。每个副本两个各自独立的循环,周期都是 `channels.scanIntervalMs`(默认 10s):
|
|
113
|
+
* - 心跳循环:写本副本的 gateway 心跳,再为本进程持有的连接续一次租。它不做任何可能慢的事(不等交还、不查库),
|
|
114
|
+
* 一个插件迟迟不退出不会拖慢其他连接的续租。
|
|
106
115
|
* - 扫描循环:复核持有的连接仍为 active、未删除且插件在该组织启用(不满足就交还,交还不阻塞本轮),
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
116
|
+
* 再扫描无人持有的这类连接,取到租约(`LockService.hold`)的副本调用插件 `connect`(传 `signal`)。
|
|
117
|
+
* The lease `capk:channel-lease:<id>` (value: this replica's random token, TTL
|
|
118
|
+
* `channels.leaseTtlMs`, default 30 s) is renewed by `LockService` (every TTL/3, plus once in the
|
|
119
|
+
* heartbeat loop). A lost lease (overwritten or expired, or no successful renewal by the renewal
|
|
120
|
+
* deadline) aborts at once and is not released (it is no longer ours).
|
|
121
|
+
* 连接被停用 / 删除 / 改配置(内核 bus `channel.changed`,或扫描时复核发现)→ 中止、等 `connect` 返回后释放租约,下一轮任一副本按新配置重连;取得租约到 `connect` 开始之间
|
|
111
122
|
* 收到的重连广播会被记下,开始后立即交还。
|
|
112
123
|
* `connect` 抛错或提前返回 → 记 `last_error`,在 Redis 写退避标记(指数退避,上限 5 分钟),释放租约后由任一副本重试。
|
|
113
|
-
* Fair share (E11-B): the
|
|
124
|
+
* Fair share (E11-B): the heartbeat loop writes this replica's heartbeat into `capk:gateway-replicas`;
|
|
114
125
|
* each scan computes this replica's target from the runnable count and the live replicas
|
|
115
126
|
* (`shareTarget`), stops claiming at the target and, when above it, gives back one connection per
|
|
116
127
|
* round (the most recently connected) with a handoff marker. Exactly one holder per connection is
|
|
117
128
|
* still guaranteed by the lease alone; the share only decides who claims.
|
|
118
|
-
* 停机时中止全部长连接并释放租约,并等进行中的 `onEvent
|
|
129
|
+
* 停机时中止全部长连接并释放租约,并等进行中的 `onEvent`(入队)结束。持有的长连接、租约与定时器都是「本进程持有的资源」,
|
|
119
130
|
* 跨副本的状态(租约、退避、失败计数)都在 Redis。
|
|
120
131
|
*/
|
|
121
|
-
|
|
122
|
-
|
|
132
|
+
let ChannelSupervisor = class ChannelSupervisor {
|
|
133
|
+
db;
|
|
134
|
+
redis;
|
|
135
|
+
bus;
|
|
136
|
+
locks;
|
|
137
|
+
connections;
|
|
138
|
+
registry;
|
|
139
|
+
inbound;
|
|
140
|
+
config;
|
|
141
|
+
log;
|
|
123
142
|
held = new Map();
|
|
124
143
|
/** 已取得租约、正在读配置准备 `connect` 的连接;值为期间是否收到了重连广播。 */
|
|
125
144
|
connecting = new Map();
|
|
126
|
-
/** 正在交还(已中止、等 `connect` 返回)的连接 → 租约 token:等待期间照常续租,交还完成才释放。 */
|
|
127
|
-
settling = new Map();
|
|
128
145
|
/** 进行中的交还(`stop()` 要等它们全部结束)。 */
|
|
129
146
|
releasing = new Set();
|
|
130
147
|
/** 进行中的 `onEvent`(去重 + 入队,很快):`stop()` 等它们结束,插件才不会在内核关闭队列之后才拿到结果。 */
|
|
@@ -139,11 +156,38 @@ export class ChannelSupervisor {
|
|
|
139
156
|
heartbeated = new Set();
|
|
140
157
|
/** A claim-only scan is queued and has not started yet: further nudges until then are dropped. */
|
|
141
158
|
claimQueued = false;
|
|
142
|
-
|
|
143
|
-
|
|
159
|
+
/**
|
|
160
|
+
* This process's replica id (`ReplicaStatusStore.replicaId`), the member of the gateway heartbeat
|
|
161
|
+
* ZSET. Not `http.replicaId`, which is optional and may repeat across replicas.
|
|
162
|
+
*/
|
|
163
|
+
replicaId;
|
|
164
|
+
/** Called at the start of every scan round (`claimOnly` for handoff nudges); for tests / metrics. */
|
|
165
|
+
onScan;
|
|
166
|
+
constructor(db, redis, bus, locks, connections,
|
|
167
|
+
/** The channel extensions loaded in this process (`channel@1` providers). */
|
|
168
|
+
registry,
|
|
169
|
+
/** Events from a plugin's `connect` (dedupe and enqueue; ack after it resolves). */
|
|
170
|
+
inbound, config, log, replicaStatus) {
|
|
171
|
+
this.db = db;
|
|
172
|
+
this.redis = redis;
|
|
173
|
+
this.bus = bus;
|
|
174
|
+
this.locks = locks;
|
|
175
|
+
this.connections = connections;
|
|
176
|
+
this.registry = registry;
|
|
177
|
+
this.inbound = inbound;
|
|
178
|
+
this.config = config;
|
|
179
|
+
this.log = log;
|
|
180
|
+
this.replicaId = replicaStatus.replicaId;
|
|
181
|
+
}
|
|
182
|
+
/** 本进程已加载、提供 `channel@1` 的插件名。 */
|
|
183
|
+
localPlugins() {
|
|
184
|
+
return this.registry
|
|
185
|
+
.list("channel")
|
|
186
|
+
.filter((e) => e.capability === CHANNEL_EXTENSION_POINT)
|
|
187
|
+
.map((e) => e.plugin);
|
|
144
188
|
}
|
|
145
189
|
async start() {
|
|
146
|
-
this.unsubscribe = await this.
|
|
190
|
+
this.unsubscribe = await this.bus.subscribe(CHANNEL_CHANGED_TOPIC, (payload) => {
|
|
147
191
|
const m = payload;
|
|
148
192
|
const id = m?.connectionId;
|
|
149
193
|
if (m?.reconnect !== true || typeof id !== "string")
|
|
@@ -160,20 +204,20 @@ export class ChannelSupervisor {
|
|
|
160
204
|
// round. Claim only (no hand-back), so hand-backs stay at one per plugin per scan round.
|
|
161
205
|
// Nudges coalesce: at most one claim-only scan waits behind the one running; nudges for a
|
|
162
206
|
// plugin not loaded here are ignored.
|
|
163
|
-
this.unsubscribeHandoff = await this.
|
|
207
|
+
this.unsubscribeHandoff = await this.bus.subscribe(CHANNEL_HANDOFF_TOPIC, (payload) => {
|
|
164
208
|
const m = payload;
|
|
165
|
-
if (this.stopped || m?.replicaId === this.
|
|
209
|
+
if (this.stopped || m?.replicaId === this.replicaId || this.claimQueued)
|
|
166
210
|
return;
|
|
167
|
-
if (typeof m?.plugin !== "string" || !this.
|
|
211
|
+
if (typeof m?.plugin !== "string" || !this.localPlugins().includes(m.plugin))
|
|
168
212
|
return;
|
|
169
213
|
this.claimQueued = true;
|
|
170
214
|
const run = this.exclusive(() => {
|
|
171
215
|
this.claimQueued = false;
|
|
172
216
|
return this.scan(true);
|
|
173
217
|
});
|
|
174
|
-
this.track(run).catch((err) => this.
|
|
218
|
+
this.track(run).catch((err) => this.log.error("channel supervisor scan failed", { err }));
|
|
175
219
|
});
|
|
176
|
-
this.loop("
|
|
220
|
+
this.loop("heartbeat", () => this.heartbeatRound());
|
|
177
221
|
this.loop("scan", () => this.exclusive(async () => {
|
|
178
222
|
await this.recheckHeld();
|
|
179
223
|
if (!this.stopped)
|
|
@@ -195,40 +239,34 @@ export class ChannelSupervisor {
|
|
|
195
239
|
return;
|
|
196
240
|
st.timer = setTimeout(() => {
|
|
197
241
|
st.running = fn()
|
|
198
|
-
.catch((err) => this.
|
|
242
|
+
.catch((err) => this.log.error(`channel supervisor ${name} failed`, { err }))
|
|
199
243
|
.finally(() => {
|
|
200
244
|
st.running = undefined;
|
|
201
|
-
run(this.
|
|
245
|
+
run(this.config.get().channels.scanIntervalMs);
|
|
202
246
|
});
|
|
203
247
|
}, ms);
|
|
204
248
|
st.timer.unref?.();
|
|
205
249
|
};
|
|
206
250
|
run(0);
|
|
207
251
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
252
|
+
/**
|
|
253
|
+
* One heartbeat round: the heartbeat first, then one renewal of every lease held (on top of
|
|
254
|
+
* `LockService`'s own), so a crashed replica's heartbeat goes stale no later than its leases
|
|
255
|
+
* expire and the survivors' share already excludes it when those connections free up.
|
|
256
|
+
*/
|
|
257
|
+
async heartbeatRound() {
|
|
258
|
+
const ttl = this.config.get().channels.leaseTtlMs;
|
|
212
259
|
await this.heartbeat(ttl);
|
|
213
260
|
await Promise.all([...this.held].map(async ([id, h]) => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
this.
|
|
222
|
-
ok = Date.now() - h.renewedAt < ttl - scanIntervalMs;
|
|
223
|
-
if (ok)
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
await this.afterRenew(id, h, ok, ttl);
|
|
261
|
+
// false marks the lease lost (`lost` aborts, the connection drops); a Redis error is the
|
|
262
|
+
// watchdog's to log and judge (lost at the renewal deadline)
|
|
263
|
+
const ok = await h.lease.renew().catch(() => undefined);
|
|
264
|
+
if (ok === true)
|
|
265
|
+
await this.afterRenew(id, h, ttl);
|
|
266
|
+
// false: the key is gone or taken, or the lease was already lost (`drop` is idempotent)
|
|
267
|
+
else if (ok === false)
|
|
268
|
+
this.drop(id, h);
|
|
227
269
|
}));
|
|
228
|
-
// 交还中的连接:插件还没退出,租约不能在别的副本眼里过期(否则两边同时在线);续不上就算了(已不是自己的)
|
|
229
|
-
await Promise.all([...this.settling].map(([id, token]) => this.deps.redis.eval(RENEW, 1, channelLeaseKey(id), token, ttl).catch((err) => {
|
|
230
|
-
this.deps.log.warn("channel lease renew failed", { connectionId: id, err });
|
|
231
|
-
})));
|
|
232
270
|
}
|
|
233
271
|
/**
|
|
234
272
|
* Writes this replica's heartbeat into the ZSET of every channel plugin loaded here (trimming
|
|
@@ -238,16 +276,16 @@ export class ChannelSupervisor {
|
|
|
238
276
|
async heartbeat(ttl) {
|
|
239
277
|
if (this.stopped)
|
|
240
278
|
return;
|
|
241
|
-
const plugins = [...new Set(this.
|
|
279
|
+
const plugins = [...new Set(this.localPlugins())];
|
|
242
280
|
const gone = [...this.heartbeated].filter((p) => !plugins.includes(p));
|
|
243
281
|
if (plugins.length === 0 && gone.length === 0)
|
|
244
282
|
return;
|
|
245
283
|
try {
|
|
246
|
-
await this.
|
|
284
|
+
await this.redis.eval(HEARTBEAT, plugins.length, ...plugins.map(gatewayReplicasKey), this.replicaId, ttl, ...gone.map(gatewayReplicasKey));
|
|
247
285
|
this.heartbeated = new Set(plugins);
|
|
248
286
|
}
|
|
249
287
|
catch (err) {
|
|
250
|
-
this.
|
|
288
|
+
this.log.warn("gateway heartbeat failed", { err });
|
|
251
289
|
}
|
|
252
290
|
}
|
|
253
291
|
/**
|
|
@@ -256,13 +294,13 @@ export class ChannelSupervisor {
|
|
|
256
294
|
* written yet on the first round).
|
|
257
295
|
*/
|
|
258
296
|
async targets(runnable) {
|
|
259
|
-
const { leaseTtlMs: ttl, shareSlack } = this.
|
|
297
|
+
const { leaseTtlMs: ttl, shareSlack } = this.config.get().channels;
|
|
260
298
|
const plugins = [...runnable.keys()];
|
|
261
|
-
const live = await liveGateways(this.
|
|
299
|
+
const live = await liveGateways(this.redis, plugins, ttl);
|
|
262
300
|
const out = new Map();
|
|
263
301
|
for (const p of plugins) {
|
|
264
|
-
const members = [...new Set([...(live.get(p) ?? []), this.
|
|
265
|
-
const rank = members.indexOf(this.
|
|
302
|
+
const members = [...new Set([...(live.get(p) ?? []), this.replicaId])].sort();
|
|
303
|
+
const rank = members.indexOf(this.replicaId);
|
|
266
304
|
out.set(p, shareTarget(runnable.get(p) ?? 0, members.length, shareSlack, rank));
|
|
267
305
|
}
|
|
268
306
|
return out;
|
|
@@ -289,26 +327,22 @@ export class ChannelSupervisor {
|
|
|
289
327
|
if (!latest)
|
|
290
328
|
return;
|
|
291
329
|
const [id] = latest;
|
|
292
|
-
const px = this.
|
|
293
|
-
await this.
|
|
330
|
+
const px = this.config.get().channels.scanIntervalMs * 2;
|
|
331
|
+
await this.redis.set(channelHandoffKey(id), this.replicaId, "PX", px);
|
|
294
332
|
this.releaseInBackground(id, this.nudge(plugin));
|
|
295
333
|
}
|
|
296
334
|
/** After-release callback: tells the other replicas a connection of `plugin` is free to claim. */
|
|
297
335
|
nudge(plugin) {
|
|
298
|
-
return () => this.
|
|
299
|
-
.publish(CHANNEL_HANDOFF_TOPIC, { plugin, replicaId: this.
|
|
300
|
-
.catch((err) => this.
|
|
336
|
+
return () => this.bus
|
|
337
|
+
.publish(CHANNEL_HANDOFF_TOPIC, { plugin, replicaId: this.replicaId })
|
|
338
|
+
.catch((err) => this.log.warn("cannot publish channel handoff", { err }));
|
|
301
339
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
this.deps.log.warn("channel lease lost; disconnecting", { connectionId: id });
|
|
305
|
-
this.drop(id, h);
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
340
|
+
/** A renewal succeeded: one lease period connected in a row clears the failure count. */
|
|
341
|
+
async afterRenew(id, h, ttl) {
|
|
308
342
|
h.renewedAt = Date.now();
|
|
309
343
|
if (!h.stable && Date.now() - h.startedAt >= ttl) {
|
|
310
344
|
h.stable = true;
|
|
311
|
-
await this.
|
|
345
|
+
await this.redis.del(channelFailsKey(id)).catch(() => { });
|
|
312
346
|
}
|
|
313
347
|
}
|
|
314
348
|
/**
|
|
@@ -316,10 +350,11 @@ export class ChannelSupervisor {
|
|
|
316
350
|
* 且插件在本进程已加载——滚动升级期间还没有该插件的副本根本不考虑它(不取租约、不记失败),留给有插件的副本。
|
|
317
351
|
*/
|
|
318
352
|
runnable(plugins) {
|
|
319
|
-
|
|
353
|
+
const db = this.db.db;
|
|
354
|
+
return (db
|
|
320
355
|
.selectFrom("channel_connections")
|
|
321
356
|
.innerJoin("orgs", "orgs.id", "channel_connections.org_id")
|
|
322
|
-
.innerJoin(enabledExtensionsByOrg(
|
|
357
|
+
.innerJoin(enabledExtensionsByOrg(db).as("en"), (j) => j
|
|
323
358
|
.onRef("en.plugin", "=", "channel_connections.plugin")
|
|
324
359
|
.onRef("en.org_id", "=", "channel_connections.org_id"))
|
|
325
360
|
.select(["channel_connections.id", "channel_connections.plugin"])
|
|
@@ -338,7 +373,7 @@ export class ChannelSupervisor {
|
|
|
338
373
|
const ids = [...this.held.keys()];
|
|
339
374
|
if (ids.length === 0)
|
|
340
375
|
return;
|
|
341
|
-
const plugins = this.
|
|
376
|
+
const plugins = this.localPlugins();
|
|
342
377
|
const live = new Set(plugins.length === 0
|
|
343
378
|
? []
|
|
344
379
|
: (await this.runnable(plugins).where("channel_connections.id", "in", ids).execute()).map((r) => r.id));
|
|
@@ -356,8 +391,8 @@ export class ChannelSupervisor {
|
|
|
356
391
|
async scan(claimOnly) {
|
|
357
392
|
if (this.stopped)
|
|
358
393
|
return;
|
|
359
|
-
this.
|
|
360
|
-
const plugins = this.
|
|
394
|
+
this.onScan?.(claimOnly);
|
|
395
|
+
const plugins = this.localPlugins();
|
|
361
396
|
if (plugins.length === 0)
|
|
362
397
|
return;
|
|
363
398
|
const rows = await this.runnable(plugins).execute();
|
|
@@ -384,34 +419,40 @@ export class ChannelSupervisor {
|
|
|
384
419
|
}
|
|
385
420
|
if (this.held.has(id))
|
|
386
421
|
continue;
|
|
387
|
-
if ((await this.
|
|
422
|
+
if ((await this.redis.exists(channelBackoffKey(id))) === 1)
|
|
388
423
|
continue;
|
|
389
|
-
if ((await this.
|
|
424
|
+
if ((await this.redis.get(channelHandoffKey(id))) === this.replicaId)
|
|
390
425
|
continue;
|
|
391
|
-
const
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
if (ok !== "OK")
|
|
426
|
+
const ttl = this.config.get().channels.leaseTtlMs;
|
|
427
|
+
const lease = await this.locks.hold(channelLeaseKey(id), randomUUID(), ttl);
|
|
428
|
+
if (!lease)
|
|
395
429
|
continue;
|
|
396
430
|
if (this.stopped) {
|
|
397
|
-
await
|
|
431
|
+
await lease.release();
|
|
398
432
|
return;
|
|
399
433
|
}
|
|
400
|
-
await this.connect(id,
|
|
434
|
+
await this.connect(id, lease);
|
|
401
435
|
}
|
|
402
436
|
}
|
|
403
437
|
/** 已取得租约:读配置并在后台跑插件的 `connect`。 */
|
|
404
|
-
async connect(id,
|
|
438
|
+
async connect(id, lease) {
|
|
405
439
|
const pending = { reconnect: false };
|
|
406
440
|
this.connecting.set(id, pending);
|
|
407
441
|
let rt;
|
|
408
442
|
try {
|
|
409
|
-
rt = await this.
|
|
443
|
+
rt = await this.connections.runtime(id);
|
|
410
444
|
}
|
|
411
445
|
catch (err) {
|
|
412
446
|
this.connecting.delete(id);
|
|
413
447
|
await this.failed(id, err);
|
|
414
|
-
await
|
|
448
|
+
await lease.release();
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
// The lease was lost while the config was read (an aborted signal never fires a listener
|
|
452
|
+
// added later): not ours any more, so no connect and no release
|
|
453
|
+
if (lease.lost.aborted) {
|
|
454
|
+
this.connecting.delete(id);
|
|
455
|
+
lease.abandon();
|
|
415
456
|
return;
|
|
416
457
|
}
|
|
417
458
|
// 插件异常信息可能带上凭据:写进 last_error / 日志前按该连接的密钥打码
|
|
@@ -420,7 +461,7 @@ export class ChannelSupervisor {
|
|
|
420
461
|
const now = Date.now();
|
|
421
462
|
const h = {
|
|
422
463
|
plugin: rt.row.plugin,
|
|
423
|
-
|
|
464
|
+
lease,
|
|
424
465
|
abort,
|
|
425
466
|
done: Promise.resolve(),
|
|
426
467
|
startedAt: now,
|
|
@@ -429,12 +470,14 @@ export class ChannelSupervisor {
|
|
|
429
470
|
};
|
|
430
471
|
this.held.set(id, h);
|
|
431
472
|
this.connecting.delete(id);
|
|
473
|
+
// 租约丢失(LockService 记一行 `lock lost`):中止,不释放(已不是自己的)
|
|
474
|
+
lease.lost.addEventListener("abort", () => this.drop(id, h), { once: true });
|
|
432
475
|
h.done = (async () => {
|
|
433
476
|
try {
|
|
434
477
|
await rt.channel.connect({
|
|
435
478
|
connectionId: id,
|
|
436
479
|
config: rt.config,
|
|
437
|
-
onEvent: (e) => this.track(this.
|
|
480
|
+
onEvent: (e) => this.track(this.inbound.onEvent(id, e)),
|
|
438
481
|
signal: abort.signal,
|
|
439
482
|
});
|
|
440
483
|
if (!abort.signal.aborted)
|
|
@@ -449,7 +492,7 @@ export class ChannelSupervisor {
|
|
|
449
492
|
// 自己结束(出错 / 提前返回):交还租约,退避后由任一副本重试
|
|
450
493
|
if (!abort.signal.aborted && this.held.get(id) === h) {
|
|
451
494
|
this.held.delete(id);
|
|
452
|
-
await
|
|
495
|
+
await lease.release();
|
|
453
496
|
}
|
|
454
497
|
}
|
|
455
498
|
})();
|
|
@@ -468,26 +511,28 @@ export class ChannelSupervisor {
|
|
|
468
511
|
async failed(id, err, redact) {
|
|
469
512
|
const raw = errMsg(err);
|
|
470
513
|
const message = (redact ? redact(raw) : raw).slice(0, MAX_ERROR_CHARS);
|
|
471
|
-
this.
|
|
514
|
+
this.log.warn("channel connection failed", { connectionId: id, error: message });
|
|
472
515
|
try {
|
|
473
|
-
const fails = await this.
|
|
474
|
-
await this.
|
|
475
|
-
const delay = Math.min(MAX_BACKOFF_MS, this.
|
|
476
|
-
await this.
|
|
477
|
-
await this.
|
|
516
|
+
const fails = await this.redis.incr(channelFailsKey(id));
|
|
517
|
+
await this.redis.expire(channelFailsKey(id), FAILS_TTL_SECONDS);
|
|
518
|
+
const delay = Math.min(MAX_BACKOFF_MS, this.config.get().channels.retryBaseMs * 2 ** Math.min(fails - 1, 20));
|
|
519
|
+
await this.redis.set(channelBackoffKey(id), "1", "PX", delay);
|
|
520
|
+
await this.db
|
|
478
521
|
.updateTable("channel_connections")
|
|
479
522
|
.set({ last_error: message })
|
|
480
523
|
.where("id", "=", id)
|
|
481
524
|
.execute();
|
|
482
525
|
}
|
|
483
526
|
catch (e) {
|
|
484
|
-
this.
|
|
527
|
+
this.log.warn("cannot record channel failure", { connectionId: id, err: e });
|
|
485
528
|
}
|
|
486
529
|
}
|
|
487
|
-
/**
|
|
530
|
+
/** 租约已丢:中止,不释放(已不是自己的;续租已停)。 */
|
|
488
531
|
drop(id, h) {
|
|
489
|
-
if (this.held.get(id)
|
|
490
|
-
|
|
532
|
+
if (this.held.get(id) !== h)
|
|
533
|
+
return;
|
|
534
|
+
this.held.delete(id);
|
|
535
|
+
h.lease.abandon();
|
|
491
536
|
h.abort.abort();
|
|
492
537
|
}
|
|
493
538
|
/** 后台交还,记入 `releasing` 供 `stop()` 等待;`after` runs once the lease is released. */
|
|
@@ -500,13 +545,15 @@ export class ChannelSupervisor {
|
|
|
500
545
|
.finally(() => this.releasing.delete(p));
|
|
501
546
|
this.releasing.add(p);
|
|
502
547
|
}
|
|
503
|
-
/**
|
|
548
|
+
/**
|
|
549
|
+
* 主动交还:中止,等 `connect` 返回(至多 SETTLE_MS,期间租约照常续着,不会在别的副本眼里提前过期)后释放租约;
|
|
550
|
+
* 超时则停止续租、让租约自然过期,避免两边同时在线。
|
|
551
|
+
*/
|
|
504
552
|
async release(id) {
|
|
505
553
|
const h = this.held.get(id);
|
|
506
554
|
if (!h)
|
|
507
555
|
return false;
|
|
508
556
|
this.held.delete(id);
|
|
509
|
-
this.settling.set(id, h.token);
|
|
510
557
|
h.abort.abort();
|
|
511
558
|
let timer;
|
|
512
559
|
const settled = await Promise.race([
|
|
@@ -517,23 +564,15 @@ export class ChannelSupervisor {
|
|
|
517
564
|
}),
|
|
518
565
|
]);
|
|
519
566
|
clearTimeout(timer);
|
|
520
|
-
if (this.settling.get(id) === h.token)
|
|
521
|
-
this.settling.delete(id);
|
|
522
567
|
if (settled)
|
|
523
|
-
await
|
|
524
|
-
else
|
|
525
|
-
|
|
568
|
+
await h.lease.release();
|
|
569
|
+
else {
|
|
570
|
+
h.lease.abandon();
|
|
571
|
+
this.log.warn("channel connect did not stop in time; lease left to expire", {
|
|
526
572
|
connectionId: id,
|
|
527
573
|
});
|
|
528
|
-
return settled;
|
|
529
|
-
}
|
|
530
|
-
async releaseLease(id, token) {
|
|
531
|
-
try {
|
|
532
|
-
await this.deps.redis.eval(RELEASE, 1, channelLeaseKey(id), token);
|
|
533
|
-
}
|
|
534
|
-
catch (err) {
|
|
535
|
-
this.deps.log.warn("cannot release channel lease", { connectionId: id, err });
|
|
536
574
|
}
|
|
575
|
+
return settled;
|
|
537
576
|
}
|
|
538
577
|
/**
|
|
539
578
|
* 本进程的插件实例变了(撤销、替换为新实例;内核接 `host.onChange`,C17):交还该插件持有的全部长连接
|
|
@@ -561,8 +600,8 @@ export class ChannelSupervisor {
|
|
|
561
600
|
// A nudged scan may still be claiming: let it finish so its leases are released below
|
|
562
601
|
await this.scanChain;
|
|
563
602
|
// Leave the share first so the other gateways count one replica fewer right away
|
|
564
|
-
await Promise.all([...this.heartbeated].map((p) => this.
|
|
565
|
-
this.
|
|
603
|
+
await Promise.all([...this.heartbeated].map((p) => this.redis.zrem(gatewayReplicasKey(p), this.replicaId).catch((err) => {
|
|
604
|
+
this.log.warn("cannot remove gateway heartbeat", { plugin: p, err });
|
|
566
605
|
})));
|
|
567
606
|
this.heartbeated.clear();
|
|
568
607
|
await Promise.all([...this.held.keys()].map((id) => this.release(id)));
|
|
@@ -571,19 +610,78 @@ export class ChannelSupervisor {
|
|
|
571
610
|
// 插件交来的事件已在入队途中:等它们结束(之后内核才关闭队列)
|
|
572
611
|
await Promise.all([...this.inflight]);
|
|
573
612
|
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
613
|
+
};
|
|
614
|
+
ChannelSupervisor = __decorate([
|
|
615
|
+
Injectable(),
|
|
616
|
+
__param(0, Inject(KernelDb)),
|
|
617
|
+
__param(1, Inject(REDIS)),
|
|
618
|
+
__param(2, Inject(KERNEL_BUS)),
|
|
619
|
+
__param(3, Inject(LockService)),
|
|
620
|
+
__param(4, Inject(ChannelConnections)),
|
|
621
|
+
__param(5, Inject(ExtensionRegistry)),
|
|
622
|
+
__param(6, Inject(ChannelInbound)),
|
|
623
|
+
__param(7, Inject(KernelConfigService)),
|
|
624
|
+
__param(8, Inject(KERNEL_LOGGER)),
|
|
625
|
+
__param(9, Inject(ReplicaStatusStore))
|
|
626
|
+
], ChannelSupervisor);
|
|
627
|
+
export { ChannelSupervisor };
|
|
628
|
+
export { GATEWAY_CHECK_JOB, GATEWAY_CHECK_SCHEDULER_ID } from "./job-ids.js";
|
|
629
|
+
/** The period of the gateway check (`@LockedCron` every minute). */
|
|
578
630
|
export const GATEWAY_CHECK_EVERY_MS = 60_000;
|
|
579
631
|
/**
|
|
580
|
-
*
|
|
632
|
+
* Warns when channel connections need a gateway and none is live (Ruling R1 / R3 / R4):
|
|
633
|
+
* {@link checkGatewayPresence}, every minute, once across replicas; a worker-role job
|
|
634
|
+
* (`WorkerModule`), as the maintenance job it replaces was. Silent for one lease TTL after this
|
|
635
|
+
* worker process built its providers (the gateways' first heartbeats; the old handler's grace also
|
|
636
|
+
* started at the worker's kernel construction). Replaces the maintenance scheduler
|
|
637
|
+
* `channel-gateway-check-every` (retired at worker start).
|
|
638
|
+
*/
|
|
639
|
+
let GatewayCheckJob = class GatewayCheckJob {
|
|
640
|
+
db;
|
|
641
|
+
redis;
|
|
642
|
+
config;
|
|
643
|
+
lockService;
|
|
644
|
+
log;
|
|
645
|
+
/** The start of the grace period: when this process built its providers. */
|
|
646
|
+
graceFrom = Date.now();
|
|
647
|
+
constructor(db, redis, config, lockService, log) {
|
|
648
|
+
this.db = db;
|
|
649
|
+
this.redis = redis;
|
|
650
|
+
this.config = config;
|
|
651
|
+
this.lockService = lockService;
|
|
652
|
+
this.log = log;
|
|
653
|
+
}
|
|
654
|
+
async run() {
|
|
655
|
+
await checkGatewayPresence({
|
|
656
|
+
db: this.db.db,
|
|
657
|
+
redis: this.redis,
|
|
658
|
+
locks: this.lockService,
|
|
659
|
+
config: this.config,
|
|
660
|
+
log: this.log,
|
|
661
|
+
graceUntil: this.graceFrom + this.config.get().channels.leaseTtlMs,
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
__decorate([
|
|
666
|
+
LockedCron("* * * * *", { name: GATEWAY_CHECK_JOB })
|
|
667
|
+
], GatewayCheckJob.prototype, "run", null);
|
|
668
|
+
GatewayCheckJob = __decorate([
|
|
669
|
+
Injectable(),
|
|
670
|
+
__param(0, Inject(KernelDb)),
|
|
671
|
+
__param(1, Inject(REDIS)),
|
|
672
|
+
__param(2, Inject(KernelConfigService)),
|
|
673
|
+
__param(3, Inject(LockService)),
|
|
674
|
+
__param(4, Inject(KERNEL_LOGGER))
|
|
675
|
+
], GatewayCheckJob);
|
|
676
|
+
export { GatewayCheckJob };
|
|
677
|
+
/**
|
|
678
|
+
* Runs once a minute across replicas ({@link GatewayCheckJob}), per channel plugin (Ruling R3): when a plugin has
|
|
581
679
|
* active connections (not deleted, org not deleted, plugin enabled for the org; long connection or
|
|
582
680
|
* webhook mode, Ruling R4) but no gateway replica with that plugin loaded has a heartbeat newer than
|
|
583
681
|
* one lease TTL (Redis server clock), nobody holds those long connections or answers their webhooks.
|
|
584
682
|
* - Logs one `warn` (naming the plugins) per interval at most across the cluster: a Redis
|
|
585
|
-
* `SET NX PX`
|
|
586
|
-
*
|
|
683
|
+
* marker (`LockService.lease`, a `SET NX PX`) a little shorter than the job period, so a
|
|
684
|
+
* duplicated job or several replicas do not repeat it while each period still gets its line.
|
|
587
685
|
* - Silent before `graceUntil` (this process's start + one lease TTL), so a fresh cluster does not
|
|
588
686
|
* warn before the gateways' first heartbeat.
|
|
589
687
|
* Returns whether it warned.
|
|
@@ -609,13 +707,13 @@ export async function checkGatewayPresence(deps) {
|
|
|
609
707
|
const plugins = [...counts.keys()].filter((p) => (counts.get(p) ?? 0) > 0).sort();
|
|
610
708
|
if (plugins.length === 0)
|
|
611
709
|
return false;
|
|
612
|
-
const live = await liveGateways(deps.redis, plugins, deps.config().channels.leaseTtlMs);
|
|
710
|
+
const live = await liveGateways(deps.redis, plugins, deps.config.get().channels.leaseTtlMs);
|
|
613
711
|
const missing = plugins.filter((p) => (live.get(p) ?? []).length === 0);
|
|
614
712
|
if (missing.length === 0)
|
|
615
713
|
return false;
|
|
616
714
|
const everyMs = deps.everyMs ?? GATEWAY_CHECK_EVERY_MS;
|
|
617
|
-
const first = await deps.
|
|
618
|
-
if (first
|
|
715
|
+
const first = await deps.locks.lease(gatewayMissingWarnedKey, "1", Math.max(Math.ceil(everyMs / 2), everyMs - 5_000));
|
|
716
|
+
if (!first)
|
|
619
717
|
return false;
|
|
620
718
|
deps.log.warn("active channel connections have no live gateway replica with their plugin loaded; add the gateway role to a process (CAPYBARA_ROLES) that can load the plugin, or they receive no messages", {
|
|
621
719
|
plugins: missing,
|