@db3.ai/app 0.1.0-beta.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -17
- package/agent-instructions.md +76 -0
- package/dist/ai/AIErrors.d.ts +7 -1
- package/dist/ai/AIErrors.js +8 -1
- package/dist/ai/AIFailover.d.ts +10 -0
- package/dist/ai/AIFailover.js +3 -2
- package/dist/ai/AIProviderAdmission.d.ts +101 -0
- package/dist/ai/AIProviderAdmission.js +336 -0
- package/dist/ai/AIRateLimiter.d.ts +11 -2
- package/dist/ai/AIRateLimiter.js +125 -10
- package/dist/ai/AIRequestTrackingError.d.ts +22 -0
- package/dist/ai/AIRequestTrackingError.js +33 -0
- package/dist/ai/Agent.d.ts +7 -7
- package/dist/ai/Agent.js +84 -56
- package/dist/ai/Ai.d.ts +11 -3
- package/dist/ai/Ai.js +94 -44
- package/dist/ai/OpenAIProviderError.js +1 -1
- package/dist/ai/ProviderSseObserver.d.ts +19 -0
- package/dist/ai/ProviderSseObserver.js +98 -0
- package/dist/ai/aiServiceTier.d.ts +5 -0
- package/dist/ai/aiServiceTier.js +14 -0
- package/dist/ai/chunkEmbeddingText.d.ts +14 -0
- package/dist/ai/chunkEmbeddingText.js +147 -0
- package/dist/ai/contracts/AI.d.ts +16 -0
- package/dist/ai/contracts/AIRequestErrorDiagnostics.d.ts +12 -0
- package/dist/ai/contracts/AIRequestErrorDiagnostics.js +1 -0
- package/dist/ai/contracts/AIServiceTier.d.ts +2 -0
- package/dist/ai/contracts/AIServiceTier.js +1 -0
- package/dist/ai/contracts/Agent.d.ts +3 -0
- package/dist/ai/contracts/EmbeddingTextChunk.d.ts +25 -0
- package/dist/ai/contracts/EmbeddingTextChunk.js +1 -0
- package/dist/ai/contracts/Pricing.d.ts +7 -1
- package/dist/ai/contracts/Providers.d.ts +2 -0
- package/dist/ai/contracts/index.d.ts +2 -0
- package/dist/ai/contracts/index.js +1 -0
- package/dist/ai/index.d.ts +8 -2
- package/dist/ai/index.js +5 -2
- package/dist/ai/{Models.d.ts → modelPricing.d.ts} +2 -2
- package/dist/ai/{Models.js → modelPricing.js} +38 -4
- package/dist/apps/AppInstallation.d.ts +21 -0
- package/dist/apps/AppInstallation.js +16 -0
- package/dist/apps/AppRouteError.d.ts +6 -0
- package/dist/apps/AppRouteError.js +10 -0
- package/dist/apps/AppService.d.ts +24 -0
- package/dist/apps/AppService.js +21 -0
- package/dist/apps/Apps.d.ts +59 -0
- package/dist/apps/Apps.js +566 -0
- package/dist/apps/appsPlugin.d.ts +3 -0
- package/dist/apps/appsPlugin.js +36 -0
- package/dist/apps/commands/disableApp.d.ts +2 -0
- package/dist/apps/commands/disableApp.js +5 -0
- package/dist/apps/commands/enableApp.d.ts +2 -0
- package/dist/apps/commands/enableApp.js +5 -0
- package/dist/apps/commands/index.d.ts +10 -0
- package/dist/apps/commands/index.js +27 -0
- package/dist/apps/commands/installApp.d.ts +2 -0
- package/dist/apps/commands/installApp.js +5 -0
- package/dist/apps/commands/listApps.d.ts +2 -0
- package/dist/apps/commands/listApps.js +5 -0
- package/dist/apps/commands/makeAppMigration.d.ts +2 -0
- package/dist/apps/commands/makeAppMigration.js +9 -0
- package/dist/apps/commands/rollbackApp.d.ts +2 -0
- package/dist/apps/commands/rollbackApp.js +5 -0
- package/dist/apps/commands/uninstallApp.d.ts +2 -0
- package/dist/apps/commands/uninstallApp.js +5 -0
- package/dist/apps/contracts/AppAction.d.ts +2 -0
- package/dist/apps/contracts/AppAction.js +1 -0
- package/dist/apps/contracts/AppDefinition.d.ts +45 -0
- package/dist/apps/contracts/AppDefinition.js +1 -0
- package/dist/apps/contracts/AppDescription.d.ts +32 -0
- package/dist/apps/contracts/AppDescription.js +1 -0
- package/dist/apps/contracts/AppManifest.d.ts +30 -0
- package/dist/apps/contracts/AppManifest.js +1 -0
- package/dist/apps/contracts/AppNavigation.d.ts +9 -0
- package/dist/apps/contracts/AppNavigation.js +1 -0
- package/dist/apps/contracts/AppNavigationBadge.d.ts +6 -0
- package/dist/apps/contracts/AppNavigationBadge.js +1 -0
- package/dist/apps/contracts/AppNavigationContext.d.ts +8 -0
- package/dist/apps/contracts/AppNavigationContext.js +1 -0
- package/dist/apps/contracts/AppNavigationResult.d.ts +12 -0
- package/dist/apps/contracts/AppNavigationResult.js +1 -0
- package/dist/apps/contracts/AppRoute.d.ts +19 -0
- package/dist/apps/contracts/AppRoute.js +1 -0
- package/dist/apps/contracts/DiscoveredApp.d.ts +10 -0
- package/dist/apps/contracts/DiscoveredApp.js +1 -0
- package/dist/apps/contracts/InstalledApps.d.ts +3 -0
- package/dist/apps/contracts/InstalledApps.js +1 -0
- package/dist/apps/contracts/index.d.ts +11 -0
- package/dist/apps/contracts/index.js +1 -0
- package/dist/apps/defineApp.d.ts +7 -0
- package/dist/apps/defineApp.js +8 -0
- package/dist/apps/discoverApps.d.ts +3 -0
- package/dist/apps/discoverApps.js +62 -0
- package/dist/apps/fastify.d.ts +1 -0
- package/dist/apps/fastify.js +1 -0
- package/dist/apps/index.d.ts +7 -0
- package/dist/apps/index.js +7 -0
- package/dist/apps/normalizeAppNavigation.d.ts +3 -0
- package/dist/apps/normalizeAppNavigation.js +30 -0
- package/dist/apps/registerAppRoutes.d.ts +6 -0
- package/dist/apps/registerAppRoutes.js +52 -0
- package/dist/apps/validateAppDefinitions.d.ts +3 -0
- package/dist/apps/validateAppDefinitions.js +65 -0
- package/dist/apps/vite.d.ts +1 -0
- package/dist/apps/vite.js +1 -0
- package/dist/apps/writeAppTypes.d.ts +2 -0
- package/dist/apps/writeAppTypes.js +13 -0
- package/dist/auth/Auth.d.ts +18 -0
- package/dist/auth/Auth.js +89 -13
- package/dist/auth/PasswordLoginAttempt.d.ts +50 -0
- package/dist/auth/PasswordLoginAttempt.js +60 -0
- package/dist/auth/PasswordSuspendedError.d.ts +10 -0
- package/dist/auth/PasswordSuspendedError.js +13 -0
- package/dist/auth/contracts/PasswordAuthProviderOptions.d.ts +26 -0
- package/dist/auth/contracts/PasswordAuthProviderOptions.js +1 -0
- package/dist/auth/contracts/PasswordSuspension.d.ts +7 -0
- package/dist/auth/contracts/PasswordSuspension.js +1 -0
- package/dist/auth/contracts/PasswordSuspensionOptions.d.ts +10 -0
- package/dist/auth/contracts/PasswordSuspensionOptions.js +1 -0
- package/dist/auth/contracts/index.d.ts +3 -0
- package/dist/auth/contracts/index.js +3 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/providers/PasswordAuthProvider.d.ts +19 -23
- package/dist/auth/providers/PasswordAuthProvider.js +96 -8
- package/dist/auth/providers/resolveAuthProviders.js +1 -0
- package/dist/cli/Cli.d.ts +2 -0
- package/dist/cli/Cli.js +8 -0
- package/dist/cli/commands/repl.js +2 -1
- package/dist/cli/contracts/CliCommand.d.ts +2 -0
- package/dist/cli/contracts/CliCommandInfo.d.ts +12 -0
- package/dist/cli/contracts/CliCommandInfo.js +1 -0
- package/dist/cli/contracts/index.d.ts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/listDb3Commands.d.ts +8 -0
- package/dist/cli/listDb3Commands.js +10 -0
- package/dist/cli/runDb3.d.ts +3 -6
- package/dist/cli/runDb3.js +5 -59
- package/dist/cli/withDb3Cli.d.ts +4 -0
- package/dist/cli/withDb3Cli.js +60 -0
- package/dist/db/ActiveQueryBuilder.d.ts +8 -0
- package/dist/db/ActiveQueryBuilder.js +11 -0
- package/dist/db/ActiveRecord.d.ts +6 -0
- package/dist/db/ActiveRecord.js +8 -0
- package/dist/db/connection.js +14 -2
- package/dist/db/fields/TimestampField.d.ts +1 -1
- package/dist/db/fields/TimestampField.js +7 -12
- package/dist/db/migrations/DatabaseMigrationManager.d.ts +3 -1
- package/dist/db/migrations/DatabaseMigrationManager.js +9 -3
- package/dist/db/migrations/contracts/DatabaseMigration.d.ts +7 -0
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +1 -1
- package/dist/db/migrations/{KnexMigrationRenderer.d.ts → renderKnexMigration.d.ts} +4 -3
- package/dist/db/migrations/{KnexMigrationRenderer.js → renderKnexMigration.js} +7 -6
- package/dist/flows/FlowCompiler.js +1 -1
- package/dist/flows/Flows.js +1 -1
- package/dist/flows/index.d.ts +1 -1
- package/dist/flows/index.js +1 -1
- package/dist/health/Health.d.ts +41 -0
- package/dist/health/Health.js +153 -0
- package/dist/health/contracts/Health.d.ts +36 -0
- package/dist/health/contracts/Health.js +1 -0
- package/dist/health/contracts/HealthHttp.d.ts +15 -0
- package/dist/health/contracts/HealthHttp.js +1 -0
- package/dist/health/contracts/index.d.ts +2 -0
- package/dist/health/contracts/index.js +1 -0
- package/dist/health/databaseHealthCheck.d.ts +15 -0
- package/dist/health/databaseHealthCheck.js +18 -0
- package/dist/health/fastify.d.ts +13 -0
- package/dist/health/fastify.js +44 -0
- package/dist/health/index.d.ts +3 -0
- package/dist/health/index.js +2 -0
- package/dist/in-app/InApp.d.ts +33 -0
- package/dist/in-app/InApp.js +191 -0
- package/dist/in-app/InAppError.d.ts +6 -0
- package/dist/in-app/InAppError.js +10 -0
- package/dist/in-app/InAppRecord.d.ts +36 -0
- package/dist/in-app/InAppRecord.js +24 -0
- package/dist/in-app/contracts/InAppInbox.d.ts +45 -0
- package/dist/in-app/contracts/InAppInbox.js +1 -0
- package/dist/in-app/contracts/InAppMessage.d.ts +22 -0
- package/dist/in-app/contracts/InAppMessage.js +1 -0
- package/dist/in-app/contracts/InAppScope.d.ts +17 -0
- package/dist/in-app/contracts/InAppScope.js +1 -0
- package/dist/in-app/contracts/index.d.ts +3 -0
- package/dist/in-app/contracts/index.js +3 -0
- package/dist/in-app/index.d.ts +4 -0
- package/dist/in-app/index.js +4 -0
- package/dist/in-app/validation.d.ts +21 -0
- package/dist/in-app/validation.js +50 -0
- package/dist/index.d.ts +2 -14
- package/dist/index.js +2 -5
- package/dist/logging/DevelopmentConsole.d.ts +42 -0
- package/dist/logging/DevelopmentConsole.js +162 -0
- package/dist/logging/Log.d.ts +3 -1
- package/dist/logging/Log.js +5 -2
- package/dist/logging/PrettyLogFormatter.d.ts +16 -0
- package/dist/logging/PrettyLogFormatter.js +151 -0
- package/dist/logging/acquireDevelopmentConsole.d.ts +6 -0
- package/dist/logging/acquireDevelopmentConsole.js +21 -0
- package/dist/logging/contracts/DevelopmentConsoleOptions.d.ts +16 -0
- package/dist/logging/contracts/DevelopmentConsoleOptions.js +1 -0
- package/dist/logging/contracts/EmailLogOptions.d.ts +8 -0
- package/dist/logging/contracts/EmailLogOptions.js +1 -0
- package/dist/logging/contracts/HttpExchangeMonitorOptions.d.ts +12 -0
- package/dist/logging/contracts/HttpExchangeMonitorOptions.js +1 -0
- package/dist/logging/contracts/LogTransportOptions.d.ts +19 -0
- package/dist/logging/contracts/LogTransportOptions.js +1 -0
- package/dist/logging/contracts/LoggingOptions.d.ts +12 -1
- package/dist/logging/contracts/index.d.ts +4 -0
- package/dist/logging/contracts/index.js +4 -0
- package/dist/logging/drivers/PinoLoggerDriver.d.ts +3 -1
- package/dist/logging/drivers/PinoLoggerDriver.js +75 -16
- package/dist/logging/formatLogEmail.d.ts +4 -0
- package/dist/logging/formatLogEmail.js +21 -0
- package/dist/logging/highlightQueueMessage.d.ts +11 -0
- package/dist/logging/highlightQueueMessage.js +36 -0
- package/dist/logging/httpBodyCapture.d.ts +24 -0
- package/dist/logging/httpBodyCapture.js +321 -0
- package/dist/logging/index.d.ts +2 -0
- package/dist/logging/index.js +2 -0
- package/dist/logging/redactLogEmail.d.ts +2 -0
- package/dist/logging/redactLogEmail.js +12 -0
- package/dist/logging/registerHttpExchangeMonitor.d.ts +10 -0
- package/dist/logging/registerHttpExchangeMonitor.js +43 -0
- package/dist/logging/transports/EmailLogTransport.d.ts +18 -0
- package/dist/logging/transports/EmailLogTransport.js +47 -0
- package/dist/mail/Mail.d.ts +2 -0
- package/dist/mail/Mail.js +3 -0
- package/dist/mail/MailDeliveryError.d.ts +9 -0
- package/dist/mail/MailDeliveryError.js +16 -0
- package/dist/mail/index.d.ts +1 -0
- package/dist/mail/index.js +1 -0
- package/dist/mail/transports/MailgunTransport.js +2 -0
- package/dist/mail/transports/ResendTransport.d.ts +3 -2
- package/dist/mail/transports/ResendTransport.js +22 -14
- package/dist/media/MediaManager.d.ts +4 -2
- package/dist/media/MediaManager.js +40 -8
- package/dist/network/BlockedUrlError.d.ts +16 -0
- package/dist/network/BlockedUrlError.js +19 -0
- package/dist/network/assertPublicUrl.d.ts +22 -0
- package/dist/network/assertPublicUrl.js +67 -0
- package/dist/network/contracts/GuardedFetch.d.ts +35 -0
- package/dist/network/contracts/GuardedFetch.js +1 -0
- package/dist/network/contracts/PublicUrlOptions.d.ts +17 -0
- package/dist/network/contracts/PublicUrlOptions.js +1 -0
- package/dist/network/contracts/index.d.ts +2 -0
- package/dist/network/contracts/index.js +2 -0
- package/dist/network/guardedFetch.d.ts +29 -0
- package/dist/network/guardedFetch.js +133 -0
- package/dist/network/index.d.ts +6 -0
- package/dist/network/index.js +6 -0
- package/dist/network/playwright/GuardedBrowserProxy.d.ts +32 -0
- package/dist/network/playwright/GuardedBrowserProxy.js +172 -0
- package/dist/network/playwright/contracts/GuardedBrowserContextOptions.d.ts +37 -0
- package/dist/network/playwright/contracts/GuardedBrowserContextOptions.js +1 -0
- package/dist/network/playwright/contracts/index.d.ts +1 -0
- package/dist/network/playwright/contracts/index.js +1 -0
- package/dist/network/playwright/index.d.ts +2 -0
- package/dist/network/playwright/index.js +2 -0
- package/dist/network/playwright/newGuardedBrowserContext.d.ts +21 -0
- package/dist/network/playwright/newGuardedBrowserContext.js +86 -0
- package/dist/network/privateNetworkAddresses.d.ts +44 -0
- package/dist/network/privateNetworkAddresses.js +157 -0
- package/dist/network/publicAddressLookup.d.ts +26 -0
- package/dist/network/publicAddressLookup.js +42 -0
- package/dist/notifications/Notifications.d.ts +27 -0
- package/dist/notifications/Notifications.js +99 -0
- package/dist/notifications/contracts/Notification.d.ts +56 -0
- package/dist/notifications/contracts/Notification.js +1 -0
- package/dist/notifications/contracts/NotificationDelivery.d.ts +11 -0
- package/dist/notifications/contracts/NotificationDelivery.js +1 -0
- package/dist/notifications/contracts/index.d.ts +2 -0
- package/dist/notifications/contracts/index.js +2 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +2 -0
- package/dist/queue/JobRunAttempt.d.ts +16 -0
- package/dist/queue/JobRunAttempt.js +17 -0
- package/dist/queue/JobRunEvent.d.ts +15 -0
- package/dist/queue/JobRunEvent.js +16 -0
- package/dist/queue/JobRunStoppedError.d.ts +6 -0
- package/dist/queue/JobRunStoppedError.js +10 -0
- package/dist/queue/Queue.d.ts +19 -4
- package/dist/queue/Queue.js +122 -9
- package/dist/queue/QueueTerminalError.d.ts +9 -0
- package/dist/queue/QueueTerminalError.js +12 -0
- package/dist/queue/QueueWorker.d.ts +12 -5
- package/dist/queue/QueueWorker.js +94 -9
- package/dist/queue/QueueWorkerReporter.d.ts +17 -0
- package/dist/queue/QueueWorkerReporter.js +71 -0
- package/dist/queue/QueueableJob.d.ts +2 -2
- package/dist/queue/RunnableJob.d.ts +78 -0
- package/dist/queue/RunnableJob.js +284 -0
- package/dist/queue/console.d.ts +8 -0
- package/dist/queue/console.js +53 -19
- package/dist/queue/contracts/QueueDriver.d.ts +8 -0
- package/dist/queue/contracts/QueueJobRunner.d.ts +4 -0
- package/dist/queue/contracts/QueueJobRunner.js +1 -0
- package/dist/queue/contracts/QueuePayload.d.ts +1 -1
- package/dist/queue/contracts/QueueSelection.d.ts +11 -0
- package/dist/queue/contracts/QueueSelection.js +1 -0
- package/dist/queue/contracts/QueueService.d.ts +18 -4
- package/dist/queue/contracts/QueueWorkerLifecycle.d.ts +2 -2
- package/dist/queue/contracts/QueueWorkerSnapshot.d.ts +14 -0
- package/dist/queue/contracts/QueueWorkerSnapshot.js +1 -0
- package/dist/queue/contracts/QueueableJob.d.ts +7 -3
- package/dist/queue/contracts/QueueableJobContract.d.ts +12 -0
- package/dist/queue/contracts/QueueableJobContract.js +1 -0
- package/dist/queue/contracts/index.d.ts +4 -0
- package/dist/queue/contracts/index.js +2 -0
- package/dist/queue/drivers/DatabaseQueueDriver.d.ts +4 -0
- package/dist/queue/drivers/DatabaseQueueDriver.js +27 -3
- package/dist/queue/drivers/RedisQueueDriver.d.ts +7 -0
- package/dist/queue/drivers/RedisQueueDriver.js +37 -0
- package/dist/queue/index.d.ts +5 -0
- package/dist/queue/index.js +5 -0
- package/dist/queue/jobEnvelopeHasPrefix.d.ts +3 -0
- package/dist/queue/jobEnvelopeHasPrefix.js +4 -0
- package/dist/scheduler/ScheduledEvent.d.ts +8 -4
- package/dist/scheduler/ScheduledEvent.js +17 -3
- package/dist/scheduler/ScheduledJob.d.ts +1 -1
- package/dist/scheduler/Scheduler.d.ts +5 -0
- package/dist/scheduler/Scheduler.js +92 -28
- package/dist/scheduler/SchedulerCheckpointRecord.d.ts +16 -0
- package/dist/scheduler/SchedulerCheckpointRecord.js +53 -0
- package/dist/scheduler/SchedulerWorker.d.ts +3 -5
- package/dist/scheduler/SchedulerWorker.js +58 -14
- package/dist/scheduler/console.js +3 -1
- package/dist/scheduler/contracts/Schedule.d.ts +19 -0
- package/dist/scheduler/contracts/Schedule.js +1 -0
- package/dist/scheduler/contracts/Scheduler.d.ts +18 -6
- package/dist/scheduler/contracts/SchedulerCheckpoint.d.ts +23 -0
- package/dist/scheduler/contracts/SchedulerCheckpoint.js +1 -0
- package/dist/scheduler/contracts/SchedulerConsole.d.ts +5 -0
- package/dist/scheduler/contracts/SchedulerWorker.d.ts +6 -1
- package/dist/scheduler/contracts/index.d.ts +2 -0
- package/dist/scheduler/contracts/index.js +2 -0
- package/dist/scheduler/index.d.ts +1 -0
- package/dist/scheduler/index.js +1 -0
- package/dist/server/App.d.ts +36 -4
- package/dist/server/App.js +57 -7
- package/dist/server/contracts/HttpErrorHandlerOptions.d.ts +29 -0
- package/dist/server/contracts/HttpErrorHandlerOptions.js +1 -0
- package/dist/server/contracts/index.d.ts +1 -0
- package/dist/server/contracts/index.js +1 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.js +4 -0
- package/dist/server/publicServerErrorMessage.d.ts +11 -0
- package/dist/server/publicServerErrorMessage.js +16 -0
- package/dist/server/registerBrowserJsonFormatting.d.ts +16 -0
- package/dist/server/registerBrowserJsonFormatting.js +100 -0
- package/dist/server/registerHttpErrorHandler.d.ts +20 -0
- package/dist/server/registerHttpErrorHandler.js +93 -0
- package/dist/ssr/vite/contracts/ViteSsrOptions.d.ts +2 -0
- package/dist/ssr/vite/fastifyViteSsr.js +4 -3
- package/dist/storage/drivers/FlystorageDisk.js +2 -2
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +2 -2
- package/dist/websocket/WebSocketChannels.d.ts +18 -0
- package/dist/websocket/WebSocketChannels.js +129 -0
- package/dist/websocket/WebSocketConnection.d.ts +25 -0
- package/dist/websocket/WebSocketConnection.js +244 -0
- package/dist/websocket/WebSockets.d.ts +41 -0
- package/dist/websocket/WebSockets.js +194 -0
- package/dist/websocket/client/WebSocketClient.d.ts +21 -0
- package/dist/websocket/client/WebSocketClient.js +230 -0
- package/dist/websocket/client/index.d.ts +3 -0
- package/dist/websocket/client/index.js +1 -0
- package/dist/websocket/contracts/WebSocketChannel.d.ts +20 -0
- package/dist/websocket/contracts/WebSocketChannel.js +1 -0
- package/dist/websocket/contracts/WebSocketClient.d.ts +45 -0
- package/dist/websocket/contracts/WebSocketClient.js +1 -0
- package/dist/websocket/contracts/WebSocketEndpoint.d.ts +43 -0
- package/dist/websocket/contracts/WebSocketEndpoint.js +1 -0
- package/dist/websocket/contracts/WebSocketOptions.d.ts +48 -0
- package/dist/websocket/contracts/WebSocketOptions.js +1 -0
- package/dist/websocket/contracts/WebSocketPresence.d.ts +6 -0
- package/dist/websocket/contracts/WebSocketPresence.js +1 -0
- package/dist/websocket/contracts/WebSocketServiceOptions.d.ts +12 -0
- package/dist/websocket/contracts/WebSocketServiceOptions.js +1 -0
- package/dist/websocket/contracts/index.d.ts +6 -0
- package/dist/websocket/contracts/index.js +1 -0
- package/dist/websocket/defineChannel.d.ts +8 -0
- package/dist/websocket/defineChannel.js +13 -0
- package/dist/websocket/defineWebSocket.d.ts +14 -0
- package/dist/websocket/defineWebSocket.js +4 -0
- package/dist/websocket/fastify.d.ts +11 -0
- package/dist/websocket/fastify.js +38 -0
- package/dist/websocket/index.d.ts +5 -0
- package/dist/websocket/index.js +4 -0
- package/package.json +108 -7
- package/src/ai/AIErrors.ts +10 -0
- package/src/ai/AIFailover.ts +3 -2
- package/src/ai/AIProviderAdmission.ts +329 -0
- package/src/ai/AIRateLimiter.ts +134 -10
- package/src/ai/AIRequestTrackingError.ts +37 -0
- package/src/ai/Agent.ts +85 -71
- package/src/ai/Ai.ts +104 -48
- package/src/ai/OpenAIProviderError.ts +1 -1
- package/src/ai/ProviderSseObserver.ts +89 -0
- package/src/ai/README.md +216 -11
- package/src/ai/aiServiceTier.ts +14 -0
- package/src/ai/chunkEmbeddingText.ts +137 -0
- package/src/ai/contracts/AI.ts +17 -0
- package/src/ai/contracts/AIRequestErrorDiagnostics.ts +12 -0
- package/src/ai/contracts/AIServiceTier.ts +2 -0
- package/src/ai/contracts/Agent.ts +3 -0
- package/src/ai/contracts/EmbeddingTextChunk.ts +26 -0
- package/src/ai/contracts/Pricing.ts +7 -1
- package/src/ai/contracts/Providers.ts +2 -0
- package/src/ai/contracts/index.ts +2 -0
- package/src/ai/examples/prepareDocumentEmbeddings.ts +20 -0
- package/src/ai/index.ts +9 -2
- package/src/ai/{Models.ts → modelPricing.ts} +37 -4
- package/src/apps/AppInstallation.ts +25 -0
- package/src/apps/AppRouteError.ts +8 -0
- package/src/apps/AppService.ts +30 -0
- package/src/apps/Apps.ts +508 -0
- package/src/apps/README.md +354 -0
- package/src/apps/appsPlugin.ts +34 -0
- package/src/apps/commands/disableApp.ts +6 -0
- package/src/apps/commands/enableApp.ts +6 -0
- package/src/apps/commands/index.ts +29 -0
- package/src/apps/commands/installApp.ts +6 -0
- package/src/apps/commands/listApps.ts +6 -0
- package/src/apps/commands/makeAppMigration.ts +9 -0
- package/src/apps/commands/rollbackApp.ts +6 -0
- package/src/apps/commands/uninstallApp.ts +6 -0
- package/src/apps/contracts/AppAction.ts +2 -0
- package/src/apps/contracts/AppDefinition.ts +49 -0
- package/src/apps/contracts/AppDescription.ts +27 -0
- package/src/apps/contracts/AppManifest.ts +32 -0
- package/src/apps/contracts/AppNavigation.ts +10 -0
- package/src/apps/contracts/AppNavigationBadge.ts +6 -0
- package/src/apps/contracts/AppNavigationContext.ts +6 -0
- package/src/apps/contracts/AppNavigationResult.ts +9 -0
- package/src/apps/contracts/AppRoute.ts +18 -0
- package/src/apps/contracts/DiscoveredApp.ts +11 -0
- package/src/apps/contracts/InstalledApps.ts +2 -0
- package/src/apps/contracts/index.ts +11 -0
- package/src/apps/defineApp.ts +10 -0
- package/src/apps/discoverApps.ts +56 -0
- package/src/apps/fastify.ts +1 -0
- package/src/apps/index.ts +7 -0
- package/src/apps/normalizeAppNavigation.ts +29 -0
- package/src/apps/registerAppRoutes.ts +48 -0
- package/src/apps/validateAppDefinitions.ts +52 -0
- package/src/apps/vite.ts +1 -0
- package/src/apps/writeAppTypes.ts +14 -0
- package/src/auth/Auth.ts +89 -23
- package/src/auth/PasswordLoginAttempt.ts +72 -0
- package/src/auth/PasswordSuspendedError.ts +13 -0
- package/src/auth/README.md +94 -4
- package/src/auth/contracts/PasswordAuthProviderOptions.ts +30 -0
- package/src/auth/contracts/PasswordSuspension.ts +7 -0
- package/src/auth/contracts/PasswordSuspensionOptions.ts +10 -0
- package/src/auth/contracts/index.ts +3 -0
- package/src/auth/examples/runPasswordAuth.ts +6 -6
- package/src/auth/index.ts +2 -0
- package/src/auth/providers/PasswordAuthProvider.ts +96 -30
- package/src/auth/providers/resolveAuthProviders.ts +1 -0
- package/src/cli/Cli.ts +9 -0
- package/src/cli/README.md +19 -0
- package/src/cli/commands/repl.ts +2 -1
- package/src/cli/contracts/CliCommand.ts +2 -0
- package/src/cli/contracts/CliCommandInfo.ts +13 -0
- package/src/cli/contracts/index.ts +1 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/listDb3Commands.ts +12 -0
- package/src/cli/runDb3.ts +5 -51
- package/src/cli/withDb3Cli.ts +55 -0
- package/src/db/ActiveQueryBuilder.ts +12 -0
- package/src/db/ActiveRecord.ts +9 -0
- package/src/db/README.md +45 -1
- package/src/db/connection.ts +12 -1
- package/src/db/examples/FieldNote.ts +7 -13
- package/src/db/examples/KnowledgeNote.ts +7 -13
- package/src/db/examples/runNoteMigrations.ts +11 -11
- package/src/db/fields/TimestampField.ts +8 -17
- package/src/db/migrations/DatabaseMigrationManager.ts +12 -4
- package/src/db/migrations/contracts/DatabaseMigration.ts +9 -0
- package/src/db/migrations/index.ts +1 -1
- package/src/db/migrations/{KnexMigrationRenderer.ts → renderKnexMigration.ts} +8 -14
- package/src/flows/FlowCompiler.ts +1 -1
- package/src/flows/Flows.ts +1 -1
- package/src/flows/index.ts +1 -1
- package/src/health/Health.ts +163 -0
- package/src/health/README.md +46 -0
- package/src/health/contracts/Health.ts +47 -0
- package/src/health/contracts/HealthHttp.ts +19 -0
- package/src/health/contracts/index.ts +2 -0
- package/src/health/databaseHealthCheck.ts +21 -0
- package/src/health/fastify.ts +49 -0
- package/src/health/index.ts +3 -0
- package/src/in-app/InApp.ts +173 -0
- package/src/in-app/InAppError.ts +8 -0
- package/src/in-app/InAppRecord.ts +41 -0
- package/src/in-app/README.md +193 -0
- package/src/in-app/contracts/InAppInbox.ts +51 -0
- package/src/in-app/contracts/InAppMessage.ts +19 -0
- package/src/in-app/contracts/InAppScope.ts +12 -0
- package/src/in-app/contracts/index.ts +3 -0
- package/src/in-app/examples/sendReportReady.ts +14 -0
- package/src/in-app/index.ts +4 -0
- package/src/in-app/validation.ts +49 -0
- package/src/index.ts +2 -22
- package/src/logging/DevelopmentConsole.ts +154 -0
- package/src/logging/Log.ts +5 -2
- package/src/logging/PrettyLogFormatter.ts +165 -0
- package/src/logging/README.md +52 -109
- package/src/logging/acquireDevelopmentConsole.ts +19 -0
- package/src/logging/contracts/DevelopmentConsoleOptions.ts +13 -0
- package/src/logging/contracts/EmailLogOptions.ts +9 -0
- package/src/logging/contracts/HttpExchangeMonitorOptions.ts +13 -0
- package/src/logging/contracts/LogTransportOptions.ts +10 -0
- package/src/logging/contracts/LoggingOptions.ts +12 -1
- package/src/logging/contracts/index.ts +4 -0
- package/src/logging/development/README.md +88 -0
- package/src/logging/drivers/PinoLoggerDriver.ts +72 -20
- package/src/logging/examples/runDevelopmentLogs.ts +36 -0
- package/src/logging/formatLogEmail.ts +24 -0
- package/src/logging/highlightQueueMessage.ts +38 -0
- package/src/logging/httpBodyCapture.ts +393 -0
- package/src/logging/index.ts +2 -0
- package/src/logging/redactLogEmail.ts +12 -0
- package/src/logging/registerHttpExchangeMonitor.ts +45 -0
- package/src/logging/transports/EmailLogTransport.ts +46 -0
- package/src/mail/Mail.ts +5 -0
- package/src/mail/MailDeliveryError.ts +8 -0
- package/src/mail/README.md +11 -1
- package/src/mail/index.ts +1 -0
- package/src/mail/transports/MailgunTransport.ts +2 -0
- package/src/mail/transports/ResendTransport.ts +24 -22
- package/src/media/MediaManager.ts +31 -10
- package/src/media/README.md +4 -0
- package/src/media/examples/runPrivateFiles.ts +2 -2
- package/src/network/BlockedUrlError.ts +19 -0
- package/src/network/README.md +133 -0
- package/src/network/assertPublicUrl.ts +77 -0
- package/src/network/contracts/GuardedFetch.ts +40 -0
- package/src/network/contracts/PublicUrlOptions.ts +17 -0
- package/src/network/contracts/index.ts +2 -0
- package/src/network/examples/runGuardedFetch.ts +35 -0
- package/src/network/guardedFetch.ts +150 -0
- package/src/network/index.ts +6 -0
- package/src/network/playwright/GuardedBrowserProxy.ts +172 -0
- package/src/network/playwright/contracts/GuardedBrowserContextOptions.ts +43 -0
- package/src/network/playwright/contracts/index.ts +1 -0
- package/src/network/playwright/index.ts +2 -0
- package/src/network/playwright/newGuardedBrowserContext.ts +74 -0
- package/src/network/privateNetworkAddresses.ts +166 -0
- package/src/network/publicAddressLookup.ts +49 -0
- package/src/notifications/Notifications.ts +105 -0
- package/src/notifications/README.md +59 -0
- package/src/notifications/contracts/Notification.ts +65 -0
- package/src/notifications/contracts/NotificationDelivery.ts +11 -0
- package/src/notifications/contracts/index.ts +2 -0
- package/src/notifications/examples/ReportReadyNotification.ts +31 -0
- package/src/notifications/index.ts +2 -0
- package/src/queue/JobRunAttempt.ts +17 -0
- package/src/queue/JobRunEvent.ts +16 -0
- package/src/queue/JobRunStoppedError.ts +8 -0
- package/src/queue/Queue.ts +112 -11
- package/src/queue/QueueTerminalError.ts +12 -0
- package/src/queue/QueueWorker.ts +86 -7
- package/src/queue/QueueWorkerReporter.ts +59 -0
- package/src/queue/QueueableJob.ts +2 -2
- package/src/queue/README.md +142 -1
- package/src/queue/RunnableJob.ts +272 -0
- package/src/queue/console.ts +54 -21
- package/src/queue/contracts/QueueDriver.ts +9 -0
- package/src/queue/contracts/QueueJobRunner.ts +4 -0
- package/src/queue/contracts/QueuePayload.ts +1 -1
- package/src/queue/contracts/QueueSelection.ts +11 -0
- package/src/queue/contracts/QueueService.ts +19 -4
- package/src/queue/contracts/QueueWorkerLifecycle.ts +2 -2
- package/src/queue/contracts/QueueWorkerSnapshot.ts +15 -0
- package/src/queue/contracts/QueueableJob.ts +7 -3
- package/src/queue/contracts/QueueableJobContract.ts +13 -0
- package/src/queue/contracts/index.ts +6 -0
- package/src/queue/drivers/DatabaseQueueDriver.ts +25 -3
- package/src/queue/drivers/RedisQueueDriver.ts +36 -0
- package/src/queue/examples/runQueueSelection.ts +34 -0
- package/src/queue/index.ts +7 -0
- package/src/queue/jobEnvelopeHasPrefix.ts +6 -0
- package/src/scheduler/README.md +50 -9
- package/src/scheduler/ScheduledEvent.ts +20 -5
- package/src/scheduler/ScheduledJob.ts +1 -1
- package/src/scheduler/Scheduler.ts +73 -27
- package/src/scheduler/SchedulerCheckpointRecord.ts +51 -0
- package/src/scheduler/SchedulerWorker.ts +54 -19
- package/src/scheduler/console.ts +3 -1
- package/src/scheduler/contracts/Schedule.ts +22 -0
- package/src/scheduler/contracts/Scheduler.ts +21 -6
- package/src/scheduler/contracts/SchedulerCheckpoint.ts +23 -0
- package/src/scheduler/contracts/SchedulerConsole.ts +5 -0
- package/src/scheduler/contracts/SchedulerWorker.ts +6 -1
- package/src/scheduler/contracts/index.ts +2 -0
- package/src/scheduler/examples/runSchedulerWindow.ts +54 -0
- package/src/scheduler/index.ts +1 -0
- package/src/server/App.ts +73 -10
- package/src/server/README.md +95 -2
- package/src/server/contracts/HttpErrorHandlerOptions.ts +29 -0
- package/src/server/contracts/index.ts +1 -0
- package/src/server/examples/createFirstServer.ts +5 -3
- package/src/server/index.ts +4 -0
- package/src/server/publicServerErrorMessage.ts +17 -0
- package/src/server/registerBrowserJsonFormatting.ts +94 -0
- package/src/server/registerHttpErrorHandler.ts +96 -0
- package/src/ssr/README.md +6 -0
- package/src/ssr/vite/contracts/ViteSsrOptions.ts +2 -0
- package/src/ssr/vite/fastifyViteSsr.ts +4 -3
- package/src/storage/drivers/FlystorageDisk.ts +2 -2
- package/src/storage/index.ts +2 -2
- package/src/websocket/README.md +458 -0
- package/src/websocket/WebSocketChannels.ts +99 -0
- package/src/websocket/WebSocketConnection.ts +162 -0
- package/src/websocket/WebSockets.ts +157 -0
- package/src/websocket/client/WebSocketClient.ts +188 -0
- package/src/websocket/client/index.ts +3 -0
- package/src/websocket/contracts/WebSocketChannel.ts +23 -0
- package/src/websocket/contracts/WebSocketClient.ts +48 -0
- package/src/websocket/contracts/WebSocketEndpoint.ts +46 -0
- package/src/websocket/contracts/WebSocketOptions.ts +50 -0
- package/src/websocket/contracts/WebSocketPresence.ts +6 -0
- package/src/websocket/contracts/WebSocketServiceOptions.ts +12 -0
- package/src/websocket/contracts/index.ts +6 -0
- package/src/websocket/defineChannel.ts +14 -0
- package/src/websocket/defineWebSocket.ts +15 -0
- package/src/websocket/examples/board/LiveBoard.ts +97 -0
- package/src/websocket/examples/board/SummarizeBoardJob.ts +52 -0
- package/src/websocket/examples/board/boardSnapshot.ts +16 -0
- package/src/websocket/examples/board/createBoardClient.ts +43 -0
- package/src/websocket/examples/board/createBoardStore.ts +58 -0
- package/src/websocket/examples/board/registerBoardRoutes.ts +31 -0
- package/src/websocket/examples/createChannelSync.ts +66 -0
- package/src/websocket/examples/deploymentEndpoint.ts +13 -0
- package/src/websocket/examples/deploymentSnapshot.ts +36 -0
- package/src/websocket/examples/resourceChannels.ts +18 -0
- package/src/websocket/examples/userEndpoint.ts +27 -0
- package/src/websocket/fastify.ts +39 -0
- package/src/websocket/index.ts +5 -0
- package/templates/AGENTS.md +33 -2
- /package/dist/flows/{FlowValueValidator.d.ts → flowValueValidator.d.ts} +0 -0
- /package/dist/flows/{FlowValueValidator.js → flowValueValidator.js} +0 -0
- /package/dist/storage/{mime.d.ts → mimeTypeFromPath.d.ts} +0 -0
- /package/dist/storage/{mime.js → mimeTypeFromPath.js} +0 -0
- /package/dist/storage/{contents.d.ts → storageContentsToBuffer.d.ts} +0 -0
- /package/dist/storage/{contents.js → storageContentsToBuffer.js} +0 -0
- /package/src/flows/{FlowValueValidator.ts → flowValueValidator.ts} +0 -0
- /package/src/storage/{mime.ts → mimeTypeFromPath.ts} +0 -0
- /package/src/storage/{contents.ts → storageContentsToBuffer.ts} +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { ActiveRecord } from '../db/ActiveRecord.js';
|
|
5
|
+
import { JobRunAttempt } from './JobRunAttempt.js';
|
|
6
|
+
import { JobRunEvent } from './JobRunEvent.js';
|
|
7
|
+
import { JobRunStoppedError } from './JobRunStoppedError.js';
|
|
8
|
+
import { QueueTerminalError } from './QueueTerminalError.js';
|
|
9
|
+
import { isQueueRetryLaterError } from './QueueRetryLaterError.js';
|
|
10
|
+
/** Persisted lifecycle values; waiting includes scheduled retries, blocked requires an explicit new run. */
|
|
11
|
+
export const JOB_RUN_STATUSES = ['waiting', 'running', 'blocked', 'completed', 'failed', 'cancelled'];
|
|
12
|
+
/**
|
|
13
|
+
* A retained run with application-owned input, state and behaviour. Register only
|
|
14
|
+
* this base model in migrations; concrete job classes share its table. Jobs must
|
|
15
|
+
* use checkpoint/save for durable work and make external effects idempotent.
|
|
16
|
+
* Tenant and subject identities are immutable; applications authorize launches
|
|
17
|
+
* and reads. Queue serialization contains only the saved run ID and generation.
|
|
18
|
+
*/
|
|
19
|
+
export class RunnableJob extends ActiveRecord.define({
|
|
20
|
+
table: 'job_runs',
|
|
21
|
+
fields: field => ({
|
|
22
|
+
id: field.ulid(),
|
|
23
|
+
jobType: field.string({ column: 'job_type', required: true, length: 200, index: true }),
|
|
24
|
+
tenantId: field.string({ column: 'tenant_id', required: true, length: 100, indexes: [{ name: 'job_runs_tenant_history', columns: ['tenant_id', 'id'] }] }),
|
|
25
|
+
subjectId: field.string({ column: 'subject_id', length: 100, indexes: [{ name: 'job_runs_subject_history', columns: ['subject_id', 'id'] }] }),
|
|
26
|
+
actorId: field.string({ column: 'actor_id', length: 100 }),
|
|
27
|
+
parentRunId: field.string({ column: 'parent_run_id', length: 26, index: true }),
|
|
28
|
+
trigger: field.string({ required: true, default: 'manual', length: 40 }),
|
|
29
|
+
status: field.choice({ choices: [...JOB_RUN_STATUSES], required: true, default: 'waiting', index: true }),
|
|
30
|
+
input: field.json({ required: true, default: {}, comment: 'Immutable application inputs captured when the run is created.' }),
|
|
31
|
+
state: field.json({ required: true, default: {}, comment: 'Mutable application checkpoint for progress, diagnosis and explicit recovery; may contain private data.' }),
|
|
32
|
+
result: field.json({ comment: 'Application outcome or result summary, separate from mutable progress state.' }),
|
|
33
|
+
error: field.text(),
|
|
34
|
+
stage: field.string({ length: 200, comment: 'Job-owned current phase; lifecycle outcome is stored in status.' }),
|
|
35
|
+
completed: field.integer({ required: true, default: 0, comment: 'Job-owned processed unit count, e.g. pages scanned or 1 for one operation; not a completion flag.' }),
|
|
36
|
+
total: field.integer({ comment: 'Planned units in the same measure as completed; null when unknown.' }),
|
|
37
|
+
failures: field.integer({ required: true, default: 0, comment: 'Job-owned failed unit count; units may also be counted as completed. Job failure is recorded in status.' }),
|
|
38
|
+
attemptCount: field.integer({ column: 'attempt_count', required: true, default: 0 }),
|
|
39
|
+
deliveryKey: field.string({ column: 'delivery_key', length: 36 }),
|
|
40
|
+
leaseToken: field.string({ column: 'lease_token', length: 36 }),
|
|
41
|
+
cancelRequestedAt: field.timestamp({ column: 'cancel_requested_at' }),
|
|
42
|
+
queuedAt: field.timestamp({ column: 'queued_at' }),
|
|
43
|
+
startedAt: field.timestamp({ column: 'started_at' }),
|
|
44
|
+
heartbeatAt: field.timestamp({ column: 'heartbeat_at' }),
|
|
45
|
+
completedAt: field.timestamp({ column: 'completed_at' }),
|
|
46
|
+
createdAt: field.timestamp({ column: 'created_at', auto: 'create' }),
|
|
47
|
+
updatedAt: field.timestamp({ column: 'updated_at', auto: 'update' }),
|
|
48
|
+
}),
|
|
49
|
+
}) {
|
|
50
|
+
/** Stable name may be overridden to preserve queued identities across class renames. */
|
|
51
|
+
static jobName;
|
|
52
|
+
static #active = new AsyncLocalStorage();
|
|
53
|
+
/** Returns the active run for child dispatch correlation within this asynchronous execution only. */
|
|
54
|
+
static current() { return _a.#active.getStore(); }
|
|
55
|
+
#context = null;
|
|
56
|
+
#token = null;
|
|
57
|
+
#updates = Promise.resolve();
|
|
58
|
+
#stop = new AbortController();
|
|
59
|
+
#publishing = false;
|
|
60
|
+
/** Internal dispatch guard; a saved delivery cannot be enqueued twice through the public API. */
|
|
61
|
+
get publishingDelivery() { return this.#publishing; }
|
|
62
|
+
/** Cooperative abort signal. Application requests should combine it with their own deadline. */
|
|
63
|
+
get signal() { return this.#stop.signal; }
|
|
64
|
+
/** Loads the authoritative run through its concrete registered class, rejecting mismatched deliveries. */
|
|
65
|
+
static async fromJSON(data) {
|
|
66
|
+
if (typeof data.runId !== 'string' || typeof data.deliveryKey !== 'string')
|
|
67
|
+
throw new Error('Invalid runnable job reference.');
|
|
68
|
+
const run = await this.findOrFail(data.runId);
|
|
69
|
+
if (run.jobType !== (this.jobName ?? this.name) || run.deliveryKey !== data.deliveryKey)
|
|
70
|
+
throw new Error('Runnable job identity does not match its delivery.');
|
|
71
|
+
return run;
|
|
72
|
+
}
|
|
73
|
+
/** Saves a new run before dispatch. During execution, saves only application-owned fields under the attempt fence. */
|
|
74
|
+
async save() {
|
|
75
|
+
if (!this.isPersisted()) {
|
|
76
|
+
if (this.constructor === _a)
|
|
77
|
+
throw new Error('Create a concrete RunnableJob subclass.');
|
|
78
|
+
this.jobType = this.constructor.jobName ?? this.constructor.name;
|
|
79
|
+
return super.save();
|
|
80
|
+
}
|
|
81
|
+
if (!this.#token)
|
|
82
|
+
throw new Error('Existing run records may only be saved by their owning execution.');
|
|
83
|
+
const values = structuredClone({ state: this.state, result: this.result, stage: this.stage, completed: this.completed, total: this.total, failures: this.failures });
|
|
84
|
+
await this.#serializeUpdate(() => this.#write(values));
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
/** Serializes concurrent progress callbacks so state merges cannot lose another completed item's update. */
|
|
88
|
+
async checkpoint(update) {
|
|
89
|
+
await this.#serializeUpdate(async () => {
|
|
90
|
+
await this.assertActive();
|
|
91
|
+
update(this);
|
|
92
|
+
await this.#write({ state: this.state, result: this.result, stage: this.stage, completed: this.completed, total: this.total, failures: this.failures });
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Checks delivery ownership and operator cancellation before launching or publishing another unit of work. */
|
|
96
|
+
async assertActive() {
|
|
97
|
+
this.signal.throwIfAborted();
|
|
98
|
+
await this.#context?.assertOwnership?.();
|
|
99
|
+
const row = await _a.where({ id: this.id, leaseToken: this.#token, status: 'running' }).first();
|
|
100
|
+
if (!this.#token || !row)
|
|
101
|
+
throw new Error('Runnable job execution ownership was lost.');
|
|
102
|
+
let cancellation = Boolean(row.cancelRequestedAt);
|
|
103
|
+
let parentId = row.parentRunId;
|
|
104
|
+
const visited = new Set();
|
|
105
|
+
while (!cancellation && parentId) {
|
|
106
|
+
if (visited.has(parentId) || visited.size >= 32)
|
|
107
|
+
throw new Error('Invalid run ancestry.');
|
|
108
|
+
visited.add(parentId);
|
|
109
|
+
const parent = await _a.find(parentId);
|
|
110
|
+
cancellation = Boolean(parent?.cancelRequestedAt);
|
|
111
|
+
parentId = parent?.parentRunId ?? null;
|
|
112
|
+
}
|
|
113
|
+
if (cancellation) {
|
|
114
|
+
const reason = new JobRunStoppedError('cancelled', 'Cancelled by the operator.');
|
|
115
|
+
this.#stop.abort(reason);
|
|
116
|
+
throw reason;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Appends bounded structured diagnostics; callers must omit credentials and private provider payloads. */
|
|
120
|
+
async log(message, data = {}, level = 'info') {
|
|
121
|
+
await this.assertActive();
|
|
122
|
+
if (JSON.stringify(data).length > 16000)
|
|
123
|
+
throw new Error('Job event data exceeds 16,000 characters.');
|
|
124
|
+
await JobRunEvent.create({ runId: this.id, tenantId: this.tenantId, attempt: this.attemptCount, message: message.slice(0, 1024), data, level }).save();
|
|
125
|
+
}
|
|
126
|
+
/** Stops launching further work until an operator creates a resumed run using the saved checkpoint. */
|
|
127
|
+
block(reason) { throw new JobRunStoppedError('blocked', reason); }
|
|
128
|
+
/** Resolves application-owned input/scope before first persistence. Override in a tenant-aware application base class. */
|
|
129
|
+
async prepare() { }
|
|
130
|
+
/** Saves a run and its dispatch generation before delivery. Failed dispatches remain visible in history. */
|
|
131
|
+
async enqueue(queue, options = {}) {
|
|
132
|
+
if (this.deliveryKey)
|
|
133
|
+
throw new Error('This run has already been dispatched.');
|
|
134
|
+
if (!this.isPersisted()) {
|
|
135
|
+
await this.prepare();
|
|
136
|
+
await this.save();
|
|
137
|
+
}
|
|
138
|
+
const key = randomUUID();
|
|
139
|
+
let reserved = false;
|
|
140
|
+
/** Reserves the delivery generation and publishes its small queue reference. */
|
|
141
|
+
const publish = async () => {
|
|
142
|
+
const changed = await _a.where({ id: this.id, status: 'waiting' }).whereNull('deliveryKey').patch({ deliveryKey: key, queuedAt: new Date() });
|
|
143
|
+
if (changed !== 1)
|
|
144
|
+
throw new Error('This run has already been dispatched.');
|
|
145
|
+
reserved = true;
|
|
146
|
+
this.deliveryKey = key;
|
|
147
|
+
this.#publishing = true;
|
|
148
|
+
try {
|
|
149
|
+
return await queue.dispatch(this, options);
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
this.#publishing = false;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
try {
|
|
156
|
+
return queue.driverName === 'database'
|
|
157
|
+
? await _a.getDb().transaction(transaction => ActiveRecord.withDb(transaction, publish))
|
|
158
|
+
: await publish();
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
if (!reserved)
|
|
162
|
+
throw error;
|
|
163
|
+
const failedDispatch = _a.where({ id: this.id, status: 'waiting' });
|
|
164
|
+
if (queue.driverName === 'database')
|
|
165
|
+
failedDispatch.whereNull('deliveryKey');
|
|
166
|
+
else
|
|
167
|
+
failedDispatch.where('deliveryKey', key);
|
|
168
|
+
await failedDispatch.patch({ status: 'failed', error: `Dispatch failed: ${error instanceof Error ? error.message : String(error)}`, completedAt: new Date() });
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** Produces a small immutable queue reference; never copies mutable model JSON into delivery storage. */
|
|
173
|
+
serialize() {
|
|
174
|
+
if (!this.isPersisted() || !this.deliveryKey)
|
|
175
|
+
throw new Error('Call run.enqueue(queue) before queueing a runnable record.');
|
|
176
|
+
return { job: this.jobType, displayName: this.jobType, data: { runId: this.id, deliveryKey: this.deliveryKey } };
|
|
177
|
+
}
|
|
178
|
+
/** Concrete application jobs implement their own bounded work, checkpoints and result publication. */
|
|
179
|
+
async handle(_context) { throw new Error('RunnableJob.handle must be implemented.'); }
|
|
180
|
+
/** Lifecycle is saved before delivery transitions; ordinary queue retry hooks are intentionally empty. */
|
|
181
|
+
async onRetry(_context) { }
|
|
182
|
+
/** Lifecycle is saved before delivery transitions, including terminal failure. */
|
|
183
|
+
async onFinalFailure(context) {
|
|
184
|
+
// A deadline can pass between handler failure and the driver's final disposition.
|
|
185
|
+
const error = context.error instanceof Error ? context.error.message : String(context.error);
|
|
186
|
+
await _a.getDb().transaction(transaction => ActiveRecord.withDb(transaction, async () => {
|
|
187
|
+
const changed = await _a.where({ id: this.id, status: 'waiting', attemptCount: this.attemptCount }).patch({ status: 'failed', error, completedAt: new Date() });
|
|
188
|
+
if (changed) {
|
|
189
|
+
await JobRunAttempt.where({ runId: this.id, attempt: this.attemptCount, status: 'retrying' }).patch({ status: 'failed', error });
|
|
190
|
+
await JobRunEvent.create({ runId: this.id, tenantId: this.tenantId, attempt: this.attemptCount, level: 'error', message: error.slice(0, 1024), data: { status: 'failed', queue: context.job.queue, deliveryId: context.job.id, jobUuid: context.job.payload.uuid, maxTries: context.job.payload.maxTries } }).save();
|
|
191
|
+
this.status = 'failed';
|
|
192
|
+
}
|
|
193
|
+
}));
|
|
194
|
+
}
|
|
195
|
+
/** Runs one fenced attempt. Expired delivery recovery preserves checkpoints and records the interrupted attempt. */
|
|
196
|
+
async execute(context) {
|
|
197
|
+
await context.assertOwnership?.();
|
|
198
|
+
this.#context = context;
|
|
199
|
+
this.#updates = Promise.resolve();
|
|
200
|
+
const token = randomUUID();
|
|
201
|
+
const claimed = await _a.getDb().transaction(transaction => ActiveRecord.withDb(transaction, async () => {
|
|
202
|
+
const raw = await _a.where('id', this.id).toKnex().forUpdate().first();
|
|
203
|
+
if (!raw)
|
|
204
|
+
throw new Error('Run no longer exists.');
|
|
205
|
+
const current = _a.fromDb(raw);
|
|
206
|
+
if (current.deliveryKey !== this.deliveryKey)
|
|
207
|
+
throw new Error('Run delivery was replaced.');
|
|
208
|
+
if (!['waiting', 'running'].includes(current.status ?? ''))
|
|
209
|
+
return false;
|
|
210
|
+
if (current.status === 'running')
|
|
211
|
+
await JobRunAttempt.where({ runId: this.id, status: 'running' }).patch({ status: 'interrupted', completedAt: new Date(), error: 'Worker reservation expired before completion.' });
|
|
212
|
+
const now = new Date();
|
|
213
|
+
const values = { status: 'running', leaseToken: token, attemptCount: (current.attemptCount ?? 0) + 1, startedAt: current.startedAt ?? now, heartbeatAt: now, completedAt: null, error: null };
|
|
214
|
+
await _a.where('id', this.id).patch(values);
|
|
215
|
+
this.assign({ ...current.toJSON(), ...values });
|
|
216
|
+
await JobRunAttempt.create({ runId: this.id, tenantId: this.tenantId, attempt: this.attemptCount, deliveryId: String(context.job.id), status: 'running', startedAt: now }).save();
|
|
217
|
+
return true;
|
|
218
|
+
}));
|
|
219
|
+
if (!claimed)
|
|
220
|
+
return;
|
|
221
|
+
this.#token = token;
|
|
222
|
+
this.#stop = new AbortController();
|
|
223
|
+
let heartbeat = Promise.resolve();
|
|
224
|
+
const timer = setInterval(() => {
|
|
225
|
+
heartbeat = heartbeat.then(async () => {
|
|
226
|
+
await this.assertActive();
|
|
227
|
+
await _a.where({ id: this.id, leaseToken: token }).patch({ heartbeatAt: new Date() });
|
|
228
|
+
}).catch(error => { this.#stop.abort(error); });
|
|
229
|
+
}, 10000);
|
|
230
|
+
try {
|
|
231
|
+
await this.log('Attempt started');
|
|
232
|
+
await _a.#active.run(this, () => this.handle(context));
|
|
233
|
+
await this.#updates;
|
|
234
|
+
await this.assertActive();
|
|
235
|
+
await this.#finish('completed', null);
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
await this.#updates.catch(() => undefined);
|
|
239
|
+
await context.assertOwnership?.();
|
|
240
|
+
const stopped = error instanceof JobRunStoppedError;
|
|
241
|
+
const retry = context.willRetry ? context.willRetry(error) : isQueueRetryLaterError(error) || !(error instanceof QueueTerminalError) && context.job.attempts < context.job.payload.maxTries;
|
|
242
|
+
const status = stopped ? error.status : retry ? 'waiting' : 'failed';
|
|
243
|
+
await this.#finish(status, error instanceof Error ? error.message : String(error));
|
|
244
|
+
if (!stopped)
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
clearInterval(timer);
|
|
249
|
+
await heartbeat;
|
|
250
|
+
this.#context = null;
|
|
251
|
+
this.#token = null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/** Writes application-owned state with a database fence; unrelated runtime fields cannot be overwritten. */
|
|
255
|
+
async #write(values) {
|
|
256
|
+
await this.assertActive();
|
|
257
|
+
if (JSON.stringify(values).length > 1000000)
|
|
258
|
+
throw new Error('Run checkpoint exceeds one megabyte. Store large evidence separately.');
|
|
259
|
+
const count = await _a.where({ id: this.id, leaseToken: this.#token, status: 'running' }).whereNull('cancelRequestedAt').patch({ ...values, heartbeatAt: new Date(), updatedAt: new Date() });
|
|
260
|
+
if (count !== 1) {
|
|
261
|
+
await this.assertActive();
|
|
262
|
+
throw new Error('Runnable job checkpoint ownership was lost.');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** Records terminal/retry state, attempt outcome and timeline in the same transaction. */
|
|
266
|
+
async #finish(status, error) {
|
|
267
|
+
await _a.getDb().transaction(transaction => ActiveRecord.withDb(transaction, async () => {
|
|
268
|
+
const now = new Date();
|
|
269
|
+
const changed = await _a.where({ id: this.id, leaseToken: this.#token, status: 'running' }).patch({ status, error, completedAt: status === 'waiting' ? null : now, heartbeatAt: now, leaseToken: null, updatedAt: now });
|
|
270
|
+
if (changed !== 1)
|
|
271
|
+
throw new Error('Runnable job completion ownership was lost.');
|
|
272
|
+
await JobRunAttempt.where({ runId: this.id, attempt: this.attemptCount, status: 'running' }).patch({ status: status === 'waiting' ? 'retrying' : status, error, completedAt: now });
|
|
273
|
+
await JobRunEvent.create({ runId: this.id, tenantId: this.tenantId, attempt: this.attemptCount, level: status === 'failed' ? 'error' : error ? 'warning' : 'info', message: error?.slice(0, 1024) ?? 'Run completed', data: { status, queue: this.#context?.job.queue, deliveryId: this.#context?.job.id, jobUuid: this.#context?.job.payload.uuid, maxTries: this.#context?.job.payload.maxTries } }).save();
|
|
274
|
+
this.status = status;
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
/** Queues state writes on this instance while allowing callers to observe their own failures. */
|
|
278
|
+
#serializeUpdate(action) {
|
|
279
|
+
const next = this.#updates.then(action);
|
|
280
|
+
this.#updates = next;
|
|
281
|
+
return next;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
_a = RunnableJob;
|
package/dist/queue/console.d.ts
CHANGED
|
@@ -29,8 +29,11 @@ export interface QueueConsoleCommand {
|
|
|
29
29
|
close?: boolean;
|
|
30
30
|
run(context: QueueConsoleCommandContext): void | Promise<void>;
|
|
31
31
|
}
|
|
32
|
+
/** Application bootstrap, named worker selections and extra commands shared by queue CLI invocations. */
|
|
32
33
|
export interface QueueConsoleOptions {
|
|
33
34
|
app: () => QueueConsoleApp;
|
|
35
|
+
/** Checked-in worker selections selected with --pool=<name>; credentials remain in the application environment. */
|
|
36
|
+
workers?: Readonly<Record<string, queue.QueueSelection>>;
|
|
34
37
|
bootstrap?: () => void | Promise<void>;
|
|
35
38
|
commands?: QueueConsoleCommand[];
|
|
36
39
|
helpText?: string;
|
|
@@ -57,4 +60,9 @@ export declare function logQueueProcessResult(result: queue.QueueProcessResult,
|
|
|
57
60
|
* @param options - Console logging options.
|
|
58
61
|
*/
|
|
59
62
|
export declare function logQueueClaimed(job: queue.QueueJob, options?: QueueConsoleLogOptions): void;
|
|
63
|
+
/**
|
|
64
|
+
* Resolves one worker selection from explicit CLI flags or a checked-in named pool.
|
|
65
|
+
* Pool admission cannot be silently broadened by combining it with queue flags.
|
|
66
|
+
*/
|
|
67
|
+
export declare function queueConsoleSelection(parsed: ParsedQueueConsoleArgs, workers?: QueueConsoleOptions['workers']): queue.QueueSelection;
|
|
60
68
|
export {};
|
package/dist/queue/console.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseJsonRecord, unknownErrorMessage } from '@db3.ai/pure';
|
|
2
|
+
import { QueueWorker } from './QueueWorker.js';
|
|
2
3
|
export async function runQueueConsole(options, argv = process.argv.slice(2)) {
|
|
3
4
|
const parsed = parseQueueConsoleArgs(argv);
|
|
4
5
|
switch (parsed.command) {
|
|
@@ -163,11 +164,10 @@ export function logQueueClaimed(job, options = {}) {
|
|
|
163
164
|
async function bootstrap(options) {
|
|
164
165
|
await options.bootstrap?.();
|
|
165
166
|
}
|
|
167
|
+
/** Runs a configured worker selection, with identical admission for one-shot and polling execution. */
|
|
166
168
|
async function workQueue(options, parsed) {
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|| process.env.QUEUE_NAME
|
|
170
|
-
|| 'default';
|
|
169
|
+
const selection = queueConsoleSelection(parsed, options.workers);
|
|
170
|
+
const queue = selection.queues === '*' ? '*' : selection.queues?.join(', ') ?? 'default';
|
|
171
171
|
const once = queueConsoleOptionBoolean(parsed, 'once');
|
|
172
172
|
const verbose = queueConsoleVerbose(parsed);
|
|
173
173
|
if (!once) {
|
|
@@ -175,26 +175,29 @@ async function workQueue(options, parsed) {
|
|
|
175
175
|
}
|
|
176
176
|
const app = options.app();
|
|
177
177
|
if (once) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
try {
|
|
179
|
+
if (verbose) {
|
|
180
|
+
console.log(`[queue] Checking "${queue}" once.`);
|
|
181
|
+
}
|
|
182
|
+
const result = await new QueueWorker(app.queue, selection).workOnce({
|
|
183
|
+
onClaimed: job => logQueueClaimed(job, {
|
|
184
|
+
verbose,
|
|
185
|
+
}),
|
|
186
|
+
});
|
|
187
|
+
if (!result) {
|
|
188
|
+
console.log(`[queue] No jobs available on "${queue}".`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
logQueueProcessResult(result, {
|
|
183
192
|
verbose,
|
|
184
|
-
})
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
console.log(`[queue] No jobs available on "${queue}".`);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
188
196
|
await app.close();
|
|
189
|
-
return;
|
|
190
197
|
}
|
|
191
|
-
logQueueProcessResult(result, {
|
|
192
|
-
verbose,
|
|
193
|
-
});
|
|
194
|
-
await app.close();
|
|
195
198
|
return;
|
|
196
199
|
}
|
|
197
|
-
const worker = app.queue.startWorker(
|
|
200
|
+
const worker = app.queue.startWorker(selection, {
|
|
198
201
|
force: true,
|
|
199
202
|
logger: app.log?.child({
|
|
200
203
|
component: 'queue-worker',
|
|
@@ -223,6 +226,34 @@ async function workQueue(options, parsed) {
|
|
|
223
226
|
void shutdown('SIGTERM');
|
|
224
227
|
});
|
|
225
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Resolves one worker selection from explicit CLI flags or a checked-in named pool.
|
|
231
|
+
* Pool admission cannot be silently broadened by combining it with queue flags.
|
|
232
|
+
*/
|
|
233
|
+
export function queueConsoleSelection(parsed, workers = {}) {
|
|
234
|
+
for (const flag of ['pool', 'queues', 'queue', 'exclude-queues']) {
|
|
235
|
+
if (Object.hasOwn(parsed.options, flag) && queueConsoleOptionString(parsed, flag) === undefined)
|
|
236
|
+
throw new Error(`--${flag} requires a non-empty value.`);
|
|
237
|
+
}
|
|
238
|
+
const pool = queueConsoleOptionString(parsed, 'pool');
|
|
239
|
+
const queues = queueConsoleOptionString(parsed, 'queues');
|
|
240
|
+
const single = queueConsoleOptionString(parsed, 'queue') || parsed.args[0];
|
|
241
|
+
const excluded = queueConsoleOptionString(parsed, 'exclude-queues');
|
|
242
|
+
if (pool) {
|
|
243
|
+
if (queues !== undefined || single !== undefined || excluded !== undefined)
|
|
244
|
+
throw new Error('--pool cannot be combined with queue selection flags.');
|
|
245
|
+
if (!Object.hasOwn(workers, pool))
|
|
246
|
+
throw new Error(`Unknown worker pool "${pool}".`);
|
|
247
|
+
return workers[pool];
|
|
248
|
+
}
|
|
249
|
+
if (queues !== undefined && single !== undefined)
|
|
250
|
+
throw new Error('Use --queues or --queue, not both.');
|
|
251
|
+
const names = queues ?? single ?? process.env.QUEUE_NAME ?? 'default';
|
|
252
|
+
return {
|
|
253
|
+
queues: names === '*' ? '*' : names.split(',').map(name => name.trim()),
|
|
254
|
+
excludeQueues: excluded === undefined ? [] : excluded.split(',').map(name => name.trim()),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
226
257
|
async function dispatchQueueJob(app, parsed) {
|
|
227
258
|
const name = parsed.args[0];
|
|
228
259
|
if (!name) {
|
|
@@ -273,6 +304,9 @@ function defaultHelpText() {
|
|
|
273
304
|
|
|
274
305
|
Options:
|
|
275
306
|
--queue=<name> Queue name, defaults to "default".
|
|
307
|
+
--queues=<names|*> Worker queue names, comma-separated; quote '*'.
|
|
308
|
+
--exclude-queues=<names> Exact queue names this worker cannot claim.
|
|
309
|
+
--pool=<name> Checked-in worker selection; cannot combine with queue flags.
|
|
276
310
|
--delay=<seconds> Delay before the job is available.
|
|
277
311
|
--tries=<count> Maximum attempts before jobs_failed.
|
|
278
312
|
--once Process one available job, then exit.
|
|
@@ -46,8 +46,16 @@ export interface QueueFailedJob {
|
|
|
46
46
|
* recording. Queue owns handler execution and retry decisions.
|
|
47
47
|
*/
|
|
48
48
|
export interface QueueDriver {
|
|
49
|
+
/** Inspects pending, delayed, reserved and chained work for maintenance; callers must quiesce producers first. */
|
|
50
|
+
hasPendingJobs?(jobPrefix: string): Promise<boolean>;
|
|
49
51
|
/** Driver name stored on failed job records and shown in diagnostics. */
|
|
50
52
|
readonly name: QueueDriverName | string;
|
|
53
|
+
/**
|
|
54
|
+
* Discovers names with pending, delayed or reserved work in this driver's namespace.
|
|
55
|
+
* Required for wildcard workers; explicit selections do not need discovery.
|
|
56
|
+
* Returned names may disappear before a claim, which must still be atomic.
|
|
57
|
+
*/
|
|
58
|
+
queueNames?(): Promise<string[]>;
|
|
51
59
|
/**
|
|
52
60
|
* Persists a job so a worker can claim it later.
|
|
53
61
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -82,7 +82,7 @@ export interface DispatchOptions {
|
|
|
82
82
|
/**
|
|
83
83
|
* Named queue/channel the job should be pushed onto.
|
|
84
84
|
*
|
|
85
|
-
* Workers
|
|
85
|
+
* Workers select eligible named queues, so this lets callers route
|
|
86
86
|
* different classes of work to different worker pools. When omitted, the
|
|
87
87
|
* queue service uses its configured default queue name.
|
|
88
88
|
*/
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named queues a worker may consume. Selection never changes a job's queue.
|
|
3
|
+
* Wildcards discover queues within the configured driver connection/namespace;
|
|
4
|
+
* exclusions always win. Names are exact, with no glob or job-class matching.
|
|
5
|
+
*/
|
|
6
|
+
export interface QueueSelection {
|
|
7
|
+
/** Exact queue names, or all currently discoverable names. Defaults to the configured default queue. */
|
|
8
|
+
queues?: readonly string[] | '*';
|
|
9
|
+
/** Exact names that this worker must never claim, including when using '*'. */
|
|
10
|
+
excludeQueues?: readonly string[];
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { QueueMonitor, QueueMonitorOptions } from '../queueMonitor.js';
|
|
2
2
|
import type { QueueEvents } from '../QueueEvents.js';
|
|
3
|
-
import type { QueueableJob } from '
|
|
3
|
+
import type { QueueableJobContract as QueueableJob } from './QueueableJobContract.js';
|
|
4
4
|
import type { QueueLifecycleErrorHandler } from './QueueEvents.js';
|
|
5
5
|
import type { DispatchOptions, QueueDriverName, QueueJob, QueueJobId, QueueProcessResult } from './QueuePayload.js';
|
|
6
6
|
import type { QueueRetryBackoffStrategy } from './QueueRetry.js';
|
|
@@ -8,6 +8,9 @@ import type { QueueDriver, QueueFailedJob } from './QueueDriver.js';
|
|
|
8
8
|
import type { QueueableJobClass } from './QueueableJob.js';
|
|
9
9
|
import type { QueueWorkerLifecycle, QueueWorkerOptions } from './QueueWorkerLifecycle.js';
|
|
10
10
|
import type { RedisQueueDriverOptions } from './RedisQueueDriver.js';
|
|
11
|
+
import type { QueueJobRunner } from './QueueJobRunner.js';
|
|
12
|
+
import type { QueueWorkerSnapshot } from './QueueWorkerSnapshot.js';
|
|
13
|
+
import type { QueueSelection } from './QueueSelection.js';
|
|
11
14
|
/**
|
|
12
15
|
* Function-style handler registered for a durable queued job name.
|
|
13
16
|
*/
|
|
@@ -27,6 +30,8 @@ export type QueueJobResolver = (context: QueueJobResolverContext) => QueueableJo
|
|
|
27
30
|
* Queue service configuration shared by dispatching, processing, and worker startup.
|
|
28
31
|
*/
|
|
29
32
|
export interface QueueOptions {
|
|
33
|
+
/** Receives serialized worker presence every ten seconds and on state changes; errors are isolated from job execution. */
|
|
34
|
+
onWorkerHeartbeat?: (snapshot: QueueWorkerSnapshot) => void | Promise<void>;
|
|
30
35
|
/**
|
|
31
36
|
* Default queue name used when dispatching or processing jobs without an explicit queue.
|
|
32
37
|
*/
|
|
@@ -101,6 +106,10 @@ export interface QueueWorkOptions {
|
|
|
101
106
|
* Public queue service API used by application code and queueable jobs.
|
|
102
107
|
*/
|
|
103
108
|
export interface QueueService {
|
|
109
|
+
/** Registers an owned set of stable names and returns idempotent runtime cleanup. */
|
|
110
|
+
registerJobs(owner: string, jobs: readonly QueueableJobClass[], run?: QueueJobRunner): () => void;
|
|
111
|
+
/** Checks all active storage, including chained work; unsupported drivers reject rather than assume empty. */
|
|
112
|
+
hasPendingJobs(jobPrefix: string): Promise<boolean>;
|
|
104
113
|
/**
|
|
105
114
|
* Always-on asynchronous queue lifecycle event dispatcher.
|
|
106
115
|
*/
|
|
@@ -189,11 +198,16 @@ export interface QueueService {
|
|
|
189
198
|
*/
|
|
190
199
|
workNextJob(queue?: string, options?: QueueWorkOptions): Promise<QueueProcessResult | null>;
|
|
191
200
|
/**
|
|
192
|
-
*
|
|
201
|
+
* Discovers names with pending work in the configured driver namespace.
|
|
202
|
+
* @throws When the driver does not implement wildcard discovery.
|
|
203
|
+
*/
|
|
204
|
+
queueNames(): Promise<string[]>;
|
|
205
|
+
/**
|
|
206
|
+
* Starts a polling worker for a named queue or round-robin selection.
|
|
193
207
|
*
|
|
194
|
-
* @param queue -
|
|
208
|
+
* @param queue - Exact queue name or named-queue selection the worker should poll.
|
|
195
209
|
* @param options - Worker lifecycle and polling options.
|
|
196
210
|
* @returns Worker lifecycle controls, or null when worker startup is disabled.
|
|
197
211
|
*/
|
|
198
|
-
startWorker(queue?: string, options?: QueueWorkerOptions): QueueWorkerLifecycle | null;
|
|
212
|
+
startWorker(queue?: string | QueueSelection, options?: QueueWorkerOptions): QueueWorkerLifecycle | null;
|
|
199
213
|
}
|
|
@@ -55,11 +55,11 @@ export interface QueueWorkerLifecycle {
|
|
|
55
55
|
*/
|
|
56
56
|
start(): void;
|
|
57
57
|
/**
|
|
58
|
-
* Stops
|
|
58
|
+
* Stops claiming further work without aborting the current job.
|
|
59
59
|
*/
|
|
60
60
|
stop(): void;
|
|
61
61
|
/**
|
|
62
|
-
* Stops
|
|
62
|
+
* Stops claiming further work and resolves after the current job has completed.
|
|
63
63
|
*/
|
|
64
64
|
stopAndDrain(): Promise<void>;
|
|
65
65
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { QueueSelection } from './QueueSelection.js';
|
|
2
|
+
/** Process-scoped worker presence, independent of the queue transport and job payloads. */
|
|
3
|
+
export interface QueueWorkerSnapshot {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
hostname: string;
|
|
7
|
+
pid: number;
|
|
8
|
+
selection: QueueSelection;
|
|
9
|
+
status: 'idle' | 'busy' | 'stopping' | 'stopped';
|
|
10
|
+
currentQueue: string | null;
|
|
11
|
+
currentJobId: string | null;
|
|
12
|
+
startedAt: string;
|
|
13
|
+
heartbeatAt: string;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Queue } from '../Queue.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { QueueableJobContract } from './QueueableJobContract.js';
|
|
3
3
|
import type { QueueJob, SerializedQueuedJob } from './QueuePayload.js';
|
|
4
4
|
/**
|
|
5
5
|
* Serialized queueable job payload stored before a driver wraps it in an envelope.
|
|
@@ -13,6 +13,10 @@ export interface QueueableJobContext {
|
|
|
13
13
|
job: QueueJob;
|
|
14
14
|
/** Queue service that is processing this job. */
|
|
15
15
|
queue: Queue;
|
|
16
|
+
/** Confirms this delivery still belongs to the current worker before publishing effects. */
|
|
17
|
+
assertOwnership?(): Promise<void>;
|
|
18
|
+
/** Uses the queue retry policy, including deadline and backoff, for a failed attempt. */
|
|
19
|
+
willRetry?(error: unknown): boolean;
|
|
16
20
|
}
|
|
17
21
|
/**
|
|
18
22
|
* Context passed after a failed attempt has safely been released for retry.
|
|
@@ -33,7 +37,7 @@ export interface QueueableJobFailureContext extends QueueableJobContext {
|
|
|
33
37
|
/**
|
|
34
38
|
* Constructor contract for serializable queueable job classes.
|
|
35
39
|
*/
|
|
36
|
-
export interface QueueableJobClass<TJob extends
|
|
40
|
+
export interface QueueableJobClass<TJob extends QueueableJobContract = QueueableJobContract> {
|
|
37
41
|
/** Runtime class name used as the default durable job name. */
|
|
38
42
|
readonly name: string;
|
|
39
43
|
/** Optional durable job name override. */
|
|
@@ -46,5 +50,5 @@ export interface QueueableJobClass<TJob extends QueueableJob = QueueableJob> {
|
|
|
46
50
|
* @param data - JSON-safe data stored in the queue payload.
|
|
47
51
|
* @returns Queueable job instance ready to handle.
|
|
48
52
|
*/
|
|
49
|
-
fromJSON(data: Record<string, unknown>): TJob
|
|
53
|
+
fromJSON(data: Record<string, unknown>): TJob | Promise<TJob>;
|
|
50
54
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { QueueableJobContext, QueueableJobFailureContext, QueueableJobRetryContext, SerializedQueueableJob } from './QueueableJob.js';
|
|
2
|
+
/** Execution and delivery contract shared by command jobs and persisted runnable records. */
|
|
3
|
+
export interface QueueableJobContract {
|
|
4
|
+
/** Serializes delivery data; persisted runs send only their identity and generation. */
|
|
5
|
+
serialize(): SerializedQueueableJob;
|
|
6
|
+
/** Performs application work after the queue has claimed delivery. */
|
|
7
|
+
handle(context: QueueableJobContext): Promise<void>;
|
|
8
|
+
/** Observes a committed retry; important state must not depend solely on this hook. */
|
|
9
|
+
onRetry(context: QueueableJobRetryContext): Promise<void>;
|
|
10
|
+
/** Observes a committed terminal failure. */
|
|
11
|
+
onFinalFailure(context: QueueableJobFailureContext): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './QueueDriver.js';
|
|
2
|
+
export * from './QueueSelection.js';
|
|
2
3
|
export * from './QueueEvents.js';
|
|
3
4
|
export * from './QueuePayload.js';
|
|
4
5
|
export * from './QueueRetry.js';
|
|
@@ -7,3 +8,6 @@ export * from './QueueService.js';
|
|
|
7
8
|
export * from './QueueWorkerLifecycle.js';
|
|
8
9
|
export * from './RedisQueueDriver.js';
|
|
9
10
|
export * from './CreateJob.js';
|
|
11
|
+
export type { QueueJobRunner } from './QueueJobRunner.js';
|
|
12
|
+
export * from './QueueableJobContract.js';
|
|
13
|
+
export type { QueueWorkerSnapshot } from './QueueWorkerSnapshot.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './QueueDriver.js';
|
|
2
|
+
export * from './QueueSelection.js';
|
|
2
3
|
export * from './QueueEvents.js';
|
|
3
4
|
export * from './QueuePayload.js';
|
|
4
5
|
export * from './QueueRetry.js';
|
|
@@ -7,3 +8,4 @@ export * from './QueueService.js';
|
|
|
7
8
|
export * from './QueueWorkerLifecycle.js';
|
|
8
9
|
export * from './RedisQueueDriver.js';
|
|
9
10
|
export * from './CreateJob.js';
|
|
11
|
+
export * from './QueueableJobContract.js';
|
|
@@ -12,6 +12,10 @@ export declare class DatabaseQueueDriver implements queue.QueueDriver {
|
|
|
12
12
|
* @param db - Database service used for queue persistence.
|
|
13
13
|
*/
|
|
14
14
|
constructor(db: Database);
|
|
15
|
+
/** Discovers queue names from the queue index, including delayed and reserved work. */
|
|
16
|
+
queueNames(): Promise<string[]>;
|
|
17
|
+
/** Scans active work in bounded pages during quiesced maintenance, including delayed and chained payloads. */
|
|
18
|
+
hasPendingJobs(jobPrefix: string): Promise<boolean>;
|
|
15
19
|
/**
|
|
16
20
|
* Persists a job in the `jobs` table.
|
|
17
21
|
*
|