@db3.ai/app 0.1.0-beta.1 → 0.1.0-beta.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/README.md +68 -9
- 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
package/dist/queue/Queue.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RunnableJob } from './RunnableJob.js';
|
|
2
|
+
import { QueueTerminalError } from './QueueTerminalError.js';
|
|
1
3
|
import { randomUUID } from 'node:crypto';
|
|
2
4
|
import { DatabaseQueueDriver } from './drivers/DatabaseQueueDriver.js';
|
|
3
5
|
import { RedisQueueDriver } from './drivers/RedisQueueDriver.js';
|
|
@@ -16,7 +18,9 @@ import { isQueueRetryLaterError } from './QueueRetryLaterError.js';
|
|
|
16
18
|
export class Queue {
|
|
17
19
|
db;
|
|
18
20
|
options;
|
|
21
|
+
#jobClasses = new Map();
|
|
19
22
|
handlers = new Map();
|
|
23
|
+
#ownedJobs = new Map();
|
|
20
24
|
driver;
|
|
21
25
|
monitor;
|
|
22
26
|
events;
|
|
@@ -35,11 +39,52 @@ export class Queue {
|
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
/**
|
|
38
|
-
* Returns the
|
|
42
|
+
* Returns the configured transport name for atomic database dispatch.
|
|
39
43
|
*/
|
|
44
|
+
get driverName() { return this.driver.name; }
|
|
45
|
+
/** Reports worker presence through the application-owned sink without changing delivery semantics. */
|
|
46
|
+
async reportWorker(snapshot) {
|
|
47
|
+
await this.options.onWorkerHeartbeat?.(snapshot);
|
|
48
|
+
}
|
|
49
|
+
/** Returns the optional queue lifecycle monitor. */
|
|
40
50
|
get queueMonitor() {
|
|
41
51
|
return this.monitor;
|
|
42
52
|
}
|
|
53
|
+
/** Registers app-owned stable job names atomically and returns cleanup for this process only. */
|
|
54
|
+
registerJobs(owner, jobs, run = operation => operation()) {
|
|
55
|
+
if (!/^[a-z][a-z0-9_]{0,39}$/.test(owner))
|
|
56
|
+
throw new Error('Invalid queue job owner.');
|
|
57
|
+
const names = new Set();
|
|
58
|
+
for (const Job of jobs) {
|
|
59
|
+
const name = queueableJobName(Job);
|
|
60
|
+
if (!isQueueableJobClass(Job) || !Job.jobName?.startsWith(`${owner}.`) || names.has(name) || this.handlers.has(name))
|
|
61
|
+
throw new Error(`Invalid or duplicate owned job "${name}"; use an explicit ${owner}. jobName.`);
|
|
62
|
+
names.add(name);
|
|
63
|
+
}
|
|
64
|
+
for (const Job of jobs) {
|
|
65
|
+
this.registerJob(Job);
|
|
66
|
+
this.#ownedJobs.set(queueableJobName(Job), { Job, run });
|
|
67
|
+
}
|
|
68
|
+
let closed = false;
|
|
69
|
+
return () => {
|
|
70
|
+
if (closed)
|
|
71
|
+
return;
|
|
72
|
+
closed = true;
|
|
73
|
+
for (const name of names) {
|
|
74
|
+
this.handlers.delete(name);
|
|
75
|
+
this.#jobClasses.delete(name);
|
|
76
|
+
this.#ownedJobs.delete(name);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** Checks active, delayed, reserved and chained payloads after producers have been quiesced. */
|
|
81
|
+
async hasPendingJobs(jobPrefix) {
|
|
82
|
+
if (!jobPrefix.trim())
|
|
83
|
+
throw new Error('A non-empty job prefix is required.');
|
|
84
|
+
if (!this.driver.hasPendingJobs)
|
|
85
|
+
throw new Error(`Queue driver "${this.driver.name}" cannot inspect outstanding app work.`);
|
|
86
|
+
return this.driver.hasPendingJobs(jobPrefix);
|
|
87
|
+
}
|
|
43
88
|
/**
|
|
44
89
|
* Returns recent terminal failures from the configured queue driver.
|
|
45
90
|
*
|
|
@@ -87,6 +132,8 @@ export class Queue {
|
|
|
87
132
|
* Registers an async handler for a named job payload.
|
|
88
133
|
*/
|
|
89
134
|
registerHandler(name, handler) {
|
|
135
|
+
if (this.#ownedJobs.has(name))
|
|
136
|
+
throw new Error(`Job "${name}" belongs to an owned registration.`);
|
|
90
137
|
this.handlers.set(name, job => {
|
|
91
138
|
return {
|
|
92
139
|
handle: () => handler(job),
|
|
@@ -102,11 +149,30 @@ export class Queue {
|
|
|
102
149
|
if (!isQueueableJobClass(Job)) {
|
|
103
150
|
throw new Error('Queue.registerJob requires a QueueableJob class.');
|
|
104
151
|
}
|
|
105
|
-
this.
|
|
106
|
-
|
|
152
|
+
const owned = this.#ownedJobs.get(queueableJobName(Job));
|
|
153
|
+
if (owned) {
|
|
154
|
+
if (owned.Job !== Job)
|
|
155
|
+
throw new Error(`Job "${queueableJobName(Job)}" belongs to another registration.`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
this.#jobClasses.set(queueableJobName(Job), Job);
|
|
159
|
+
this.handlers.set(queueableJobName(Job), async (job) => {
|
|
160
|
+
const instance = await queueableJobFromJSON(Job, job.payload.data);
|
|
107
161
|
const context = this.createQueueableJobContext(job);
|
|
162
|
+
let retryDelay;
|
|
163
|
+
context.willRetry = error => {
|
|
164
|
+
retryDelay ??= queueRetryDelaySeconds(job.payload.backoff ?? this.resolveRetryBackoff(), job.attempts);
|
|
165
|
+
return isQueueRetryLaterError(error) || !(error instanceof QueueTerminalError) && job.attempts < job.payload.maxTries && !queueRetryDeadlineReached(job.payload.retryUntil, retryDelay, unixTimestamp());
|
|
166
|
+
};
|
|
167
|
+
context.assertOwnership = async () => {
|
|
168
|
+
const error = await this.confirmLease(job, this.retryAfterSeconds(), 'checkpoint');
|
|
169
|
+
if (error)
|
|
170
|
+
throw error;
|
|
171
|
+
};
|
|
108
172
|
return {
|
|
109
|
-
|
|
173
|
+
retainsFailure: instance instanceof RunnableJob,
|
|
174
|
+
get retryDelaySeconds() { return retryDelay; },
|
|
175
|
+
handle: () => instance instanceof RunnableJob ? instance.execute(context) : instance.handle(context),
|
|
110
176
|
onRetry: (error, delaySeconds) => instance.onRetry({
|
|
111
177
|
...context,
|
|
112
178
|
error,
|
|
@@ -120,6 +186,21 @@ export class Queue {
|
|
|
120
186
|
});
|
|
121
187
|
}
|
|
122
188
|
async dispatch(job, dataOrOptions = {}, maybeOptions = {}) {
|
|
189
|
+
const dispatchedName = typeof job === 'string' ? job : queueableJobName(job.constructor);
|
|
190
|
+
const Registered = this.#jobClasses.get(dispatchedName);
|
|
191
|
+
// Applications can register a retained implementation of a framework job.
|
|
192
|
+
if (Registered?.prototype instanceof RunnableJob && !(job instanceof RunnableJob)) {
|
|
193
|
+
const input = typeof job === 'string' ? dataOrOptions : job.serialize().data;
|
|
194
|
+
return this.dispatch(new Registered(input), typeof job === 'string' ? maybeOptions : dataOrOptions);
|
|
195
|
+
}
|
|
196
|
+
if (job instanceof RunnableJob && !job.publishingDelivery) {
|
|
197
|
+
const parent = RunnableJob.current();
|
|
198
|
+
if (parent) {
|
|
199
|
+
await parent.assertActive();
|
|
200
|
+
job.parentRunId ??= parent.id;
|
|
201
|
+
}
|
|
202
|
+
return job.enqueue(this, dataOrOptions);
|
|
203
|
+
}
|
|
123
204
|
const serialized = isQueueableJob(job) ? job.serialize() : null;
|
|
124
205
|
const name = resolveDispatchedJobName(job, serialized?.job);
|
|
125
206
|
const options = serialized ? dataOrOptions : maybeOptions;
|
|
@@ -179,6 +260,26 @@ export class Queue {
|
|
|
179
260
|
});
|
|
180
261
|
if (!job)
|
|
181
262
|
return null;
|
|
263
|
+
const owned = this.#ownedJobs.get(job.payload.job);
|
|
264
|
+
if (!owned)
|
|
265
|
+
return this.#workClaimedJob(job, retryAfterSeconds, options);
|
|
266
|
+
let entered = false;
|
|
267
|
+
try {
|
|
268
|
+
return await owned.run(async () => { entered = true; return this.#workClaimedJob(job, retryAfterSeconds, options); });
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (entered)
|
|
272
|
+
throw error;
|
|
273
|
+
// Admission was refused before app code ran. Retain the job without consuming an attempt.
|
|
274
|
+
if (!(await this.driver.defer(job, 30)))
|
|
275
|
+
return this.recordLostLease(job, performance.now(), this.lostLeaseError(job, 'defer'));
|
|
276
|
+
const deferred = { ...job, attempts: Math.max(0, job.attempts - 1) };
|
|
277
|
+
await this.publishJobEvent('deferred', deferred, { delaySeconds: 30, error });
|
|
278
|
+
return { job: deferred, status: 'deferred', delaySeconds: 30, error };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/** Processes an already claimed job and completes its durable transition and hooks before releasing ownership. */
|
|
282
|
+
async #workClaimedJob(job, retryAfterSeconds, options) {
|
|
182
283
|
options.onClaimed?.(job);
|
|
183
284
|
await this.publishJobEvent('claimed', job);
|
|
184
285
|
let execution = null;
|
|
@@ -237,10 +338,12 @@ export class Queue {
|
|
|
237
338
|
error,
|
|
238
339
|
};
|
|
239
340
|
}
|
|
240
|
-
const delaySeconds = queueRetryDelaySeconds(job.payload.backoff ?? this.resolveRetryBackoff(), job.attempts);
|
|
341
|
+
const delaySeconds = execution?.retryDelaySeconds ?? queueRetryDelaySeconds(job.payload.backoff ?? this.resolveRetryBackoff(), job.attempts);
|
|
241
342
|
const retryDeadlineReached = queueRetryDeadlineReached(job.payload.retryUntil, delaySeconds, unixTimestamp());
|
|
242
|
-
if (job.attempts >= job.payload.maxTries || retryDeadlineReached) {
|
|
243
|
-
const failed =
|
|
343
|
+
if (error instanceof QueueTerminalError || job.attempts >= job.payload.maxTries || retryDeadlineReached) {
|
|
344
|
+
const failed = execution?.retainsFailure
|
|
345
|
+
? await this.driver.delete(job)
|
|
346
|
+
: await this.driver.fail(job, error);
|
|
244
347
|
if (!failed) {
|
|
245
348
|
return await this.recordLostLease(job, startedAt, this.lostLeaseError(job, 'fail'));
|
|
246
349
|
}
|
|
@@ -378,12 +481,22 @@ export class Queue {
|
|
|
378
481
|
return new Error(`Queue attempt ${job.attempts} no longer owns ${job.payload.job} job ${String(job.id)}; refused to ${operation}.`);
|
|
379
482
|
}
|
|
380
483
|
/**
|
|
381
|
-
*
|
|
484
|
+
* Discovers named queues without reading or changing job payloads.
|
|
485
|
+
* @throws When a custom driver does not implement wildcard discovery.
|
|
486
|
+
*/
|
|
487
|
+
async queueNames() {
|
|
488
|
+
if (!this.driver.queueNames)
|
|
489
|
+
throw new Error(`Queue driver "${this.driver.name}" does not support wildcard queue discovery.`);
|
|
490
|
+
return this.driver.queueNames();
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Starts a polling worker for a named queue or selection unless disabled.
|
|
494
|
+
* @example queue.startWorker({ queues: '*', excludeQueues: ['articles'] });
|
|
382
495
|
*/
|
|
383
496
|
startWorker(queue = process.env.QUEUE_NAME || this.options.queue || 'default', options = {}) {
|
|
384
497
|
if (this.workerDisabled() && !options.force)
|
|
385
498
|
return null;
|
|
386
|
-
const worker = new QueueWorker(this, queue, options.intervalMs ?? this.workerIntervalMs(), options.maxJobsPerTick ?? this.maxJobsPerTick(), options.logger, options.verbose ?? false);
|
|
499
|
+
const worker = new QueueWorker(this, typeof queue === 'string' ? queue : { ...queue, queues: queue.queues ?? [this.options.queue || 'default'] }, options.intervalMs ?? this.workerIntervalMs(), options.maxJobsPerTick ?? this.maxJobsPerTick(), options.logger, options.verbose ?? false);
|
|
387
500
|
worker.start();
|
|
388
501
|
return worker;
|
|
389
502
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stops a queue delivery immediately, preserving its failed-job record and hooks.
|
|
3
|
+
* Use for a durable failure that ordinary retries cannot repair. Applications
|
|
4
|
+
* still own partial output and progress; explicit replay remains a separate act.
|
|
5
|
+
*/
|
|
6
|
+
export declare class QueueTerminalError extends Error {
|
|
7
|
+
/** Creates an immediately terminal queue failure with a safe explanation. */
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stops a queue delivery immediately, preserving its failed-job record and hooks.
|
|
3
|
+
* Use for a durable failure that ordinary retries cannot repair. Applications
|
|
4
|
+
* still own partial output and progress; explicit replay remains a separate act.
|
|
5
|
+
*/
|
|
6
|
+
export class QueueTerminalError extends Error {
|
|
7
|
+
/** Creates an immediately terminal queue failure with a safe explanation. */
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'QueueTerminalError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { Queue } from './Queue.js';
|
|
|
2
2
|
import type * as queue from './contracts/index.js';
|
|
3
3
|
export type { QueueLogger, QueueWorkerLifecycle, QueueWorkerOptions } from './contracts/index.js';
|
|
4
4
|
/**
|
|
5
|
-
* Polls
|
|
5
|
+
* Polls eligible named queues in round-robin order, executing one job at a time.
|
|
6
6
|
*
|
|
7
7
|
* The worker intentionally owns only timer and lifecycle behavior. It delegates claims,
|
|
8
8
|
* handler execution, retries, and failure recording back to Queue.
|
|
@@ -10,25 +10,32 @@ export type { QueueLogger, QueueWorkerLifecycle, QueueWorkerOptions } from './co
|
|
|
10
10
|
export declare class QueueWorker implements queue.QueueWorkerLifecycle {
|
|
11
11
|
#private;
|
|
12
12
|
private readonly queueManager;
|
|
13
|
-
private readonly queue;
|
|
14
13
|
private readonly logger?;
|
|
15
14
|
private readonly verbose;
|
|
15
|
+
private readonly queue;
|
|
16
16
|
private timer;
|
|
17
17
|
private readonly intervalMs;
|
|
18
18
|
private readonly maxJobsPerTick;
|
|
19
|
-
|
|
19
|
+
/** Creates a worker without starting its polling loop; workOnce can be used for bounded execution. */
|
|
20
|
+
constructor(queueManager: Queue, selection?: string | queue.QueueSelection, intervalMs?: number, maxJobsPerTick?: number, logger?: queue.QueueLogger | undefined, verbose?: boolean);
|
|
20
21
|
/**
|
|
21
22
|
* Starts the worker with an immediate tick followed by interval-based polling.
|
|
22
23
|
*/
|
|
23
24
|
start(): void;
|
|
24
25
|
/**
|
|
25
|
-
* Stops future
|
|
26
|
+
* Stops future claims. An already-running job is allowed to finish.
|
|
26
27
|
*/
|
|
27
28
|
stop(): void;
|
|
28
29
|
/**
|
|
29
|
-
* Stops future
|
|
30
|
+
* Stops future claims and waits for the current job, including timer-free execution.
|
|
30
31
|
*/
|
|
31
32
|
stopAndDrain(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Processes at most one eligible job, rotating after each claim and skipping empty queues.
|
|
35
|
+
* Wildcard discovery is refreshed on every call, including after an idle poll.
|
|
36
|
+
* Concurrent calls are rejected so one worker cannot occupy multiple execution slots.
|
|
37
|
+
*/
|
|
38
|
+
workOnce(options?: queue.QueueWorkOptions): Promise<queue.QueueProcessResult | null>;
|
|
32
39
|
/**
|
|
33
40
|
* Starts one tick when the previous tick is no longer running.
|
|
34
41
|
*/
|
|
@@ -1,30 +1,47 @@
|
|
|
1
|
+
import { QueueWorkerReporter } from './QueueWorkerReporter.js';
|
|
1
2
|
import { unknownErrorMessage } from '@db3.ai/pure';
|
|
2
3
|
const DEFAULT_WORKER_INTERVAL_MS = 1000;
|
|
3
4
|
const MIN_WORKER_INTERVAL_MS = 100;
|
|
4
5
|
const DEFAULT_MAX_JOBS_PER_TICK = 5;
|
|
5
6
|
const MIN_MAX_JOBS_PER_TICK = 1;
|
|
6
7
|
/**
|
|
7
|
-
* Polls
|
|
8
|
+
* Polls eligible named queues in round-robin order, executing one job at a time.
|
|
8
9
|
*
|
|
9
10
|
* The worker intentionally owns only timer and lifecycle behavior. It delegates claims,
|
|
10
11
|
* handler execution, retries, and failure recording back to Queue.
|
|
11
12
|
*/
|
|
12
13
|
export class QueueWorker {
|
|
13
14
|
queueManager;
|
|
14
|
-
queue;
|
|
15
15
|
logger;
|
|
16
16
|
verbose;
|
|
17
|
+
#presence;
|
|
17
18
|
#activeTick = null;
|
|
19
|
+
#activeJob = null;
|
|
20
|
+
#lastQueue = null;
|
|
21
|
+
#stopping = false;
|
|
22
|
+
#queues;
|
|
23
|
+
#excludeQueues;
|
|
24
|
+
queue;
|
|
18
25
|
timer = null;
|
|
19
26
|
intervalMs;
|
|
20
27
|
maxJobsPerTick;
|
|
21
|
-
|
|
28
|
+
/** Creates a worker without starting its polling loop; workOnce can be used for bounded execution. */
|
|
29
|
+
constructor(queueManager, selection = 'default', intervalMs = Number(process.env.QUEUE_WORKER_INTERVAL_MS || DEFAULT_WORKER_INTERVAL_MS), maxJobsPerTick = Number(process.env.QUEUE_WORKER_MAX_JOBS_PER_TICK || DEFAULT_MAX_JOBS_PER_TICK), logger, verbose = false) {
|
|
22
30
|
this.queueManager = queueManager;
|
|
23
|
-
this.queue = queue;
|
|
24
31
|
this.logger = logger;
|
|
25
32
|
this.verbose = verbose;
|
|
33
|
+
const requested = typeof selection === 'string' ? { queues: [selection] } : selection;
|
|
34
|
+
this.#queues = requested.queues === '*' ? '*' : normalizeQueueNames(requested.queues ?? ['default']);
|
|
35
|
+
if (this.#queues !== '*' && this.#queues.length === 0)
|
|
36
|
+
throw new Error('A worker must select at least one queue.');
|
|
37
|
+
this.#excludeQueues = new Set(normalizeQueueNames(requested.excludeQueues ?? []));
|
|
38
|
+
if (this.#queues !== '*' && this.#queues.every(name => this.#excludeQueues.has(name)))
|
|
39
|
+
throw new Error('Worker queue exclusions leave no eligible queues.');
|
|
40
|
+
this.queue = (this.#queues === '*' ? '*' : this.#queues.join(', '))
|
|
41
|
+
+ (this.#excludeQueues.size ? ` excluding ${[...this.#excludeQueues].join(', ')}` : '');
|
|
26
42
|
this.intervalMs = normalizeWorkerIntervalMs(intervalMs);
|
|
27
43
|
this.maxJobsPerTick = normalizeMaxJobsPerTick(maxJobsPerTick);
|
|
44
|
+
this.#presence = new QueueWorkerReporter({ queues: this.#queues, excludeQueues: [...this.#excludeQueues] }, snapshot => this.queueManager.reportWorker(snapshot), this.logger);
|
|
28
45
|
}
|
|
29
46
|
/**
|
|
30
47
|
* Starts the worker with an immediate tick followed by interval-based polling.
|
|
@@ -32,18 +49,25 @@ export class QueueWorker {
|
|
|
32
49
|
start() {
|
|
33
50
|
if (this.timer)
|
|
34
51
|
return;
|
|
52
|
+
this.#stopping = false;
|
|
35
53
|
this.logger?.info(this.verbose
|
|
36
54
|
? `[queue] Worker started for "${this.queue}" (interval ${this.intervalMs}ms, max ${this.maxJobsPerTick} jobs/tick).`
|
|
37
55
|
: `[queue] Worker started for "${this.queue}".`);
|
|
38
|
-
this.
|
|
56
|
+
this.#presence.start();
|
|
39
57
|
this.timer = setInterval(() => {
|
|
40
58
|
this.startTick();
|
|
41
59
|
}, this.intervalMs);
|
|
60
|
+
this.startTick();
|
|
42
61
|
}
|
|
43
62
|
/**
|
|
44
|
-
* Stops future
|
|
63
|
+
* Stops future claims. An already-running job is allowed to finish.
|
|
45
64
|
*/
|
|
46
65
|
stop() {
|
|
66
|
+
this.#stopping = true;
|
|
67
|
+
if (this.#activeJob)
|
|
68
|
+
this.#presence.update('stopping');
|
|
69
|
+
else
|
|
70
|
+
void this.#presence.stop();
|
|
47
71
|
if (!this.timer)
|
|
48
72
|
return;
|
|
49
73
|
clearInterval(this.timer);
|
|
@@ -51,13 +75,67 @@ export class QueueWorker {
|
|
|
51
75
|
this.logger?.info(`[queue] Worker stopped for "${this.queue}".`);
|
|
52
76
|
}
|
|
53
77
|
/**
|
|
54
|
-
* Stops future
|
|
78
|
+
* Stops future claims and waits for the current job, including timer-free execution.
|
|
55
79
|
*/
|
|
56
80
|
async stopAndDrain() {
|
|
57
81
|
this.stop();
|
|
58
82
|
if (this.#activeTick) {
|
|
59
83
|
await this.#activeTick;
|
|
60
84
|
}
|
|
85
|
+
await this.#activeJob;
|
|
86
|
+
await this.#presence.stop();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Processes at most one eligible job, rotating after each claim and skipping empty queues.
|
|
90
|
+
* Wildcard discovery is refreshed on every call, including after an idle poll.
|
|
91
|
+
* Concurrent calls are rejected so one worker cannot occupy multiple execution slots.
|
|
92
|
+
*/
|
|
93
|
+
async workOnce(options = {}) {
|
|
94
|
+
if (this.#activeJob)
|
|
95
|
+
throw new Error('This queue worker is already processing a job.');
|
|
96
|
+
if (this.#stopping)
|
|
97
|
+
return null;
|
|
98
|
+
this.#presence.start();
|
|
99
|
+
const pending = this.#workOnce(options);
|
|
100
|
+
this.#activeJob = pending;
|
|
101
|
+
try {
|
|
102
|
+
return await pending;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
this.#activeJob = null;
|
|
106
|
+
if (this.#stopping || !this.timer)
|
|
107
|
+
await this.#presence.stop();
|
|
108
|
+
else
|
|
109
|
+
this.#presence.update('idle');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Resolves eligible names and delegates each atomic claim to the queue service. */
|
|
113
|
+
async #workOnce(options) {
|
|
114
|
+
const names = (this.#queues === '*' ? [...new Set(await this.queueManager.queueNames())].sort() : [...this.#queues])
|
|
115
|
+
.filter(name => !this.#excludeQueues.has(name));
|
|
116
|
+
let start = 0;
|
|
117
|
+
if (this.#lastQueue !== null) {
|
|
118
|
+
const previous = names.indexOf(this.#lastQueue);
|
|
119
|
+
start = previous >= 0 ? previous + 1 : names.findIndex(name => name > this.#lastQueue);
|
|
120
|
+
if (start < 0 || start >= names.length)
|
|
121
|
+
start = 0;
|
|
122
|
+
}
|
|
123
|
+
for (let offset = 0; offset < names.length && !this.#stopping; offset++) {
|
|
124
|
+
const name = names[(start + offset) % names.length];
|
|
125
|
+
const result = await this.queueManager.workNextJob(name, {
|
|
126
|
+
...options,
|
|
127
|
+
onClaimed: job => {
|
|
128
|
+
this.#lastQueue = name;
|
|
129
|
+
this.#presence.update('busy', job.queue, String(job.id));
|
|
130
|
+
options.onClaimed?.(job);
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
if (result) {
|
|
134
|
+
this.#lastQueue = name;
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
61
139
|
}
|
|
62
140
|
/**
|
|
63
141
|
* Starts one tick when the previous tick is no longer running.
|
|
@@ -79,8 +157,8 @@ export class QueueWorker {
|
|
|
79
157
|
async tick() {
|
|
80
158
|
let processedThisTick = 0;
|
|
81
159
|
try {
|
|
82
|
-
for (let processed = 0; processed < this.maxJobsPerTick; processed += 1) {
|
|
83
|
-
const result = await this.
|
|
160
|
+
for (let processed = 0; processed < this.maxJobsPerTick && !this.#stopping; processed += 1) {
|
|
161
|
+
const result = await this.workOnce({
|
|
84
162
|
onClaimed: job => this.logClaimed(job),
|
|
85
163
|
});
|
|
86
164
|
if (!result) {
|
|
@@ -173,6 +251,13 @@ export class QueueWorker {
|
|
|
173
251
|
}
|
|
174
252
|
}
|
|
175
253
|
export { QueueWorker as DatabaseQueueWorker };
|
|
254
|
+
/** Validates and copies exact queue names so caller mutations cannot alter worker admission. */
|
|
255
|
+
function normalizeQueueNames(names) {
|
|
256
|
+
if (!Array.isArray(names) || names.some(name => typeof name !== 'string' || !name.trim() || name !== name.trim() || name === '*')) {
|
|
257
|
+
throw new Error('Queue names must be non-empty exact names; use queues: "*" to select all queues.');
|
|
258
|
+
}
|
|
259
|
+
return [...new Set(names)];
|
|
260
|
+
}
|
|
176
261
|
/**
|
|
177
262
|
* Formats a singular or plural word for a count.
|
|
178
263
|
*
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { QueueWorkerSnapshot, QueueSelection, QueueLogger } from './contracts/index.js';
|
|
2
|
+
/** Serializes small presence writes; a slow or unavailable sink cannot build an unbounded backlog or stop jobs. */
|
|
3
|
+
export declare class QueueWorkerReporter {
|
|
4
|
+
#private;
|
|
5
|
+
private readonly publish;
|
|
6
|
+
private readonly logger?;
|
|
7
|
+
/** Creates an identity unique to this worker, including multiple workers in the same process. */
|
|
8
|
+
constructor(selection: QueueSelection, publish: (snapshot: QueueWorkerSnapshot) => Promise<void>, logger?: QueueLogger | undefined);
|
|
9
|
+
/** Starts liveness updates, including while a long job is awaiting network work. */
|
|
10
|
+
start(): void;
|
|
11
|
+
/** Updates the latest state without queuing one database write per job or poll. */
|
|
12
|
+
update(status: QueueWorkerSnapshot['status'], currentQueue?: string | null, currentJobId?: string | null): void;
|
|
13
|
+
/** Stops timers immediately and flushes a final state when the worker drains. */
|
|
14
|
+
stop(): Promise<void>;
|
|
15
|
+
/** Coalesces concurrent updates and isolates sink errors from claims and handlers. */
|
|
16
|
+
flush(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { hostname } from 'node:os';
|
|
2
|
+
import { ulid } from '@db3.ai/pure/ulid';
|
|
3
|
+
/** Serializes small presence writes; a slow or unavailable sink cannot build an unbounded backlog or stop jobs. */
|
|
4
|
+
export class QueueWorkerReporter {
|
|
5
|
+
publish;
|
|
6
|
+
logger;
|
|
7
|
+
#snapshot;
|
|
8
|
+
#timer = null;
|
|
9
|
+
#pending = null;
|
|
10
|
+
#dirty = false;
|
|
11
|
+
/** Creates an identity unique to this worker, including multiple workers in the same process. */
|
|
12
|
+
constructor(selection, publish, logger) {
|
|
13
|
+
this.publish = publish;
|
|
14
|
+
this.logger = logger;
|
|
15
|
+
const now = new Date().toISOString();
|
|
16
|
+
this.#snapshot = { id: ulid(), name: process.env.QUEUE_WORKER_NAME || 'queue-worker', hostname: hostname(), pid: process.pid, selection, status: 'idle', currentQueue: null, currentJobId: null, startedAt: now, heartbeatAt: now };
|
|
17
|
+
}
|
|
18
|
+
/** Starts liveness updates, including while a long job is awaiting network work. */
|
|
19
|
+
start() {
|
|
20
|
+
if (this.#timer)
|
|
21
|
+
return;
|
|
22
|
+
this.#timer = setInterval(() => { void this.flush(); }, 10_000);
|
|
23
|
+
this.#timer.unref();
|
|
24
|
+
this.update('idle');
|
|
25
|
+
void this.flush();
|
|
26
|
+
}
|
|
27
|
+
/** Updates the latest state without queuing one database write per job or poll. */
|
|
28
|
+
update(status, currentQueue = null, currentJobId = null) {
|
|
29
|
+
if (status === 'stopping') {
|
|
30
|
+
currentQueue = this.#snapshot.currentQueue;
|
|
31
|
+
currentJobId = this.#snapshot.currentJobId;
|
|
32
|
+
}
|
|
33
|
+
if (this.#snapshot.status === status && this.#snapshot.currentQueue === currentQueue && this.#snapshot.currentJobId === currentJobId)
|
|
34
|
+
return;
|
|
35
|
+
this.#snapshot = { ...this.#snapshot, status, currentQueue, currentJobId };
|
|
36
|
+
void this.flush();
|
|
37
|
+
}
|
|
38
|
+
/** Stops timers immediately and flushes a final state when the worker drains. */
|
|
39
|
+
async stop() {
|
|
40
|
+
if (this.#timer)
|
|
41
|
+
clearInterval(this.#timer);
|
|
42
|
+
this.#timer = null;
|
|
43
|
+
this.update('stopped');
|
|
44
|
+
await this.flush();
|
|
45
|
+
}
|
|
46
|
+
/** Coalesces concurrent updates and isolates sink errors from claims and handlers. */
|
|
47
|
+
async flush() {
|
|
48
|
+
this.#dirty = true;
|
|
49
|
+
if (this.#pending)
|
|
50
|
+
return this.#pending;
|
|
51
|
+
this.#pending = this.#drain();
|
|
52
|
+
try {
|
|
53
|
+
await this.#pending;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
this.#pending = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Writes the most recent immutable snapshot, retaining changes made while a write was pending. */
|
|
60
|
+
async #drain() {
|
|
61
|
+
while (this.#dirty) {
|
|
62
|
+
this.#dirty = false;
|
|
63
|
+
try {
|
|
64
|
+
await this.publish(structuredClone({ ...this.#snapshot, heartbeatAt: new Date().toISOString() }));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
this.logger?.warn?.('[queue] Unable to publish worker presence.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -81,7 +81,7 @@ export declare abstract class QueueableJob<TData extends Record<string, unknown>
|
|
|
81
81
|
* @param value - Unknown value to inspect.
|
|
82
82
|
* @returns True when the value is a queueable job instance.
|
|
83
83
|
*/
|
|
84
|
-
export declare function isQueueableJob(value: unknown): value is
|
|
84
|
+
export declare function isQueueableJob(value: unknown): value is queue.QueueableJobContract;
|
|
85
85
|
/**
|
|
86
86
|
* Returns true when a class looks like a QueueableJob subclass.
|
|
87
87
|
*
|
|
@@ -106,4 +106,4 @@ export declare function queueableJobName(Job: queue.QueueableJobClass | {
|
|
|
106
106
|
* @param data - JSON payload data stored in the queue envelope.
|
|
107
107
|
* @returns Rehydrated queueable job instance.
|
|
108
108
|
*/
|
|
109
|
-
export declare function queueableJobFromJSON(Job: queue.QueueableJobClass, data: Record<string, unknown>):
|
|
109
|
+
export declare function queueableJobFromJSON(Job: queue.QueueableJobClass, data: Record<string, unknown>): queue.QueueableJobContract | Promise<queue.QueueableJobContract>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ActiveRecord } from '../db/ActiveRecord.js';
|
|
2
|
+
import type { Queue } from './Queue.js';
|
|
3
|
+
import type { DispatchOptions, QueueJobId, QueueableJobContext, QueueableJobContract, QueueableJobFailureContext, QueueableJobRetryContext, SerializedQueueableJob } from './contracts/index.js';
|
|
4
|
+
/** Persisted lifecycle values; waiting includes scheduled retries, blocked requires an explicit new run. */
|
|
5
|
+
export declare const JOB_RUN_STATUSES: readonly ["waiting", "running", "blocked", "completed", "failed", "cancelled"];
|
|
6
|
+
declare const RunnableJob_base: import("../db/index.js").DefinedActiveRecord<typeof ActiveRecord, {
|
|
7
|
+
id: import("../db/index.js").UlidField;
|
|
8
|
+
jobType: import("../db/index.js").StringField;
|
|
9
|
+
tenantId: import("../db/index.js").StringField;
|
|
10
|
+
subjectId: import("../db/index.js").StringField;
|
|
11
|
+
actorId: import("../db/index.js").StringField;
|
|
12
|
+
parentRunId: import("../db/index.js").StringField;
|
|
13
|
+
trigger: import("../db/index.js").StringField;
|
|
14
|
+
status: import("../db/index.js").ChoiceStringField;
|
|
15
|
+
input: import("../db/index.js").JsonField<Record<string, unknown> | null>;
|
|
16
|
+
state: import("../db/index.js").JsonField<Record<string, unknown> | null>;
|
|
17
|
+
result: import("../db/index.js").JsonField<Record<string, unknown> | null>;
|
|
18
|
+
error: import("../db/index.js").TextField;
|
|
19
|
+
stage: import("../db/index.js").StringField;
|
|
20
|
+
completed: import("../db/index.js").IntegerField;
|
|
21
|
+
total: import("../db/index.js").IntegerField;
|
|
22
|
+
failures: import("../db/index.js").IntegerField;
|
|
23
|
+
attemptCount: import("../db/index.js").IntegerField;
|
|
24
|
+
deliveryKey: import("../db/index.js").StringField;
|
|
25
|
+
leaseToken: import("../db/index.js").StringField;
|
|
26
|
+
cancelRequestedAt: import("../db/index.js").TimestampField;
|
|
27
|
+
queuedAt: import("../db/index.js").TimestampField;
|
|
28
|
+
startedAt: import("../db/index.js").TimestampField;
|
|
29
|
+
heartbeatAt: import("../db/index.js").TimestampField;
|
|
30
|
+
completedAt: import("../db/index.js").TimestampField;
|
|
31
|
+
createdAt: import("../db/index.js").TimestampField;
|
|
32
|
+
updatedAt: import("../db/index.js").TimestampField;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* A retained run with application-owned input, state and behaviour. Register only
|
|
36
|
+
* this base model in migrations; concrete job classes share its table. Jobs must
|
|
37
|
+
* use checkpoint/save for durable work and make external effects idempotent.
|
|
38
|
+
* Tenant and subject identities are immutable; applications authorize launches
|
|
39
|
+
* and reads. Queue serialization contains only the saved run ID and generation.
|
|
40
|
+
*/
|
|
41
|
+
export declare class RunnableJob extends RunnableJob_base implements QueueableJobContract {
|
|
42
|
+
#private;
|
|
43
|
+
/** Stable name may be overridden to preserve queued identities across class renames. */
|
|
44
|
+
static jobName?: string;
|
|
45
|
+
/** Returns the active run for child dispatch correlation within this asynchronous execution only. */
|
|
46
|
+
static current(): RunnableJob | undefined;
|
|
47
|
+
/** Internal dispatch guard; a saved delivery cannot be enqueued twice through the public API. */
|
|
48
|
+
get publishingDelivery(): boolean;
|
|
49
|
+
/** Cooperative abort signal. Application requests should combine it with their own deadline. */
|
|
50
|
+
get signal(): AbortSignal;
|
|
51
|
+
/** Loads the authoritative run through its concrete registered class, rejecting mismatched deliveries. */
|
|
52
|
+
static fromJSON<T extends typeof RunnableJob>(this: T, data: Record<string, unknown>): Promise<InstanceType<T>>;
|
|
53
|
+
/** Saves a new run before dispatch. During execution, saves only application-owned fields under the attempt fence. */
|
|
54
|
+
save(): Promise<this>;
|
|
55
|
+
/** Serializes concurrent progress callbacks so state merges cannot lose another completed item's update. */
|
|
56
|
+
checkpoint(update: (run: this) => void): Promise<void>;
|
|
57
|
+
/** Checks delivery ownership and operator cancellation before launching or publishing another unit of work. */
|
|
58
|
+
assertActive(): Promise<void>;
|
|
59
|
+
/** Appends bounded structured diagnostics; callers must omit credentials and private provider payloads. */
|
|
60
|
+
log(message: string, data?: Record<string, unknown>, level?: 'info' | 'warning' | 'error'): Promise<void>;
|
|
61
|
+
/** Stops launching further work until an operator creates a resumed run using the saved checkpoint. */
|
|
62
|
+
block(reason: string): never;
|
|
63
|
+
/** Resolves application-owned input/scope before first persistence. Override in a tenant-aware application base class. */
|
|
64
|
+
prepare(): Promise<void>;
|
|
65
|
+
/** Saves a run and its dispatch generation before delivery. Failed dispatches remain visible in history. */
|
|
66
|
+
enqueue(queue: Queue, options?: DispatchOptions): Promise<QueueJobId>;
|
|
67
|
+
/** Produces a small immutable queue reference; never copies mutable model JSON into delivery storage. */
|
|
68
|
+
serialize(): SerializedQueueableJob;
|
|
69
|
+
/** Concrete application jobs implement their own bounded work, checkpoints and result publication. */
|
|
70
|
+
handle(_context: QueueableJobContext): Promise<void>;
|
|
71
|
+
/** Lifecycle is saved before delivery transitions; ordinary queue retry hooks are intentionally empty. */
|
|
72
|
+
onRetry(_context: QueueableJobRetryContext): Promise<void>;
|
|
73
|
+
/** Lifecycle is saved before delivery transitions, including terminal failure. */
|
|
74
|
+
onFinalFailure(context: QueueableJobFailureContext): Promise<void>;
|
|
75
|
+
/** Runs one fenced attempt. Expired delivery recovery preserves checkpoints and records the interrupted attempt. */
|
|
76
|
+
execute(context: QueueableJobContext): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
export {};
|