@plitzi/sdk-server 0.37.2 → 0.37.4
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/CHANGELOG.md +1170 -0
- package/README.md +100 -7
- package/dist/actions.d.ts +6 -2
- package/dist/actions.js +5 -2
- package/dist/adapters/cloudAdapters.js +4 -3
- package/dist/adapters/jsonAdapters.js +28 -6
- package/dist/adapters/jsonAdapters.test.d.ts +1 -0
- package/dist/auth.d.ts +7 -4
- package/dist/auth.js +8 -6
- package/dist/core/auth/api.d.ts +29 -1
- package/dist/core/auth/api.js +47 -13
- package/dist/core/auth/createAuth.d.ts +4 -0
- package/dist/core/auth/createAuth.js +3 -3
- package/dist/core/auth/credentials.d.ts +3 -0
- package/dist/core/auth/credentials.js +1 -1
- package/dist/core/auth/csrf.d.ts +25 -1
- package/dist/core/auth/csrf.js +29 -4
- package/dist/core/auth/renewal.d.ts +26 -0
- package/dist/core/auth/renewal.js +24 -0
- package/dist/core/auth/routes.js +8 -6
- package/dist/core/auth/session.d.ts +45 -0
- package/dist/core/auth/session.js +47 -1
- package/dist/core/auth/sessionActivity.d.ts +11 -0
- package/dist/core/auth/sessionActivity.js +14 -0
- package/dist/core/auth/throttle.d.ts +15 -0
- package/dist/core/auth/throttle.js +29 -1
- package/dist/core/auth/totp.d.ts +9 -1
- package/dist/core/auth/totp.js +11 -6
- package/dist/core/createServer.actions.test.d.ts +1 -0
- package/dist/core/createServer.d.ts +14 -1
- package/dist/core/createServer.functions.test.d.ts +1 -0
- package/dist/core/createServer.js +22 -12
- package/dist/core/fontStore.js +1 -1
- package/dist/core/handlers/authRouteHandlers.d.ts +1 -1
- package/dist/core/handlers/authRouteHandlers.js +57 -21
- package/dist/core/handlers/csrfMiddleware.d.ts +23 -0
- package/dist/core/handlers/csrfMiddleware.js +31 -7
- package/dist/core/handlers/csrfMiddleware.test.d.ts +1 -0
- package/dist/core/handlers/oauthRouteHandlers.js +5 -3
- package/dist/core/handlers/socialRouteHandlers.d.ts +1 -1
- package/dist/core/handlers/socialRouteHandlers.js +2 -1
- package/dist/core/http/dispatcher.d.ts +9 -1
- package/dist/core/http/dispatcher.js +38 -11
- package/dist/core/http/navigation.d.ts +5 -2
- package/dist/core/http/navigation.js +7 -4
- package/dist/core/http/socketResponse.d.ts +18 -0
- package/dist/core/http/socketResponse.js +59 -0
- package/dist/core/http/sse.d.ts +26 -0
- package/dist/core/http/sse.js +78 -0
- package/dist/core/http/stages/authRoutes.js +3 -1
- package/dist/core/http/stages/exchangeRoute.test.d.ts +1 -0
- package/dist/core/http/stages/middlewares.d.ts +1 -1
- package/dist/core/http/stages/middlewares.js +16 -10
- package/dist/core/http/stages/middlewares.test.d.ts +1 -0
- package/dist/core/http/stages/oauth.js +2 -2
- package/dist/core/http/stages/sessionRenewal.d.ts +16 -0
- package/dist/core/http/stages/sessionRenewal.js +81 -0
- package/dist/core/http/stages/sessionRenewal.test.d.ts +1 -0
- package/dist/core/http/stages/signInRoute.d.ts +2 -0
- package/dist/core/http/stages/signInRoute.js +139 -0
- package/dist/core/http/stages/signInRoute.test.d.ts +1 -0
- package/dist/core/http/types.d.ts +9 -0
- package/dist/core/http/webExchange.d.ts +18 -0
- package/dist/core/http/webExchange.js +53 -0
- package/dist/core/oauth/authorize.js +37 -13
- package/dist/core/oauth/consentPage.js +11 -0
- package/dist/core/oauth/issueContext.d.ts +14 -0
- package/dist/core/oauth/issueContext.js +32 -0
- package/dist/core/oauth/records.d.ts +7 -0
- package/dist/core/oauth/register.d.ts +2 -0
- package/dist/core/oauth/register.js +32 -11
- package/dist/core/oauth/register.test.d.ts +1 -0
- package/dist/core/oauth/token.js +21 -6
- package/dist/core/oauth/token.test.d.ts +1 -0
- package/dist/core/requestParser.d.ts +4 -0
- package/dist/core/requestParser.js +14 -7
- package/dist/core/sdkAssets.js +1 -1
- package/dist/core/server/baseServer.d.ts +10 -0
- package/dist/core/server/baseServer.js +42 -11
- package/dist/core/server/closeOnSignals.js +4 -3
- package/dist/core/server/drain.d.ts +18 -0
- package/dist/core/server/drain.js +62 -0
- package/dist/core/server/drain.test.d.ts +1 -0
- package/dist/core/server/fleet/channel.d.ts +103 -0
- package/dist/core/server/fleet/channel.js +191 -0
- package/dist/core/server/fleet/channel.test.d.ts +1 -0
- package/dist/core/server/fleet/fixtures/fleetServer.d.ts +1 -0
- package/dist/core/server/fleet/fleet.integration.test.d.ts +1 -0
- package/dist/core/server/fleet/link.d.ts +23 -0
- package/dist/core/server/fleet/link.js +70 -0
- package/dist/core/server/fleet/relay.d.ts +11 -0
- package/dist/core/server/fleet/relay.js +104 -0
- package/dist/core/server/fleet/relay.test.d.ts +1 -0
- package/dist/core/server/fleet/role.d.ts +46 -0
- package/dist/core/server/fleet/role.js +59 -0
- package/dist/core/server/fleet/role.test.d.ts +1 -0
- package/dist/core/server/fleet/stores.d.ts +7 -0
- package/dist/core/server/fleet/stores.js +19 -0
- package/dist/core/server/fleet/supervisor.d.ts +26 -0
- package/dist/core/server/fleet/supervisor.js +108 -0
- package/dist/core/server/fleet/supervisor.test.d.ts +1 -0
- package/dist/core/server/pageServer.js +34 -5
- package/dist/core/services/action.js +10 -2
- package/dist/core/services/functionRoutes.d.ts +9 -0
- package/dist/core/services/functionRoutes.js +47 -0
- package/dist/core/services/realtime.d.ts +8 -0
- package/dist/core/services/realtime.js +57 -0
- package/dist/core/services/registry.js +6 -2
- package/dist/core/staticFiles.js +12 -4
- package/dist/core/staticFiles.test.d.ts +1 -0
- package/dist/core/transports.d.ts +13 -3
- package/dist/core/transports.js +14 -5
- package/dist/functions-api.d.ts +281 -0
- package/dist/functions.d.ts +19 -0
- package/dist/functions.js +5 -0
- package/dist/functionsRunner.d.ts +15 -0
- package/dist/functionsRunner.js +6 -0
- package/dist/handlers.d.ts +2 -2
- package/dist/handlers.js +2 -2
- package/dist/helpers/atomicFile.d.ts +10 -0
- package/dist/helpers/atomicFile.js +33 -0
- package/dist/helpers/atomicFile.test.d.ts +1 -0
- package/dist/helpers/buildResponseHelpers.js +35 -11
- package/dist/helpers/buildServerInfo.js +4 -2
- package/dist/helpers/buildServerInfo.test.d.ts +1 -0
- package/dist/helpers/cache/CompressedFileCache.d.ts +18 -0
- package/dist/helpers/cache/CompressedFileCache.js +44 -0
- package/dist/helpers/cache/CompressedFileCache.test.d.ts +1 -0
- package/dist/helpers/cache/cacheManager.d.ts +1 -1
- package/dist/helpers/cache/cacheManager.js +2 -1
- package/dist/helpers/cache/cacheManager.test.d.ts +1 -0
- package/dist/helpers/cache/index.d.ts +1 -1
- package/dist/helpers/cache/keys.d.ts +15 -1
- package/dist/helpers/cache/keys.js +47 -5
- package/dist/helpers/cache/serverCaches.d.ts +7 -1
- package/dist/helpers/compress.d.ts +3 -1
- package/dist/helpers/compress.js +11 -3
- package/dist/helpers/hydrationPayload.d.ts +11 -0
- package/dist/helpers/hydrationPayload.js +51 -0
- package/dist/helpers/hydrationPayload.test.d.ts +1 -0
- package/dist/helpers/metrics.d.ts +1 -1
- package/dist/helpers/metrics.js +3 -2
- package/dist/helpers/outboundGuard.d.ts +14 -6
- package/dist/helpers/outboundGuard.js +132 -8
- package/dist/helpers/paintedCookie.d.ts +8 -0
- package/dist/helpers/paintedCookie.js +13 -0
- package/dist/helpers/reportReactBuild.d.ts +9 -0
- package/dist/helpers/reportReactBuild.js +18 -0
- package/dist/helpers/reportReactBuild.test.d.ts +1 -0
- package/dist/helpers/serverLog.d.ts +25 -1
- package/dist/helpers/serverLog.js +68 -3
- package/dist/helpers/serverLog.test.d.ts +1 -0
- package/dist/helpers/wsFrame.d.ts +3 -0
- package/dist/helpers/wsFrame.js +5 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -2
- package/dist/kernel.d.ts +2 -1
- package/dist/kernel.js +3 -2
- package/dist/modules/actions/connectorWrite.js +2 -1
- package/dist/modules/actions/index.d.ts +29 -10
- package/dist/modules/actions/index.js +43 -6
- package/dist/modules/actions/jobs/failureStreak.d.ts +17 -0
- package/dist/modules/actions/jobs/failureStreak.js +47 -0
- package/dist/modules/actions/jobs/failureStreak.test.d.ts +1 -0
- package/dist/modules/actions/jobs/index.d.ts +2 -1
- package/dist/modules/actions/jobs/index.js +5 -3
- package/dist/modules/actions/jobs/memoryQueue.d.ts +3 -0
- package/dist/modules/actions/jobs/memoryQueue.js +17 -1
- package/dist/modules/actions/jobs/scheduler.d.ts +2 -0
- package/dist/modules/actions/jobs/scheduler.js +12 -7
- package/dist/modules/actions/jobs/worker.d.ts +3 -1
- package/dist/modules/actions/jobs/worker.js +9 -4
- package/dist/modules/actions/moduleFor.js +5 -2
- package/dist/modules/actions/runtime/errors.d.ts +12 -0
- package/dist/modules/actions/runtime/errors.js +16 -1
- package/dist/modules/actions/runtime/kvChange.d.ts +27 -0
- package/dist/modules/actions/runtime/kvChange.js +23 -0
- package/dist/modules/actions/runtime/kvList.d.ts +51 -0
- package/dist/modules/actions/runtime/kvList.js +52 -0
- package/dist/modules/actions/runtime/kvStore.d.ts +8 -0
- package/dist/modules/actions/runtime/kvStore.js +46 -20
- package/dist/modules/actions/runtime/memoryKv.d.ts +3 -0
- package/dist/modules/actions/runtime/memoryKv.js +19 -1
- package/dist/modules/actions/runtime/namespaceKv.d.ts +4 -6
- package/dist/modules/actions/runtime/namespaceKv.js +15 -3
- package/dist/modules/actions/runtime/namespaceKv.test.d.ts +1 -0
- package/dist/modules/actions/runtime/precheck.js +4 -8
- package/dist/modules/actions/runtime/rateLimit.d.ts +19 -0
- package/dist/modules/actions/runtime/rateLimit.js +19 -0
- package/dist/modules/actions/runtime/redisKv.d.ts +27 -0
- package/dist/modules/actions/runtime/redisKv.integration.test.d.ts +1 -0
- package/dist/modules/actions/runtime/redisKv.js +46 -0
- package/dist/modules/actions/runtime/report.js +2 -1
- package/dist/modules/actions/runtime/runAction.d.ts +10 -2
- package/dist/modules/actions/runtime/runAction.js +52 -116
- package/dist/modules/actions/runtime/runLogger.d.ts +5 -0
- package/dist/modules/actions/runtime/runLogger.js +8 -2
- package/dist/modules/actions/runtime/signing.d.ts +20 -0
- package/dist/modules/actions/runtime/signing.js +25 -0
- package/dist/modules/actions/runtime/signing.test.d.ts +1 -0
- package/dist/modules/actions/runtime/taskContext.d.ts +33 -0
- package/dist/modules/actions/runtime/taskContext.js +124 -0
- package/dist/modules/actions/tasks/builtins.js +5 -1
- package/dist/modules/actions/tasks/flow.js +81 -10
- package/dist/modules/actions/tasks/helpers.js +2 -2
- package/dist/modules/actions/tasks/http.js +2 -3
- package/dist/modules/actions/tasks/kv.js +39 -0
- package/dist/modules/actions/tasks/list.d.ts +2 -0
- package/dist/modules/actions/tasks/list.js +145 -0
- package/dist/modules/actions/tasks/realtime.d.ts +2 -0
- package/dist/modules/actions/tasks/realtime.js +104 -0
- package/dist/modules/actions/tasks/registry.d.ts +10 -1
- package/dist/modules/actions/tasks/registry.js +17 -6
- package/dist/modules/actions/transport/callHandler.js +5 -2
- package/dist/modules/actions/transport/catalogHandler.d.ts +5 -2
- package/dist/modules/actions/transport/catalogHandler.js +3 -2
- package/dist/modules/actions/transport/stream.d.ts +4 -5
- package/dist/modules/actions/transport/stream.js +12 -76
- package/dist/modules/actions/transport/webhookHandler.js +4 -3
- package/dist/modules/actions/types.d.ts +86 -3
- package/dist/modules/connectors/engine.js +3 -5
- package/dist/modules/functions/build.d.ts +22 -0
- package/dist/modules/functions/build.js +122 -0
- package/dist/modules/functions/build.test.d.ts +1 -0
- package/dist/modules/functions/capabilities.d.ts +22 -0
- package/dist/modules/functions/capabilities.js +228 -0
- package/dist/modules/functions/config.d.ts +34 -0
- package/dist/modules/functions/config.js +24 -0
- package/dist/modules/functions/context.d.ts +17 -0
- package/dist/modules/functions/context.js +88 -0
- package/dist/modules/functions/contract.d.ts +121 -0
- package/dist/modules/functions/contract.js +9 -0
- package/dist/modules/functions/driver.d.ts +36 -0
- package/dist/modules/functions/driver.js +150 -0
- package/dist/modules/functions/load.d.ts +15 -0
- package/dist/modules/functions/load.js +45 -0
- package/dist/modules/functions/load.test.d.ts +1 -0
- package/dist/modules/functions/local.d.ts +29 -0
- package/dist/modules/functions/local.js +61 -0
- package/dist/modules/functions/local.test.d.ts +1 -0
- package/dist/modules/functions/manifest.d.ts +24 -0
- package/dist/modules/functions/manifest.js +163 -0
- package/dist/modules/functions/manifest.test.d.ts +1 -0
- package/dist/modules/functions/native.d.ts +8 -0
- package/dist/modules/functions/native.js +21 -0
- package/dist/modules/functions/native.test.d.ts +1 -0
- package/dist/modules/functions/protocol.d.ts +216 -0
- package/dist/modules/functions/protocol.js +18 -0
- package/dist/modules/functions/routes.d.ts +36 -0
- package/dist/modules/functions/routes.js +181 -0
- package/dist/modules/functions/routes.test.d.ts +1 -0
- package/dist/modules/functions/runner/messages.d.ts +5 -0
- package/dist/modules/functions/runner/messages.js +188 -0
- package/dist/modules/functions/runner/remote.d.ts +19 -0
- package/dist/modules/functions/runner/remote.js +116 -0
- package/dist/modules/functions/runner/remote.test.d.ts +1 -0
- package/dist/modules/functions/runner/service.d.ts +32 -0
- package/dist/modules/functions/runner/service.js +209 -0
- package/dist/modules/functions/sandbox/guest.d.ts +45 -0
- package/dist/modules/functions/sandbox/guest.js +660 -0
- package/dist/modules/functions/sandbox/isolate.d.ts +37 -0
- package/dist/modules/functions/sandbox/isolate.js +347 -0
- package/dist/modules/functions/sandbox/isolate.test.d.ts +1 -0
- package/dist/modules/functions/sandbox/prelude.d.ts +2 -0
- package/dist/modules/functions/sandbox/prelude.js +49 -0
- package/dist/modules/functions/space.d.ts +40 -0
- package/dist/modules/functions/space.js +162 -0
- package/dist/modules/functions/testing/tasksOf.d.ts +4 -0
- package/dist/modules/functions/tryEntry.d.ts +9 -0
- package/dist/modules/functions/tryEntry.js +49 -0
- package/dist/modules/mongo/kv.js +31 -0
- package/dist/modules/mysql/accounts.js +19 -9
- package/dist/modules/mysql/index.d.ts +2 -1
- package/dist/modules/mysql/jobs/index.d.ts +1 -1
- package/dist/modules/mysql/jobs/kv.js +30 -0
- package/dist/modules/mysql/jobs/schema.d.ts +9 -0
- package/dist/modules/mysql/jobs/schema.js +21 -4
- package/dist/modules/mysql/schema.js +25 -0
- package/dist/modules/mysql/sessions.d.ts +1 -11
- package/dist/modules/mysql/sessions.js +6 -1
- package/dist/modules/realtime/declarations.d.ts +11 -0
- package/dist/modules/realtime/declarations.js +26 -0
- package/dist/modules/realtime/grants.d.ts +23 -0
- package/dist/modules/realtime/grants.js +61 -0
- package/dist/modules/realtime/handlers.d.ts +74 -0
- package/dist/modules/realtime/handlers.js +224 -0
- package/dist/modules/realtime/hub.d.ts +62 -0
- package/dist/modules/realtime/hub.js +141 -0
- package/dist/modules/realtime/index.d.ts +51 -0
- package/dist/modules/realtime/index.js +62 -0
- package/dist/modules/realtime/memoryPubSub.d.ts +10 -0
- package/dist/modules/realtime/memoryPubSub.js +43 -0
- package/dist/modules/realtime/realtime.test.d.ts +1 -0
- package/dist/modules/realtime/redisPubSub.d.ts +24 -0
- package/dist/modules/realtime/redisPubSub.js +36 -0
- package/dist/modules/realtime/redisPubSub.test.d.ts +1 -0
- package/dist/modules/realtime/socket.d.ts +25 -0
- package/dist/modules/realtime/socket.js +122 -0
- package/dist/modules/realtime/socket.test.d.ts +1 -0
- package/dist/modules/rsc/handler.d.ts +16 -0
- package/dist/modules/rsc/handler.js +17 -10
- package/dist/modules/rsc/handler.test.d.ts +1 -0
- package/dist/modules/rsc/resolveRscData.js +2 -1
- package/dist/modules/runtime/bundle.d.ts +24 -0
- package/dist/modules/runtime/bundle.js +102 -0
- package/dist/modules/runtime/contract.d.ts +37 -0
- package/dist/modules/runtime/contract.js +21 -0
- package/dist/modules/runtime/entry.test.d.ts +1 -0
- package/dist/modules/runtime/host.d.ts +38 -0
- package/dist/modules/runtime/host.js +68 -0
- package/dist/modules/runtime/inside.d.ts +15 -0
- package/dist/modules/runtime/inside.js +47 -0
- package/dist/modules/runtime/inside.test.d.ts +1 -0
- package/dist/modules/runtime/runner.d.ts +11 -0
- package/dist/modules/runtime/runner.js +38 -0
- package/dist/modules/runtime/runtime.test.d.ts +1 -0
- package/dist/modules/runtime/stages.d.ts +50 -0
- package/dist/modules/runtime/stages.js +117 -0
- package/dist/modules/ssr/Component.d.ts +3 -1
- package/dist/modules/ssr/Component.js +2 -1
- package/dist/modules/ssr/handler.js +10 -2
- package/dist/modules/ssr/loadPluginComponents.js +2 -1
- package/dist/modules/ssr/prepareRender.js +39 -10
- package/dist/modules/ssr/preview.d.ts +3 -0
- package/dist/modules/ssr/preview.js +17 -7
- package/dist/modules/ssr/redirect.test.d.ts +1 -0
- package/dist/modules/ssr/registerExternalPlugins.d.ts +6 -1
- package/dist/modules/ssr/registerExternalPlugins.js +19 -16
- package/dist/modules/ssr/registerExternalPlugins.test.d.ts +1 -0
- package/dist/modules/ssr/reportMissingPlugins.d.ts +9 -0
- package/dist/modules/ssr/reportMissingPlugins.js +24 -0
- package/dist/modules/ssr/reportMissingPlugins.test.d.ts +1 -0
- package/dist/modules/ssr/streamBody.d.ts +2 -2
- package/dist/modules/ssr/streamBody.js +4 -1
- package/dist/modules/ssr/template.js +1 -1
- package/dist/modules/ssr/views/template.ejs +8 -5
- package/dist/mysql.d.ts +1 -1
- package/dist/mysql.js +2 -2
- package/dist/oauth.js +2 -2
- package/dist/plugins/compile.js +9 -4
- package/dist/plugins/copy.js +3 -3
- package/dist/plugins/manager.d.ts +35 -3
- package/dist/plugins/manager.js +109 -38
- package/dist/runtime.d.ts +15 -0
- package/dist/runtime.js +7 -0
- package/package.json +39 -8
- package/skills/plitzi-authoring/SKILL.md +98 -14
- package/skills/plitzi-authoring/reference/accessibility.md +111 -0
- package/skills/plitzi-authoring/reference/authoring-errors.md +70 -0
- package/skills/plitzi-authoring/reference/data-and-visibility.md +84 -18
- package/skills/plitzi-authoring/reference/elements-and-styles.md +61 -7
- package/skills/plitzi-authoring/reference/flows.md +108 -17
- package/skills/plitzi-authoring/reference/lists.md +74 -0
- package/skills/plitzi-authoring/reference/performance.md +67 -0
- package/skills/plitzi-authoring/reference/plugins.md +167 -0
- package/skills/plitzi-authoring/reference/review-checklist.md +19 -2
- package/skills/plitzi-authoring/reference/templates.md +67 -27
- package/skills/plitzi-authoring/reference/testing.md +72 -5
- package/skills/plitzi-authoring/reference/validation.md +73 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { createServer, resolveServices } from './core/createServer';
|
|
2
2
|
export { closeOnSignals } from './core/server/closeOnSignals';
|
|
3
|
+
export { loadFunctions, readFunctionsDir } from './modules/functions/load';
|
|
3
4
|
export { registerHealthCheck, buildHealthPayload } from './core/health';
|
|
4
|
-
export { consoleLogger, renderLogEvent } from './helpers/serverLog';
|
|
5
|
+
export { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from './helpers/serverLog';
|
|
5
6
|
export type { HealthCheckApp, HealthIdentity } from './core/health';
|
|
6
7
|
export { createCloudAdapters } from './adapters/cloudAdapters';
|
|
7
8
|
export { createJsonAdapters } from './adapters/jsonAdapters';
|
|
@@ -9,6 +10,8 @@ export { createAuthAdapters } from './adapters/authAdapters';
|
|
|
9
10
|
export { authoringPreview, createMemoryCache, createSpaceAdapters, fixedSpace, presentsCredential, refuse, verifiedDomain, wildcardSubdomain } from './adapters/space';
|
|
10
11
|
export { createLocalFontStore, hostedPathsOf } from './core/fontStore';
|
|
11
12
|
export { createMemoryDraftStore, takeDraftOverride } from './modules/ssr/preview';
|
|
13
|
+
export { createMemoryPubSub } from './modules/realtime/memoryPubSub';
|
|
14
|
+
export { createRedisPubSub } from './modules/realtime/redisPubSub';
|
|
12
15
|
export { PREVIEW_TOKEN_PARAM } from './core/previewToken';
|
|
13
16
|
export { resolveRscData } from './modules/rsc/resolveRscData';
|
|
14
17
|
export { fetchConnectorRecords, rebaseMedia, writeConnectorRecord, createConnectorResolver } from './modules/connectors';
|
|
@@ -19,6 +22,8 @@ export type { AuthoringPreviewOptions, DeploymentRow, FrameAncestorsConfig, Spac
|
|
|
19
22
|
export type { RscElementResolver, RscResolveContext, ResolveRscDataOptions } from './modules/rsc/resolveRscData';
|
|
20
23
|
export type { ConnectorAuth, ConnectorCredential, ConnectorEndpoints, ConnectorFilter, ConnectorLookups, ConnectorManifest, ConnectorManifestDraft, ConnectorPageInfo, ConnectorPagination, ConnectorQuery, ConnectorReadEndpoint, ConnectorRecord, ConnectorResponseMapping, ConnectorResult, ProviderPagination } from './modules/connectors';
|
|
21
24
|
export type { FontStore, StoredFont } from './core/fontStore';
|
|
25
|
+
export type { PubSubAdapter, SSRRealtimeConfig } from '@plitzi/sdk-shared';
|
|
26
|
+
export type { RedisPubSubClients } from './modules/realtime/redisPubSub';
|
|
22
27
|
export type { ResolvedServices } from './core/createServer';
|
|
23
28
|
export type { Closable, CloseOnSignalsOptions } from './core/server/closeOnSignals';
|
|
24
29
|
export type { BaseContext, PipelineExtensions, SSRContext, Stage } from './core/http/types';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from "./helpers/serverLog.js";
|
|
1
2
|
import { fetchConnectorRecords, rebaseMedia, writeConnectorRecord } from "./modules/connectors/engine.js";
|
|
3
|
+
import { createMemoryPubSub } from "./modules/realtime/memoryPubSub.js";
|
|
2
4
|
import { createConnectorResolver } from "./modules/connectors/resolver.js";
|
|
3
5
|
import { resolveRscData } from "./modules/rsc/resolveRscData.js";
|
|
4
6
|
import { PREVIEW_TOKEN_PARAM } from "./core/previewToken.js";
|
|
@@ -7,7 +9,7 @@ import { resolveServices } from "./core/services/resolve.js";
|
|
|
7
9
|
import { buildHealthPayload, registerHealthCheck } from "./core/health.js";
|
|
8
10
|
import { createServer } from "./core/createServer.js";
|
|
9
11
|
import { closeOnSignals } from "./core/server/closeOnSignals.js";
|
|
10
|
-
import {
|
|
12
|
+
import { loadFunctions, readFunctionsDir } from "./modules/functions/load.js";
|
|
11
13
|
import { createCloudAdapters } from "./adapters/cloudAdapters.js";
|
|
12
14
|
import { createJsonAdapters } from "./adapters/jsonAdapters.js";
|
|
13
15
|
import { createAuthAdapters } from "./adapters/authAdapters.js";
|
|
@@ -15,4 +17,5 @@ import { createMemoryCache, refuse } from "./adapters/space/types.js";
|
|
|
15
17
|
import { authoringPreview, fixedSpace, presentsCredential, verifiedDomain, wildcardSubdomain } from "./adapters/space/resolvers.js";
|
|
16
18
|
import { createSpaceAdapters } from "./adapters/space/index.js";
|
|
17
19
|
import { createLocalFontStore, hostedPathsOf } from "./core/fontStore.js";
|
|
18
|
-
|
|
20
|
+
import { createRedisPubSub } from "./modules/realtime/redisPubSub.js";
|
|
21
|
+
export { PREVIEW_TOKEN_PARAM, authoringPreview, buildHealthPayload, closeOnSignals, consoleLogger, createAuthAdapters, createCloudAdapters, createConnectorResolver, createJsonAdapters, createLocalFontStore, createMemoryCache, createMemoryDraftStore, createMemoryPubSub, createRedisPubSub, createServer, createSpaceAdapters, fetchConnectorRecords, fixedSpace, hostedPathsOf, isLogged, loadFunctions, logLevelOf, presentsCredential, readFunctionsDir, rebaseMedia, refuse, registerHealthCheck, renderLogEvent, resolveRscData, resolveServices, serverLog, takeDraftOverride, verifiedDomain, wildcardSubdomain, writeConnectorRecord };
|
package/dist/kernel.d.ts
CHANGED
|
@@ -16,8 +16,9 @@ export { healthStage } from './core/http/stages/health';
|
|
|
16
16
|
export { configStaticStage, publicDirStage, wellKnownStage } from './core/http/stages/static';
|
|
17
17
|
export { buildHealthPayload, registerHealthCheck } from './core/health';
|
|
18
18
|
export { clientIp, parseRequest, readRawBody, requestOrigin } from './core/requestParser';
|
|
19
|
-
export { consoleLogger, renderLogEvent } from './helpers/serverLog';
|
|
19
|
+
export { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from './helpers/serverLog';
|
|
20
20
|
export { PREVIEW_TOKEN_PARAM } from './core/previewToken';
|
|
21
|
+
export { assertOutboundAllowed, isBlockedHost } from './helpers/outboundGuard';
|
|
21
22
|
export type { HttpServerParts } from './core/server/baseServer';
|
|
22
23
|
export type { BuildContext } from './core/http/dispatcher';
|
|
23
24
|
export type { HealthCheckApp, HealthIdentity } from './core/health';
|
package/dist/kernel.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { consoleLogger, isLogged, logLevelOf, renderLogEvent, serverLog } from "./helpers/serverLog.js";
|
|
2
|
+
import { assertOutboundAllowed, isBlockedHost } from "./helpers/outboundGuard.js";
|
|
1
3
|
import { clientIp, parseRequest, readRawBody, requestOrigin } from "./core/requestParser.js";
|
|
2
4
|
import { createHttpServer } from "./core/server/baseServer.js";
|
|
3
5
|
import { PREVIEW_TOKEN_PARAM } from "./core/previewToken.js";
|
|
@@ -5,5 +7,4 @@ import { makeHandler } from "./core/http/dispatcher.js";
|
|
|
5
7
|
import { buildHealthPayload, registerHealthCheck } from "./core/health.js";
|
|
6
8
|
import { healthStage } from "./core/http/stages/health.js";
|
|
7
9
|
import { configStaticStage, publicDirStage, wellKnownStage } from "./core/http/stages/static.js";
|
|
8
|
-
|
|
9
|
-
export { PREVIEW_TOKEN_PARAM, buildHealthPayload, clientIp, configStaticStage, consoleLogger, createHttpServer, healthStage, makeHandler, parseRequest, publicDirStage, readRawBody, registerHealthCheck, renderLogEvent, requestOrigin, wellKnownStage };
|
|
10
|
+
export { PREVIEW_TOKEN_PARAM, assertOutboundAllowed, buildHealthPayload, clientIp, configStaticStage, consoleLogger, createHttpServer, healthStage, isBlockedHost, isLogged, logLevelOf, makeHandler, parseRequest, publicDirStage, readRawBody, registerHealthCheck, renderLogEvent, requestOrigin, serverLog, wellKnownStage };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { serverLog } from "../../helpers/serverLog.js";
|
|
1
2
|
import { writeConnectorRecord } from "../connectors/engine.js";
|
|
2
3
|
//#region src/modules/actions/connectorWrite.ts
|
|
3
4
|
var parseBody = (body) => {
|
|
@@ -72,7 +73,7 @@ var handleAction = async (req, res, config, lookups) => {
|
|
|
72
73
|
res.setHeader("Cache-Control", "no-store");
|
|
73
74
|
res.send(JSON.stringify({ record: record ?? null }));
|
|
74
75
|
} catch (err) {
|
|
75
|
-
|
|
76
|
+
serverLog.error("Action", "connector write failed", err);
|
|
76
77
|
fail(res, 502, "Connector write failed");
|
|
77
78
|
}
|
|
78
79
|
};
|
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
import { ActionJobs } from './jobs';
|
|
2
2
|
import { RunGuards } from './runtime/guards';
|
|
3
3
|
import { ActionRunner } from './runtime/runAction';
|
|
4
|
-
import { ActionKvStore, ActionsConfig, ActionTaskRegistry, ResolvedActionLimits } from './types';
|
|
4
|
+
import { ActionKvStore, ActionsConfig, ActionTaskRegistry, ResolvedActionLimits, SpaceRevision } from './types';
|
|
5
|
+
import { FunctionsSource } from '../functions/build';
|
|
6
|
+
import { ManifestReading } from '../functions/manifest';
|
|
7
|
+
import { RouteHandler, RouteVisit } from '../functions/routes';
|
|
8
|
+
import { PreparedFunctions } from '../functions/space';
|
|
5
9
|
import { ActionDocument } from '@plitzi/sdk-shared';
|
|
6
10
|
export type ActionsModule = ActionRunner & {
|
|
11
|
+
/** The deployment's own tasks: shipped, and its native functions. */
|
|
7
12
|
registry: ActionTaskRegistry;
|
|
13
|
+
/**
|
|
14
|
+
* What a space's actions can use as of that revision: the deployment's tasks and the space's own functions — what
|
|
15
|
+
* its catalog offers, what a check checks against and what its runs run.
|
|
16
|
+
*/
|
|
17
|
+
registryFor: (spaceId: number, at?: SpaceRevision) => Promise<ActionTaskRegistry>;
|
|
18
|
+
/**
|
|
19
|
+
* A space's functions source, built, read and checked — ready to store, or the problems to show where they are. The
|
|
20
|
+
* one way a space's functions become storable; refused when this server has no runner.
|
|
21
|
+
*/
|
|
22
|
+
prepareFunctions: (source: FunctionsSource) => Promise<PreparedFunctions>;
|
|
23
|
+
/**
|
|
24
|
+
* What a space's code declares, read by every rule a saved space's functions meet — for code that is not built here:
|
|
25
|
+
* a space runtime's, described by the runtime itself when it starts. The manifest, and the problems that refuse it.
|
|
26
|
+
*/
|
|
27
|
+
readManifest: (declared: unknown) => ManifestReading;
|
|
28
|
+
/**
|
|
29
|
+
* The function that answers `method path` under `/api/` for this visit — the deployment's own routes, then the space's
|
|
30
|
+
* — or none, and the page server answers as it would have.
|
|
31
|
+
*/
|
|
32
|
+
routeFor: (visit: RouteVisit, method: string, path: string) => Promise<RouteHandler | undefined>;
|
|
8
33
|
guards: RunGuards;
|
|
9
34
|
/** The key/value store, namespaced to one space — the same one the `kv` tasks write through, so a rate limit the
|
|
10
35
|
* transport keeps and a counter a flow keeps cannot end up in different places. */
|
|
@@ -20,16 +45,10 @@ export type ActionsModule = ActionRunner & {
|
|
|
20
45
|
*/
|
|
21
46
|
jobs?: ActionJobs;
|
|
22
47
|
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
* Constructed rather than imported piecemeal so the task registry is validated ONCE, at boot, and so the guards
|
|
27
|
-
* are a single set for the process — two instances would each think they were the only run in flight, which is
|
|
28
|
-
* the same as having no single-flight at all. Nothing outside this folder needs to know how a run is assembled.
|
|
29
|
-
*/
|
|
30
|
-
export declare const createActionsModule: (config: ActionsConfig) => ActionsModule;
|
|
31
|
-
export { ActionRunError } from './runtime/errors';
|
|
48
|
+
export declare const createActionsModule: (given: ActionsConfig) => ActionsModule;
|
|
49
|
+
export { ActionRefusal, ActionRunError } from './runtime/errors';
|
|
32
50
|
export { precheckRun } from './runtime/precheck';
|
|
51
|
+
export { spaceKvPatterns } from './runtime/namespaceKv';
|
|
33
52
|
export { checkAction } from './runtime/check';
|
|
34
53
|
export { DEFAULT_LIMITS, resolveLimits } from './runtime/limits';
|
|
35
54
|
export { createRunGuards, deriveRunKey } from './runtime/guards';
|
|
@@ -2,15 +2,19 @@ import "./jobs/memoryQueue.js";
|
|
|
2
2
|
import "./jobs/scheduler.js";
|
|
3
3
|
import "./runtime/errors.js";
|
|
4
4
|
import "./jobs/worker.js";
|
|
5
|
+
import { fleetStore } from "../../core/server/fleet/link.js";
|
|
5
6
|
import { createActionJobs } from "./jobs/index.js";
|
|
6
7
|
import { createRunGuards } from "./runtime/guards.js";
|
|
7
8
|
import { createKvStore } from "./runtime/kvStore.js";
|
|
8
9
|
import { resolveLimits } from "./runtime/limits.js";
|
|
9
|
-
import { createMemoryKv } from "./runtime/memoryKv.js";
|
|
10
|
-
import { namespaceKv } from "./runtime/namespaceKv.js";
|
|
10
|
+
import { KV_METHODS, createMemoryKv } from "./runtime/memoryKv.js";
|
|
11
|
+
import { namespaceKv, spaceKvPatterns } from "./runtime/namespaceKv.js";
|
|
11
12
|
import "./runtime/precheck.js";
|
|
12
13
|
import { createActionRunner } from "./runtime/runAction.js";
|
|
13
14
|
import { createTaskRegistry } from "./tasks/registry.js";
|
|
15
|
+
import { readManifest } from "../functions/manifest.js";
|
|
16
|
+
import { createRoutes } from "../functions/routes.js";
|
|
17
|
+
import { createSpaceRegistries, prepareFunctions } from "../functions/space.js";
|
|
14
18
|
import "./runtime/check.js";
|
|
15
19
|
import "./runtime/runLogger.js";
|
|
16
20
|
import "./taskCatalog.js";
|
|
@@ -27,9 +31,32 @@ import { handleActionCancel } from "./transport/cancelHandler.js";
|
|
|
27
31
|
* are a single set for the process — two instances would each think they were the only run in flight, which is
|
|
28
32
|
* the same as having no single-flight at all. Nothing outside this folder needs to know how a run is assembled.
|
|
29
33
|
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The workers of one server are one replica, so with no `kv` configured they share the primary's: a flow's counter,
|
|
36
|
+
* a webhook's rate limit, a run's single-flight key, a cancel and a replayed answer then mean the same whichever
|
|
37
|
+
* worker the request lands on — the path a deployment with its own shared store already takes. One process keeps
|
|
38
|
+
* its own map.
|
|
39
|
+
*/
|
|
40
|
+
var withFleetKv = (config) => {
|
|
41
|
+
if (config.kv) return config;
|
|
42
|
+
return {
|
|
43
|
+
...config,
|
|
44
|
+
kv: fleetStore("actions.kv", KV_METHODS) ?? createMemoryKv()
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
var createActionsModule = (given) => {
|
|
48
|
+
const config = withFleetKv(given);
|
|
49
|
+
const registry = createTaskRegistry(config.functions?.native, { db: (config.dbDrivers?.length ?? 0) > 0 });
|
|
50
|
+
const spaceRegistries = createSpaceRegistries(registry, config.functions);
|
|
51
|
+
const reserved = new Set(registry.list().map((task) => task.namespace));
|
|
52
|
+
const registryFor = async (spaceId, at) => spaceRegistries.registryFor(await config.lookups.getFunctions?.(spaceId, at));
|
|
53
|
+
const registryForRun = (request) => Object.values(request.entry.document.nodes).every((node) => node.type !== "task" || !node.action || registry.get(node.action)) ? registry : registryFor(request.spaceId, request.at);
|
|
54
|
+
const { runAction, taskContext } = createActionRunner(config, registryForRun, config.fetchImpl);
|
|
55
|
+
const routes = createRoutes({
|
|
56
|
+
config: config.functions ?? {},
|
|
57
|
+
...config.lookups.getFunctions ? { getFunctions: config.lookups.getFunctions } : {},
|
|
58
|
+
taskContext
|
|
59
|
+
});
|
|
33
60
|
/**
|
|
34
61
|
* Single-flight over the store the deployment already gave the `kv` tasks — its own Redis, table or whatever it
|
|
35
62
|
* runs — because per process it is not a guarantee: the same double-click behind a load balancer lands on two
|
|
@@ -41,6 +68,16 @@ var createActionsModule = (config) => {
|
|
|
41
68
|
const module = {
|
|
42
69
|
runAction,
|
|
43
70
|
registry,
|
|
71
|
+
registryFor,
|
|
72
|
+
routeFor: routes.routeFor,
|
|
73
|
+
prepareFunctions: (source) => {
|
|
74
|
+
const runner = config.functions?.runner;
|
|
75
|
+
return runner ? prepareFunctions(source, runner, reserved) : Promise.resolve({
|
|
76
|
+
ok: false,
|
|
77
|
+
problems: [{ message: "This server runs no space functions" }]
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
readManifest: (declared) => readManifest(declared, reserved),
|
|
44
81
|
guards,
|
|
45
82
|
kv: (spaceId) => namespaceKv(kv, spaceId),
|
|
46
83
|
limitsFor
|
|
@@ -49,4 +86,4 @@ var createActionsModule = (config) => {
|
|
|
49
86
|
return module;
|
|
50
87
|
};
|
|
51
88
|
//#endregion
|
|
52
|
-
export { createActionsModule, handleActionCall, handleActionCancel, handleActionCatalog, handleActionWebhook };
|
|
89
|
+
export { createActionsModule, handleActionCall, handleActionCancel, handleActionCatalog, handleActionWebhook, spaceKvPatterns };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** How long a pass may keep failing before it is reported as the error it has become. */
|
|
2
|
+
export declare const FAILURE_STREAK_ESCALATION_MS = 60000;
|
|
3
|
+
export type FailureStreak = {
|
|
4
|
+
failed: (error: unknown) => void;
|
|
5
|
+
succeeded: () => void;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* How a pass that runs again by itself reports failing: a schedule sweep, a claim, a heartbeat.
|
|
9
|
+
*
|
|
10
|
+
* A store that drops its connections for a moment — a failover, a driver resetting its pool because the host stalled
|
|
11
|
+
* — fails one pass, and the next, seconds later, works. Nothing is lost: every pass is safe to repeat. Reported as an
|
|
12
|
+
* error with a stack, each of those read as an incident, and the ones that are an incident read the same.
|
|
13
|
+
*
|
|
14
|
+
* So the first failure of a streak is a warning with its reason; a streak still going after `escalateAfterMs` is the
|
|
15
|
+
* error, with the whole cause, once; and the pass that ends a streak that got that far says so.
|
|
16
|
+
*/
|
|
17
|
+
export declare const createFailureStreak: (scope: string, what: string, escalateAfterMs?: number, now?: () => number) => FailureStreak;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { serverLog } from "../../../helpers/serverLog.js";
|
|
2
|
+
//#region src/modules/actions/jobs/failureStreak.ts
|
|
3
|
+
/** How long a pass may keep failing before it is reported as the error it has become. */
|
|
4
|
+
var FAILURE_STREAK_ESCALATION_MS = 6e4;
|
|
5
|
+
var reasonOf = (error) => error instanceof Error ? error.message : String(error);
|
|
6
|
+
/**
|
|
7
|
+
* How a pass that runs again by itself reports failing: a schedule sweep, a claim, a heartbeat.
|
|
8
|
+
*
|
|
9
|
+
* A store that drops its connections for a moment — a failover, a driver resetting its pool because the host stalled
|
|
10
|
+
* — fails one pass, and the next, seconds later, works. Nothing is lost: every pass is safe to repeat. Reported as an
|
|
11
|
+
* error with a stack, each of those read as an incident, and the ones that are an incident read the same.
|
|
12
|
+
*
|
|
13
|
+
* So the first failure of a streak is a warning with its reason; a streak still going after `escalateAfterMs` is the
|
|
14
|
+
* error, with the whole cause, once; and the pass that ends a streak that got that far says so.
|
|
15
|
+
*/
|
|
16
|
+
var createFailureStreak = (scope, what, escalateAfterMs = FAILURE_STREAK_ESCALATION_MS, now = Date.now) => {
|
|
17
|
+
let since;
|
|
18
|
+
let failures = 0;
|
|
19
|
+
let escalated = false;
|
|
20
|
+
return {
|
|
21
|
+
failed: (error) => {
|
|
22
|
+
failures += 1;
|
|
23
|
+
if (since === void 0) {
|
|
24
|
+
since = now();
|
|
25
|
+
serverLog.warn(scope, `${what} failed, trying again`, reasonOf(error));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const elapsed = now() - since;
|
|
29
|
+
if (!escalated && elapsed >= escalateAfterMs) {
|
|
30
|
+
escalated = true;
|
|
31
|
+
serverLog.error(scope, `${what} has been failing for ${String(Math.round(elapsed / 1e3))}s`, error);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
succeeded: () => {
|
|
35
|
+
if (since === void 0) return;
|
|
36
|
+
if (escalated) {
|
|
37
|
+
const seconds = Math.round((now() - since) / 1e3);
|
|
38
|
+
serverLog.info(scope, `${what} is working again, after ${String(failures)} failures over ${String(seconds)}s`);
|
|
39
|
+
}
|
|
40
|
+
since = void 0;
|
|
41
|
+
failures = 0;
|
|
42
|
+
escalated = false;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { FAILURE_STREAK_ESCALATION_MS, createFailureStreak };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -20,7 +20,8 @@ export type ActionJobs = {
|
|
|
20
20
|
*
|
|
21
21
|
* With no `queue` supplied this is one process's memory, which is right for a single replica and wrong the moment
|
|
22
22
|
* there are two. That is a sentence rather than a silent behaviour because the failure is invisible: everything
|
|
23
|
-
* works, and the nightly email goes out once per replica.
|
|
23
|
+
* works, and the nightly email goes out once per replica. The workers of one server are one replica: they share
|
|
24
|
+
* the primary's queue, and only one of them runs the scheduler and the jobs (`runsFleetJobs`).
|
|
24
25
|
*/
|
|
25
26
|
export declare const createActionJobs: (config: ActionJobsConfig, module: ActionsModule, lookups: ActionLookups) => ActionJobs;
|
|
26
27
|
export { createMemoryJobQueue } from './memoryQueue';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { createMemoryJobQueue } from "./memoryQueue.js";
|
|
1
|
+
import { JOB_QUEUE_METHODS, createMemoryJobQueue } from "./memoryQueue.js";
|
|
2
2
|
import { DEFAULT_MAX_ATTEMPTS, scheduleFor, scheduleJobId, schedulesFor } from "./schedules.js";
|
|
3
3
|
import { createScheduler } from "./scheduler.js";
|
|
4
4
|
import { createJobWorker } from "./worker.js";
|
|
5
|
+
import { fleetStore } from "../../../core/server/fleet/link.js";
|
|
5
6
|
//#region src/modules/actions/jobs/index.ts
|
|
6
7
|
/**
|
|
7
8
|
* The scheduling half of actions: a producer, a consumer and the store they meet in.
|
|
@@ -13,10 +14,11 @@ import { createJobWorker } from "./worker.js";
|
|
|
13
14
|
*
|
|
14
15
|
* With no `queue` supplied this is one process's memory, which is right for a single replica and wrong the moment
|
|
15
16
|
* there are two. That is a sentence rather than a silent behaviour because the failure is invisible: everything
|
|
16
|
-
* works, and the nightly email goes out once per replica.
|
|
17
|
+
* works, and the nightly email goes out once per replica. The workers of one server are one replica: they share
|
|
18
|
+
* the primary's queue, and only one of them runs the scheduler and the jobs (`runsFleetJobs`).
|
|
17
19
|
*/
|
|
18
20
|
var createActionJobs = (config, module, lookups) => {
|
|
19
|
-
const queue = config.queue ?? createMemoryJobQueue();
|
|
21
|
+
const queue = config.queue ?? fleetStore("actions.jobs", JOB_QUEUE_METHODS) ?? createMemoryJobQueue();
|
|
20
22
|
const { produce = true, workers = 4 } = config;
|
|
21
23
|
const scheduler = createScheduler({
|
|
22
24
|
queue,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StoreMethods } from '../../../core/server/fleet/channel';
|
|
1
2
|
import { ActionJobQueue } from '@plitzi/sdk-shared';
|
|
2
3
|
export type MemoryJobQueueOptions = {
|
|
3
4
|
/**
|
|
@@ -16,6 +17,8 @@ export type MemoryJobQueueOptions = {
|
|
|
16
17
|
*/
|
|
17
18
|
clock?: () => number;
|
|
18
19
|
};
|
|
20
|
+
/** Every method of the queue, for the copy a server's workers share (see `fleet/stores.ts`). */
|
|
21
|
+
export declare const JOB_QUEUE_METHODS: StoreMethods<ActionJobQueue>;
|
|
19
22
|
/**
|
|
20
23
|
* The default queue: one process's Maps.
|
|
21
24
|
*
|
|
@@ -5,6 +5,22 @@ var TERMINAL = /* @__PURE__ */ new Set([
|
|
|
5
5
|
"dead",
|
|
6
6
|
"cancelled"
|
|
7
7
|
]);
|
|
8
|
+
/** Every method of the queue, for the copy a server's workers share (see `fleet/stores.ts`). */
|
|
9
|
+
var JOB_QUEUE_METHODS = {
|
|
10
|
+
now: true,
|
|
11
|
+
enqueue: true,
|
|
12
|
+
claim: true,
|
|
13
|
+
heartbeat: true,
|
|
14
|
+
settle: true,
|
|
15
|
+
dueSchedules: true,
|
|
16
|
+
advanceSchedule: true,
|
|
17
|
+
putSchedules: true,
|
|
18
|
+
listJobs: true,
|
|
19
|
+
getJob: true,
|
|
20
|
+
listSchedules: true,
|
|
21
|
+
requeue: true,
|
|
22
|
+
cancel: true
|
|
23
|
+
};
|
|
8
24
|
/**
|
|
9
25
|
* The default queue: one process's Maps.
|
|
10
26
|
*
|
|
@@ -175,4 +191,4 @@ var createMemoryJobQueue = ({ retainFinished = 500, clock = Date.now } = {}) =>
|
|
|
175
191
|
};
|
|
176
192
|
};
|
|
177
193
|
//#endregion
|
|
178
|
-
export { createMemoryJobQueue };
|
|
194
|
+
export { JOB_QUEUE_METHODS, createMemoryJobQueue };
|
|
@@ -16,6 +16,8 @@ export type SchedulerOptions = {
|
|
|
16
16
|
reconcileMs?: number;
|
|
17
17
|
/** The spaces to reconcile, for a server that serves a known few. `listScheduledSpaces` wins over it. */
|
|
18
18
|
spaces?: number[];
|
|
19
|
+
/** Every failed pass, in place of the default report — a warning, then an error once a pass has kept failing for a
|
|
20
|
+
* minute (see `createFailureStreak`). */
|
|
19
21
|
onError?: (error: unknown) => void;
|
|
20
22
|
};
|
|
21
23
|
export type SweepResult = {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { serverLog } from "../../../helpers/serverLog.js";
|
|
2
|
+
import { createFailureStreak } from "./failureStreak.js";
|
|
1
3
|
import { scheduleJobId, schedulesFor } from "./schedules.js";
|
|
2
4
|
import { cronFiresBetween, cronNextFire } from "@plitzi/sdk-shared/actions";
|
|
3
5
|
//#region src/modules/actions/jobs/scheduler.ts
|
|
@@ -25,7 +27,7 @@ var PARK_MS = 2108160 * MINUTE_MS;
|
|
|
25
27
|
* first occurrence after now, recording how many went by. A digest missed for a day sends once and says it missed
|
|
26
28
|
* 23 — rather than sending 23 times, which is how a scheduler that "catches up" turns an outage into an incident.
|
|
27
29
|
*/
|
|
28
|
-
var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, batch = 200, maxAttempts = 3, reconcileMs = 15 * MINUTE_MS, spaces, onError
|
|
30
|
+
var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, batch = 200, maxAttempts = 3, reconcileMs = 15 * MINUTE_MS, spaces, onError }) => {
|
|
29
31
|
let timer;
|
|
30
32
|
let reconcileTimer;
|
|
31
33
|
let running = false;
|
|
@@ -86,14 +88,17 @@ var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, ba
|
|
|
86
88
|
const reconcileAll = async () => {
|
|
87
89
|
for (const spaceId of await scheduledSpaces()) await reconcile(spaceId);
|
|
88
90
|
};
|
|
91
|
+
const sweepFailures = createFailureStreak("Actions", "schedule sweep");
|
|
92
|
+
const reconcileFailures = createFailureStreak("Actions", "schedule reconcile");
|
|
89
93
|
/** One pass at a time per replica: a sweep that outlives its interval must not have a second one land on top. */
|
|
90
|
-
const guarded = async (pass) => {
|
|
94
|
+
const guarded = async (pass, failures) => {
|
|
91
95
|
if (running) return;
|
|
92
96
|
running = true;
|
|
93
97
|
try {
|
|
94
98
|
await pass();
|
|
99
|
+
failures.succeeded();
|
|
95
100
|
} catch (error) {
|
|
96
|
-
onError(error);
|
|
101
|
+
(onError ?? failures.failed)(error);
|
|
97
102
|
} finally {
|
|
98
103
|
running = false;
|
|
99
104
|
}
|
|
@@ -103,14 +108,14 @@ var createScheduler = ({ queue, lookups, environment = "main", pollMs = 15e3, ba
|
|
|
103
108
|
reconcile,
|
|
104
109
|
start: () => {
|
|
105
110
|
if (timer) return;
|
|
106
|
-
timer = setInterval(() => void guarded(sweep), pollMs + Math.floor(Math.random() * 1e3));
|
|
111
|
+
timer = setInterval(() => void guarded(sweep, sweepFailures), pollMs + Math.floor(Math.random() * 1e3));
|
|
107
112
|
timer.unref();
|
|
108
113
|
if (!lookups.listScheduledSpaces && !spaces?.length) {
|
|
109
|
-
|
|
114
|
+
serverLog.warn("Actions", "schedules are running but nothing says which spaces to watch. Name them as `action.jobs.spaces`, or answer `action.lookups.listScheduledSpaces`.");
|
|
110
115
|
return;
|
|
111
116
|
}
|
|
112
|
-
guarded(reconcileAll);
|
|
113
|
-
reconcileTimer = setInterval(() => void guarded(reconcileAll), reconcileMs);
|
|
117
|
+
guarded(reconcileAll, reconcileFailures);
|
|
118
|
+
reconcileTimer = setInterval(() => void guarded(reconcileAll, reconcileFailures), reconcileMs);
|
|
114
119
|
reconcileTimer.unref();
|
|
115
120
|
},
|
|
116
121
|
stop: () => {
|
|
@@ -35,6 +35,8 @@ export type JobWorkerOptions = {
|
|
|
35
35
|
};
|
|
36
36
|
/** Names this replica in the job history, so a bad one is identifiable. Defaults to the process and a random id. */
|
|
37
37
|
workerId?: string;
|
|
38
|
+
/** Every failure, in place of the default report. By default a claim or a heartbeat that fails is a warning, and an
|
|
39
|
+
* error once it has kept failing for a minute (see `createFailureStreak`); anything else is an error at once. */
|
|
38
40
|
onError?: (error: unknown) => void;
|
|
39
41
|
};
|
|
40
42
|
export type JobWorker = {
|
|
@@ -59,4 +61,4 @@ export type JobWorker = {
|
|
|
59
61
|
stop: () => Promise<void>;
|
|
60
62
|
inFlight: () => number;
|
|
61
63
|
};
|
|
62
|
-
export declare const createJobWorker: ({ queue, lookups, module, workers, pollMs, leaseMs, backoff, workerId, onError }: JobWorkerOptions) => JobWorker;
|
|
64
|
+
export declare const createJobWorker: ({ queue, lookups, module, workers, pollMs, leaseMs, backoff, workerId, onError: customOnError }: JobWorkerOptions) => JobWorker;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { serverLog } from "../../../helpers/serverLog.js";
|
|
2
|
+
import { createFailureStreak } from "./failureStreak.js";
|
|
1
3
|
import { ActionRunError } from "../runtime/errors.js";
|
|
2
4
|
import { randomUUID } from "node:crypto";
|
|
3
5
|
//#region src/modules/actions/jobs/worker.ts
|
|
@@ -31,7 +33,10 @@ var GIVE_UP = /* @__PURE__ */ new Set([
|
|
|
31
33
|
"forbidden",
|
|
32
34
|
"recursion"
|
|
33
35
|
]);
|
|
34
|
-
var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leaseMs = 3e4, backoff = {}, workerId = `${process.pid}-${randomUUID().slice(0, 8)}`, onError
|
|
36
|
+
var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leaseMs = 3e4, backoff = {}, workerId = `${process.pid}-${randomUUID().slice(0, 8)}`, onError: customOnError }) => {
|
|
37
|
+
const onError = customOnError ?? ((error) => serverLog.error("Actions", "job worker failed", error));
|
|
38
|
+
const claimFailures = createFailureStreak("Actions", "job claim");
|
|
39
|
+
const heartbeatFailures = createFailureStreak("Actions", "job heartbeat");
|
|
35
40
|
const { baseMs = 3e4, maxMs = 9e5 } = backoff;
|
|
36
41
|
const active = /* @__PURE__ */ new Map();
|
|
37
42
|
/** Every job this worker started, until it has settled — what `stop()` waits for. */
|
|
@@ -223,7 +228,7 @@ var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leas
|
|
|
223
228
|
/** One pass at a time, and the one under way is kept so `stop()` can wait for the claim it may be making. */
|
|
224
229
|
const guarded = async () => {
|
|
225
230
|
if (pass) return;
|
|
226
|
-
pass = poll().then(() =>
|
|
231
|
+
pass = poll().then(() => claimFailures.succeeded()).catch(customOnError ?? claimFailures.failed).finally(() => {
|
|
227
232
|
pass = void 0;
|
|
228
233
|
});
|
|
229
234
|
await pass;
|
|
@@ -236,7 +241,7 @@ var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leas
|
|
|
236
241
|
if (timer || workers <= 0) return;
|
|
237
242
|
timer = setInterval(() => void guarded(), pollMs);
|
|
238
243
|
timer.unref();
|
|
239
|
-
heart = setInterval(() => void beat().catch(
|
|
244
|
+
heart = setInterval(() => void beat().then(() => heartbeatFailures.succeeded()).catch(customOnError ?? heartbeatFailures.failed), Math.max(1e3, Math.floor(leaseMs / 3)));
|
|
240
245
|
heart.unref();
|
|
241
246
|
},
|
|
242
247
|
stop: async () => {
|
|
@@ -244,7 +249,7 @@ var createJobWorker = ({ queue, lookups, module, workers = 4, pollMs = 1e3, leas
|
|
|
244
249
|
clearInterval(timer);
|
|
245
250
|
timer = void 0;
|
|
246
251
|
await pass;
|
|
247
|
-
if (inFlight.size > 0)
|
|
252
|
+
if (inFlight.size > 0) serverLog.info("Actions", `waiting for ${inFlight.size} running job(s) to finish before stopping`);
|
|
248
253
|
/**
|
|
249
254
|
* Drained rather than abandoned: a deploy finishes the jobs it started instead of leaving them to be retried.
|
|
250
255
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createActionsModule } from "./index.js";
|
|
2
|
+
import { realtimeModuleFor } from "../realtime/index.js";
|
|
2
3
|
//#region src/modules/actions/moduleFor.ts
|
|
3
4
|
/**
|
|
4
5
|
* The one actions module for a server, whoever asks first.
|
|
@@ -19,16 +20,18 @@ var actionsModuleFor = (config) => {
|
|
|
19
20
|
if (existing) return existing;
|
|
20
21
|
const module = createActionsModule({
|
|
21
22
|
lookups,
|
|
22
|
-
|
|
23
|
+
functions: config.functions,
|
|
23
24
|
limits: config.action?.limits,
|
|
24
25
|
concurrency: config.action?.concurrency,
|
|
25
26
|
kv: config.action?.kv,
|
|
26
27
|
jobs: config.action?.jobs,
|
|
27
28
|
rateLimit: config.action?.rateLimit,
|
|
28
29
|
idempotency: config.action?.idempotency,
|
|
30
|
+
signingSecret: config.action?.signingSecret,
|
|
29
31
|
dbDrivers: config.action?.dbDrivers,
|
|
30
32
|
email: config.action?.email,
|
|
31
|
-
onRun: config.action?.onRun
|
|
33
|
+
onRun: config.action?.onRun,
|
|
34
|
+
realtime: realtimeModuleFor(config)
|
|
32
35
|
});
|
|
33
36
|
modules.set(config, module);
|
|
34
37
|
return module;
|
|
@@ -14,3 +14,15 @@ export declare class ActionRunError extends Error {
|
|
|
14
14
|
steps?: ActionRunStep[];
|
|
15
15
|
constructor(reason: ActionErrorReason, message: string);
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* A step refusing to go on, with a reason written for whoever called — a password too easy to guess, a board that is
|
|
19
|
+
* read-only, a quota reached.
|
|
20
|
+
*
|
|
21
|
+
* What any other step throws stays in the run's record and never reaches the caller: an error can carry a query, a
|
|
22
|
+
* URL, a credential's name, and a page is shown to anybody. This one says, by its type, that its message was written
|
|
23
|
+
* to be read. A run that ends on it answers `status: 'failed'` with the message as `error`, which a page's flow reads
|
|
24
|
+
* as `{{ step.error }}` — the same place a refusal before the run began puts its own.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ActionRefusal extends Error {
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
@@ -18,5 +18,20 @@ var ActionRunError = class extends Error {
|
|
|
18
18
|
this.reason = reason;
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* A step refusing to go on, with a reason written for whoever called — a password too easy to guess, a board that is
|
|
23
|
+
* read-only, a quota reached.
|
|
24
|
+
*
|
|
25
|
+
* What any other step throws stays in the run's record and never reaches the caller: an error can carry a query, a
|
|
26
|
+
* URL, a credential's name, and a page is shown to anybody. This one says, by its type, that its message was written
|
|
27
|
+
* to be read. A run that ends on it answers `status: 'failed'` with the message as `error`, which a page's flow reads
|
|
28
|
+
* as `{{ step.error }}` — the same place a refusal before the run began puts its own.
|
|
29
|
+
*/
|
|
30
|
+
var ActionRefusal = class extends Error {
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "ActionRefusal";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
21
36
|
//#endregion
|
|
22
|
-
export { ActionRunError };
|
|
37
|
+
export { ActionRefusal, ActionRunError };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** What a change needs of a store: read a key, and write it only if it still holds what was read. */
|
|
2
|
+
export type KvChangeStore<V> = {
|
|
3
|
+
get: (key: string) => Promise<V | undefined>;
|
|
4
|
+
swap: (key: string, expected: V | undefined, next: V, ttlSeconds?: number) => Promise<boolean>;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* The lifetime a change writes with: a number of seconds, one worked out from the value written, or none.
|
|
8
|
+
*/
|
|
9
|
+
export type KvChangeLifetime<T> = number | ((next: T) => number | undefined);
|
|
10
|
+
export type KvChangeOptions<T> = {
|
|
11
|
+
lifetime?: KvChangeLifetime<T> | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* The error a change that kept losing ends with — an `ActionRefusal` where there is one to make: being too busy is
|
|
14
|
+
* something to tell whoever asked, not a fault. Handed in because this function may import nothing.
|
|
15
|
+
*/
|
|
16
|
+
refusal: (message: string) => Error;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Reads `key`, hands its value to `change`, and writes back what that answers — unless somebody wrote in between, and
|
|
20
|
+
* then it reads again and asks again. `change` answering `undefined` writes nothing. Answers what was written, or
|
|
21
|
+
* `undefined` when nothing was. Losing every time ends in `refusal`, whose message names no key: it is for a visitor.
|
|
22
|
+
*
|
|
23
|
+
* The one read-change-write there is: `ctx.kv.change`, a list's writes, and the sandbox's `ctx.kv.change` too — its
|
|
24
|
+
* guest is handed THIS function's source (`isolate.ts`), so it must stay self-contained: no import, nothing of this
|
|
25
|
+
* module's, only what the guest's globals also have (`setTimeout`, `Math`).
|
|
26
|
+
*/
|
|
27
|
+
export declare const changeKv: <V, T extends V>(store: KvChangeStore<V>, key: string, change: (current: V | undefined) => T | undefined | Promise<T | undefined>, { lifetime, refusal }: KvChangeOptions<T>) => Promise<T | undefined>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/modules/actions/runtime/kvChange.ts
|
|
2
|
+
/**
|
|
3
|
+
* Reads `key`, hands its value to `change`, and writes back what that answers — unless somebody wrote in between, and
|
|
4
|
+
* then it reads again and asks again. `change` answering `undefined` writes nothing. Answers what was written, or
|
|
5
|
+
* `undefined` when nothing was. Losing every time ends in `refusal`, whose message names no key: it is for a visitor.
|
|
6
|
+
*
|
|
7
|
+
* The one read-change-write there is: `ctx.kv.change`, a list's writes, and the sandbox's `ctx.kv.change` too — its
|
|
8
|
+
* guest is handed THIS function's source (`isolate.ts`), so it must stay self-contained: no import, nothing of this
|
|
9
|
+
* module's, only what the guest's globals also have (`setTimeout`, `Math`).
|
|
10
|
+
*/
|
|
11
|
+
var changeKv = async (store, key, change, { lifetime, refusal }) => {
|
|
12
|
+
const attempts = 25;
|
|
13
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
14
|
+
const current = await store.get(key);
|
|
15
|
+
const next = await change(current);
|
|
16
|
+
if (next === void 0) return;
|
|
17
|
+
if (await store.swap(key, current, next, typeof lifetime === "function" ? lifetime(next) : lifetime)) return next;
|
|
18
|
+
await new Promise((resolve) => setTimeout(resolve, Math.random() * Math.min(5 + attempt * 5, 50)));
|
|
19
|
+
}
|
|
20
|
+
throw refusal("Many people are changing this at once — try again in a moment");
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { changeKv };
|