@backstage/backend-defaults 0.11.2-next.0 → 0.12.1-next.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/config.d.ts +195 -0
  3. package/dist/CreateBackend.cjs.js.map +1 -1
  4. package/dist/PackageDiscoveryService.cjs.js +13 -3
  5. package/dist/PackageDiscoveryService.cjs.js.map +1 -1
  6. package/dist/alpha/entrypoints/actions/DefaultActionsService.cjs.js.map +1 -1
  7. package/dist/alpha/entrypoints/actions/actionsServiceFactory.cjs.js.map +1 -1
  8. package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +1 -1
  9. package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +1 -1
  10. package/dist/cache.d.ts +20 -1
  11. package/dist/database.d.ts +1 -1
  12. package/dist/discovery.d.ts +1 -1
  13. package/dist/discoveryFeatureLoader.cjs.js.map +1 -1
  14. package/dist/entrypoints/auditor/DefaultAuditorService.cjs.js.map +1 -1
  15. package/dist/entrypoints/auditor/WinstonRootAuditorService.cjs.js.map +1 -1
  16. package/dist/entrypoints/auditor/auditorServiceFactory.cjs.js.map +1 -1
  17. package/dist/entrypoints/auditor/types.cjs.js.map +1 -1
  18. package/dist/entrypoints/auditor/utils.cjs.js.map +1 -1
  19. package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -1
  20. package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -1
  21. package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -1
  22. package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js.map +1 -1
  23. package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -1
  24. package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -1
  25. package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -1
  26. package/dist/entrypoints/auth/external/static.cjs.js.map +1 -1
  27. package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
  28. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -1
  29. package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -1
  30. package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -1
  31. package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -1
  32. package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -1
  33. package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -1
  34. package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -1
  35. package/dist/entrypoints/cache/CacheManager.cjs.js +112 -7
  36. package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -1
  37. package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -1
  38. package/dist/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.cjs.js +141 -0
  39. package/dist/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.cjs.js.map +1 -0
  40. package/dist/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.cjs.js +129 -0
  41. package/dist/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.cjs.js.map +1 -0
  42. package/dist/entrypoints/cache/types.cjs.js.map +1 -1
  43. package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -1
  44. package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -1
  45. package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js.map +1 -1
  46. package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -1
  47. package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -1
  48. package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
  49. package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -1
  50. package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -1
  51. package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -1
  52. package/dist/entrypoints/discovery/SrvResolvers.cjs.js.map +1 -1
  53. package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -1
  54. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -1
  55. package/dist/entrypoints/httpRouter/http/createAuthIntegrationRouter.cjs.js.map +1 -1
  56. package/dist/entrypoints/httpRouter/http/createCookieAuthRefreshMiddleware.cjs.js.map +1 -1
  57. package/dist/entrypoints/httpRouter/http/createCredentialsBarrier.cjs.js.map +1 -1
  58. package/dist/entrypoints/httpRouter/http/createLifecycleMiddleware.cjs.js.map +1 -1
  59. package/dist/entrypoints/httpRouter/http/createRateLimitMiddleware.cjs.js.map +1 -1
  60. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
  61. package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -1
  62. package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -1
  63. package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -1
  64. package/dist/entrypoints/permissionsRegistry/permissionsRegistryServiceFactory.cjs.js.map +1 -1
  65. package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -1
  66. package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -1
  67. package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -1
  68. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -1
  69. package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -1
  70. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -1
  71. package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -1
  72. package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -1
  73. package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -1
  74. package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -1
  75. package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -1
  76. package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -1
  77. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
  78. package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -1
  79. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -1
  80. package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -1
  81. package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -1
  82. package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -1
  83. package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -1
  84. package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -1
  85. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -1
  86. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -1
  87. package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -1
  88. package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
  89. package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -1
  90. package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -1
  91. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -1
  92. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -1
  93. package/dist/entrypoints/urlReader/lib/AzureBlobStorageUrlReader.cjs.js.map +1 -1
  94. package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -1
  95. package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -1
  96. package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -1
  97. package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -1
  98. package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -1
  99. package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -1
  100. package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -1
  101. package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -1
  102. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
  103. package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -1
  104. package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -1
  105. package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -1
  106. package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -1
  107. package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -1
  108. package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -1
  109. package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -1
  110. package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -1
  111. package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -1
  112. package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -1
  113. package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
  114. package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -1
  115. package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -1
  116. package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -1
  117. package/dist/httpAuth.d.ts +1 -1
  118. package/dist/lib/RateLimitStoreFactory.cjs.js.map +1 -1
  119. package/dist/lib/escapeRegExp.cjs.js.map +1 -1
  120. package/dist/lib/rateLimitMiddleware.cjs.js.map +1 -1
  121. package/dist/package.json.cjs.js +2 -269
  122. package/dist/package.json.cjs.js.map +1 -1
  123. package/dist/urlReader.d.ts +1 -1
  124. package/package.json +12 -11
@@ -1 +1 @@
1
- {"version":3,"file":"rootHttpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n LifecycleService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport express, { Express, RequestHandler } from 'express';\nimport type { Server } from 'node:http';\nimport {\n createHttpServer,\n MiddlewareFactory,\n readHttpServerOptions,\n} from './http';\nimport { DefaultRootHttpRouter } from './DefaultRootHttpRouter';\nimport { createHealthRouter } from './createHealthRouter';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { readDurationFromConfig } from '@backstage/config';\n\n/**\n * @public\n */\nexport interface RootHttpRouterConfigureContext {\n app: Express;\n server: Server;\n middleware: MiddlewareFactory;\n routes: RequestHandler;\n config: RootConfigService;\n logger: LoggerService;\n lifecycle: LifecycleService;\n healthRouter: RequestHandler;\n applyDefaults: () => void;\n}\n\n/**\n * HTTP route registration for root services.\n *\n * See {@link @backstage/code-plugin-api#RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport type RootHttpRouterFactoryOptions = {\n /**\n * The path to forward all unmatched requests to. Defaults to '/api/app' if\n * not given. Disables index path behavior if false is given.\n */\n indexPath?: string | false;\n\n configure?(context: RootHttpRouterConfigureContext): void;\n};\n\nfunction defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) {\n applyDefaults();\n}\n\nconst rootHttpRouterServiceFactoryWithOptions = (\n options?: RootHttpRouterFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n rootLogger: coreServices.rootLogger,\n lifecycle: coreServices.rootLifecycle,\n health: coreServices.rootHealth,\n },\n async factory({ config, rootLogger, lifecycle, health }) {\n const { indexPath, configure = defaultConfigure } = options ?? {};\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n const app = express();\n\n const trustProxy = config.getOptional('backend.trustProxy');\n\n const router = DefaultRootHttpRouter.create({ indexPath });\n const middleware = MiddlewareFactory.create({ config, logger });\n const routes = router.handler();\n\n const healthRouter = createHealthRouter({ config, health });\n\n const server = await createHttpServer(\n app,\n readHttpServerOptions(config.getOptionalConfig('backend')),\n { logger },\n );\n\n configure({\n app,\n server,\n routes,\n middleware,\n config,\n logger,\n lifecycle,\n healthRouter,\n applyDefaults() {\n if (process.env.NODE_ENV === 'development') {\n app.set('json spaces', 2);\n }\n if (trustProxy !== undefined) {\n app.set('trust proxy', trustProxy);\n }\n app.use(middleware.helmet());\n app.use(middleware.cors());\n app.use(middleware.compression());\n app.use(middleware.logging());\n app.use(middleware.rateLimit());\n app.use(healthRouter);\n app.use(routes);\n app.use(middleware.notFound());\n app.use(middleware.error());\n },\n });\n\n if (config.has('backend.lifecycle.serverShutdownDelay')) {\n const serverShutdownDelay = readDurationFromConfig(config, {\n key: 'backend.lifecycle.serverShutdownDelay',\n });\n lifecycle.addBeforeShutdownHook(async () => {\n const timeoutMs = durationToMilliseconds(serverShutdownDelay);\n return await new Promise(resolve => {\n setTimeout(resolve, timeoutMs);\n });\n });\n }\n\n lifecycle.addShutdownHook(() => server.stop());\n\n await server.start();\n\n return router;\n },\n });\n\n/** @public */\nexport const rootHttpRouterServiceFactory = Object.assign(\n rootHttpRouterServiceFactoryWithOptions,\n rootHttpRouterServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","config","express","DefaultRootHttpRouter","MiddlewareFactory","createHealthRouter","createHttpServer","readHttpServerOptions","readDurationFromConfig","durationToMilliseconds"],"mappings":"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"}
1
+ {"version":3,"file":"rootHttpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n LifecycleService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport express, { Express, RequestHandler } from 'express';\nimport type { Server } from 'node:http';\nimport {\n createHttpServer,\n MiddlewareFactory,\n readHttpServerOptions,\n} from './http';\nimport { DefaultRootHttpRouter } from './DefaultRootHttpRouter';\nimport { createHealthRouter } from './createHealthRouter';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { readDurationFromConfig } from '@backstage/config';\n\n/**\n * @public\n */\nexport interface RootHttpRouterConfigureContext {\n app: Express;\n server: Server;\n middleware: MiddlewareFactory;\n routes: RequestHandler;\n config: RootConfigService;\n logger: LoggerService;\n lifecycle: LifecycleService;\n healthRouter: RequestHandler;\n applyDefaults: () => void;\n}\n\n/**\n * HTTP route registration for root services.\n *\n * See {@link @backstage/code-plugin-api#RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport type RootHttpRouterFactoryOptions = {\n /**\n * The path to forward all unmatched requests to. Defaults to '/api/app' if\n * not given. Disables index path behavior if false is given.\n */\n indexPath?: string | false;\n\n configure?(context: RootHttpRouterConfigureContext): void;\n};\n\nfunction defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) {\n applyDefaults();\n}\n\nconst rootHttpRouterServiceFactoryWithOptions = (\n options?: RootHttpRouterFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n rootLogger: coreServices.rootLogger,\n lifecycle: coreServices.rootLifecycle,\n health: coreServices.rootHealth,\n },\n async factory({ config, rootLogger, lifecycle, health }) {\n const { indexPath, configure = defaultConfigure } = options ?? {};\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n const app = express();\n\n const trustProxy = config.getOptional('backend.trustProxy');\n\n const router = DefaultRootHttpRouter.create({ indexPath });\n const middleware = MiddlewareFactory.create({ config, logger });\n const routes = router.handler();\n\n const healthRouter = createHealthRouter({ config, health });\n\n const server = await createHttpServer(\n app,\n readHttpServerOptions(config.getOptionalConfig('backend')),\n { logger },\n );\n\n configure({\n app,\n server,\n routes,\n middleware,\n config,\n logger,\n lifecycle,\n healthRouter,\n applyDefaults() {\n if (process.env.NODE_ENV === 'development') {\n app.set('json spaces', 2);\n }\n if (trustProxy !== undefined) {\n app.set('trust proxy', trustProxy);\n }\n app.use(middleware.helmet());\n app.use(middleware.cors());\n app.use(middleware.compression());\n app.use(middleware.logging());\n app.use(middleware.rateLimit());\n app.use(healthRouter);\n app.use(routes);\n app.use(middleware.notFound());\n app.use(middleware.error());\n },\n });\n\n if (config.has('backend.lifecycle.serverShutdownDelay')) {\n const serverShutdownDelay = readDurationFromConfig(config, {\n key: 'backend.lifecycle.serverShutdownDelay',\n });\n lifecycle.addBeforeShutdownHook(async () => {\n const timeoutMs = durationToMilliseconds(serverShutdownDelay);\n return await new Promise(resolve => {\n setTimeout(resolve, timeoutMs);\n });\n });\n }\n\n lifecycle.addShutdownHook(() => server.stop());\n\n await server.start();\n\n return router;\n },\n });\n\n/** @public */\nexport const rootHttpRouterServiceFactory = Object.assign(\n rootHttpRouterServiceFactoryWithOptions,\n rootHttpRouterServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","config","express","DefaultRootHttpRouter","MiddlewareFactory","createHealthRouter","createHttpServer","readHttpServerOptions","readDurationFromConfig","durationToMilliseconds"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rootLifecycleServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n LifecycleServiceStartupHook,\n LifecycleServiceStartupOptions,\n LifecycleServiceShutdownHook,\n LifecycleServiceShutdownOptions,\n RootLifecycleService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class BackendLifecycleImpl implements RootLifecycleService {\n constructor(private readonly logger: LoggerService) {}\n\n #hasStarted = false;\n #startupTasks: Array<{\n hook: LifecycleServiceStartupHook;\n options?: LifecycleServiceStartupOptions;\n }> = [];\n\n addStartupHook(\n hook: LifecycleServiceStartupHook,\n options?: LifecycleServiceStartupOptions,\n ): void {\n if (this.#hasStarted) {\n throw new Error('Attempted to add startup hook after startup');\n }\n this.#startupTasks.push({ hook, options });\n }\n\n async startup(): Promise<void> {\n if (this.#hasStarted) {\n return;\n }\n this.#hasStarted = true;\n\n this.logger.debug(`Running ${this.#startupTasks.length} startup tasks...`);\n await Promise.all(\n this.#startupTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Startup hook succeeded`);\n } catch (error) {\n logger.error(`Startup hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasBeforeShutdown = false;\n #beforeShutdownTasks: Array<{ hook: () => void | Promise<void> }> = [];\n\n addBeforeShutdownHook(hook: () => void): void {\n if (this.#hasBeforeShutdown) {\n throw new Error(\n 'Attempt to add before shutdown hook after shutdown has started',\n );\n }\n this.#beforeShutdownTasks.push({ hook });\n }\n\n async beforeShutdown(): Promise<void> {\n if (this.#hasBeforeShutdown) {\n return;\n }\n this.#hasBeforeShutdown = true;\n\n this.logger.debug(\n `Running ${this.#beforeShutdownTasks.length} before shutdown tasks...`,\n );\n await Promise.all(\n this.#beforeShutdownTasks.map(async ({ hook }) => {\n try {\n await hook();\n this.logger.debug(`Before shutdown hook succeeded`);\n } catch (error) {\n this.logger.error(`Before shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasShutdown = false;\n #shutdownTasks: Array<{\n hook: LifecycleServiceShutdownHook;\n options?: LifecycleServiceShutdownOptions;\n }> = [];\n\n addShutdownHook(\n hook: LifecycleServiceShutdownHook,\n options?: LifecycleServiceShutdownOptions,\n ): void {\n if (this.#hasShutdown) {\n throw new Error('Attempted to add shutdown hook after shutdown');\n }\n this.#shutdownTasks.push({ hook, options });\n }\n\n async shutdown(): Promise<void> {\n if (this.#hasShutdown) {\n return;\n }\n this.#hasShutdown = true;\n\n this.logger.debug(\n `Running ${this.#shutdownTasks.length} shutdown tasks...`,\n );\n await Promise.all(\n this.#shutdownTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Shutdown hook succeeded`);\n } catch (error) {\n logger.error(`Shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n}\n\n/**\n * Registration of backend startup and shutdown lifecycle hooks.\n *\n * See {@link @backstage/code-plugin-api#RootLifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLifecycleServiceFactory = createServiceFactory({\n service: coreServices.rootLifecycle,\n deps: {\n logger: coreServices.rootLogger,\n },\n async factory({ logger }) {\n return new BackendLifecycleImpl(logger);\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":"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"}
1
+ {"version":3,"file":"rootLifecycleServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n LifecycleServiceStartupHook,\n LifecycleServiceStartupOptions,\n LifecycleServiceShutdownHook,\n LifecycleServiceShutdownOptions,\n RootLifecycleService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class BackendLifecycleImpl implements RootLifecycleService {\n constructor(private readonly logger: LoggerService) {}\n\n #hasStarted = false;\n #startupTasks: Array<{\n hook: LifecycleServiceStartupHook;\n options?: LifecycleServiceStartupOptions;\n }> = [];\n\n addStartupHook(\n hook: LifecycleServiceStartupHook,\n options?: LifecycleServiceStartupOptions,\n ): void {\n if (this.#hasStarted) {\n throw new Error('Attempted to add startup hook after startup');\n }\n this.#startupTasks.push({ hook, options });\n }\n\n async startup(): Promise<void> {\n if (this.#hasStarted) {\n return;\n }\n this.#hasStarted = true;\n\n this.logger.debug(`Running ${this.#startupTasks.length} startup tasks...`);\n await Promise.all(\n this.#startupTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Startup hook succeeded`);\n } catch (error) {\n logger.error(`Startup hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasBeforeShutdown = false;\n #beforeShutdownTasks: Array<{ hook: () => void | Promise<void> }> = [];\n\n addBeforeShutdownHook(hook: () => void): void {\n if (this.#hasBeforeShutdown) {\n throw new Error(\n 'Attempt to add before shutdown hook after shutdown has started',\n );\n }\n this.#beforeShutdownTasks.push({ hook });\n }\n\n async beforeShutdown(): Promise<void> {\n if (this.#hasBeforeShutdown) {\n return;\n }\n this.#hasBeforeShutdown = true;\n\n this.logger.debug(\n `Running ${this.#beforeShutdownTasks.length} before shutdown tasks...`,\n );\n await Promise.all(\n this.#beforeShutdownTasks.map(async ({ hook }) => {\n try {\n await hook();\n this.logger.debug(`Before shutdown hook succeeded`);\n } catch (error) {\n this.logger.error(`Before shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasShutdown = false;\n #shutdownTasks: Array<{\n hook: LifecycleServiceShutdownHook;\n options?: LifecycleServiceShutdownOptions;\n }> = [];\n\n addShutdownHook(\n hook: LifecycleServiceShutdownHook,\n options?: LifecycleServiceShutdownOptions,\n ): void {\n if (this.#hasShutdown) {\n throw new Error('Attempted to add shutdown hook after shutdown');\n }\n this.#shutdownTasks.push({ hook, options });\n }\n\n async shutdown(): Promise<void> {\n if (this.#hasShutdown) {\n return;\n }\n this.#hasShutdown = true;\n\n this.logger.debug(\n `Running ${this.#shutdownTasks.length} shutdown tasks...`,\n );\n await Promise.all(\n this.#shutdownTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Shutdown hook succeeded`);\n } catch (error) {\n logger.error(`Shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n}\n\n/**\n * Registration of backend startup and shutdown lifecycle hooks.\n *\n * See {@link @backstage/code-plugin-api#RootLifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLifecycleServiceFactory = createServiceFactory({\n service: coreServices.rootLifecycle,\n deps: {\n logger: coreServices.rootLogger,\n },\n async factory({ logger }) {\n return new BackendLifecycleImpl(logger);\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"WinstonLogger.cjs.js","sources":["../../../src/entrypoints/rootLogger/WinstonLogger.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { Format, TransformableInfo } from 'logform';\nimport {\n Logger,\n format,\n createLogger,\n transports,\n transport as Transport,\n} from 'winston';\nimport { MESSAGE } from 'triple-beam';\nimport { escapeRegExp } from '../../lib/escapeRegExp';\n\n/**\n * @public\n */\nexport interface WinstonLoggerOptions {\n meta?: JsonObject;\n level?: string;\n format?: Format;\n transports?: Transport[];\n}\n\n/**\n * A {@link @backstage/backend-plugin-api#LoggerService} implementation based on winston.\n *\n * @public\n */\nexport class WinstonLogger implements RootLoggerService {\n #winston: Logger;\n #addRedactions?: (redactions: Iterable<string>) => void;\n\n /**\n * Creates a {@link WinstonLogger} instance.\n */\n static create(options: WinstonLoggerOptions): WinstonLogger {\n const redacter = WinstonLogger.redacter();\n const defaultFormatter =\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat();\n\n let logger = createLogger({\n level: process.env.LOG_LEVEL || options.level || 'info',\n format: format.combine(\n options.format ?? defaultFormatter,\n redacter.format,\n ),\n transports: options.transports ?? new transports.Console(),\n });\n\n if (options.meta) {\n logger = logger.child(options.meta);\n }\n\n return new WinstonLogger(logger, redacter.add);\n }\n\n /**\n * Creates a winston log formatter for redacting secrets.\n */\n static redacter(): {\n format: Format;\n add: (redactions: Iterable<string>) => void;\n } {\n const redactionSet = new Set<string>();\n\n let redactionPattern: RegExp | undefined = undefined;\n\n return {\n format: format((obj: TransformableInfo) => {\n if (!redactionPattern || !obj) {\n return obj;\n }\n\n obj[MESSAGE] = obj[MESSAGE]?.replace?.(redactionPattern, '***');\n\n return obj;\n })(),\n add(newRedactions) {\n let added = 0;\n for (const redactionToTrim of newRedactions) {\n // Skip null or undefined values\n if (redactionToTrim === null || redactionToTrim === undefined) {\n continue;\n }\n // Trimming the string ensures that we don't accdentally get extra\n // newlines or other whitespace interfering with the redaction; this\n // can happen for example when using string literals in yaml\n const redaction = redactionToTrim.trim();\n // Exclude secrets that are empty or just one character in length. These\n // typically mean that you are running local dev or tests, or using the\n // --lax flag which sets things to just 'x'.\n if (redaction.length <= 1) {\n continue;\n }\n if (!redactionSet.has(redaction)) {\n redactionSet.add(redaction);\n added += 1;\n }\n }\n if (added > 0) {\n const redactions = Array.from(redactionSet)\n .map(r => escapeRegExp(r))\n .join('|');\n redactionPattern = new RegExp(`(${redactions})`, 'g');\n }\n },\n };\n }\n\n /**\n * Creates a pretty printed winston log formatter.\n */\n static colorFormat(): Format {\n const colorizer = format.colorize();\n\n return format.combine(\n format.timestamp(),\n format.colorize({\n colors: {\n timestamp: 'dim',\n prefix: 'blue',\n field: 'cyan',\n debug: 'grey',\n },\n }),\n format.printf((info: TransformableInfo) => {\n const { timestamp, level, message, plugin, service, ...fields } = info;\n const prefix = plugin || service;\n const timestampColor = colorizer.colorize('timestamp', timestamp);\n const prefixColor = colorizer.colorize('prefix', prefix);\n\n const extraFields = Object.entries(fields)\n .map(([key, value]) => {\n let stringValue = '';\n\n try {\n stringValue = JSON.stringify(value);\n } catch (e) {\n stringValue = '[field value not castable to string]';\n }\n\n return `${colorizer.colorize('field', `${key}`)}=${stringValue}`;\n })\n .join(' ');\n\n return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;\n }),\n );\n }\n\n private constructor(\n winston: Logger,\n addRedactions?: (redactions: Iterable<string>) => void,\n ) {\n this.#winston = winston;\n this.#addRedactions = addRedactions;\n }\n\n error(message: string, meta?: JsonObject): void {\n this.#winston.error(message, meta);\n }\n\n warn(message: string, meta?: JsonObject): void {\n this.#winston.warn(message, meta);\n }\n\n info(message: string, meta?: JsonObject): void {\n this.#winston.info(message, meta);\n }\n\n debug(message: string, meta?: JsonObject): void {\n this.#winston.debug(message, meta);\n }\n\n child(meta: JsonObject): LoggerService {\n return new WinstonLogger(this.#winston.child(meta));\n }\n\n addRedactions(redactions: Iterable<string>) {\n this.#addRedactions?.(redactions);\n }\n}\n"],"names":["format","createLogger","transports","MESSAGE","escapeRegExp"],"mappings":"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"}
1
+ {"version":3,"file":"WinstonLogger.cjs.js","sources":["../../../src/entrypoints/rootLogger/WinstonLogger.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { Format, TransformableInfo } from 'logform';\nimport {\n Logger,\n format,\n createLogger,\n transports,\n transport as Transport,\n} from 'winston';\nimport { MESSAGE } from 'triple-beam';\nimport { escapeRegExp } from '../../lib/escapeRegExp';\n\n/**\n * @public\n */\nexport interface WinstonLoggerOptions {\n meta?: JsonObject;\n level?: string;\n format?: Format;\n transports?: Transport[];\n}\n\n/**\n * A {@link @backstage/backend-plugin-api#LoggerService} implementation based on winston.\n *\n * @public\n */\nexport class WinstonLogger implements RootLoggerService {\n #winston: Logger;\n #addRedactions?: (redactions: Iterable<string>) => void;\n\n /**\n * Creates a {@link WinstonLogger} instance.\n */\n static create(options: WinstonLoggerOptions): WinstonLogger {\n const redacter = WinstonLogger.redacter();\n const defaultFormatter =\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat();\n\n let logger = createLogger({\n level: process.env.LOG_LEVEL || options.level || 'info',\n format: format.combine(\n options.format ?? defaultFormatter,\n redacter.format,\n ),\n transports: options.transports ?? new transports.Console(),\n });\n\n if (options.meta) {\n logger = logger.child(options.meta);\n }\n\n return new WinstonLogger(logger, redacter.add);\n }\n\n /**\n * Creates a winston log formatter for redacting secrets.\n */\n static redacter(): {\n format: Format;\n add: (redactions: Iterable<string>) => void;\n } {\n const redactionSet = new Set<string>();\n\n let redactionPattern: RegExp | undefined = undefined;\n\n return {\n format: format((obj: TransformableInfo) => {\n if (!redactionPattern || !obj) {\n return obj;\n }\n\n obj[MESSAGE] = obj[MESSAGE]?.replace?.(redactionPattern, '***');\n\n return obj;\n })(),\n add(newRedactions) {\n let added = 0;\n for (const redactionToTrim of newRedactions) {\n // Skip null or undefined values\n if (redactionToTrim === null || redactionToTrim === undefined) {\n continue;\n }\n // Trimming the string ensures that we don't accdentally get extra\n // newlines or other whitespace interfering with the redaction; this\n // can happen for example when using string literals in yaml\n const redaction = redactionToTrim.trim();\n // Exclude secrets that are empty or just one character in length. These\n // typically mean that you are running local dev or tests, or using the\n // --lax flag which sets things to just 'x'.\n if (redaction.length <= 1) {\n continue;\n }\n if (!redactionSet.has(redaction)) {\n redactionSet.add(redaction);\n added += 1;\n }\n }\n if (added > 0) {\n const redactions = Array.from(redactionSet)\n .map(r => escapeRegExp(r))\n .join('|');\n redactionPattern = new RegExp(`(${redactions})`, 'g');\n }\n },\n };\n }\n\n /**\n * Creates a pretty printed winston log formatter.\n */\n static colorFormat(): Format {\n const colorizer = format.colorize();\n\n return format.combine(\n format.timestamp(),\n format.colorize({\n colors: {\n timestamp: 'dim',\n prefix: 'blue',\n field: 'cyan',\n debug: 'grey',\n },\n }),\n format.printf((info: TransformableInfo) => {\n const { timestamp, level, message, plugin, service, ...fields } = info;\n const prefix = plugin || service;\n const timestampColor = colorizer.colorize('timestamp', timestamp);\n const prefixColor = colorizer.colorize('prefix', prefix);\n\n const extraFields = Object.entries(fields)\n .map(([key, value]) => {\n let stringValue = '';\n\n try {\n stringValue = JSON.stringify(value);\n } catch (e) {\n stringValue = '[field value not castable to string]';\n }\n\n return `${colorizer.colorize('field', `${key}`)}=${stringValue}`;\n })\n .join(' ');\n\n return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;\n }),\n );\n }\n\n private constructor(\n winston: Logger,\n addRedactions?: (redactions: Iterable<string>) => void,\n ) {\n this.#winston = winston;\n this.#addRedactions = addRedactions;\n }\n\n error(message: string, meta?: JsonObject): void {\n this.#winston.error(message, meta);\n }\n\n warn(message: string, meta?: JsonObject): void {\n this.#winston.warn(message, meta);\n }\n\n info(message: string, meta?: JsonObject): void {\n this.#winston.info(message, meta);\n }\n\n debug(message: string, meta?: JsonObject): void {\n this.#winston.debug(message, meta);\n }\n\n child(meta: JsonObject): LoggerService {\n return new WinstonLogger(this.#winston.child(meta));\n }\n\n addRedactions(redactions: Iterable<string>) {\n this.#addRedactions?.(redactions);\n }\n}\n"],"names":["format","createLogger","transports","MESSAGE","escapeRegExp"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rootLoggerServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLogger/rootLoggerServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { transports, format } from 'winston';\nimport { WinstonLogger } from '../rootLogger/WinstonLogger';\nimport { createConfigSecretEnumerator } from '../rootConfig/createConfigSecretEnumerator';\n\n/**\n * Root-level logging.\n *\n * See {@link @backstage/backend-plugin-api#RootLoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLoggerServiceFactory = createServiceFactory({\n service: coreServices.rootLogger,\n deps: {\n config: coreServices.rootConfig,\n },\n async factory({ config }) {\n const logger = WinstonLogger.create({\n meta: {\n service: 'backstage',\n },\n level: process.env.LOG_LEVEL || 'info',\n format:\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat(),\n transports: [new transports.Console()],\n });\n\n const secretEnumerator = await createConfigSecretEnumerator({ logger });\n logger.addRedactions(secretEnumerator(config));\n config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));\n\n return logger;\n },\n});\n"],"names":["createServiceFactory","coreServices","WinstonLogger","format","transports","createConfigSecretEnumerator"],"mappings":";;;;;;;AAiCO,MAAM,2BAA2BA,qCAAqB,CAAA;AAAA,EAC3D,SAASC,6BAAa,CAAA,UAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA;AAAA,GACvB;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAU,EAAA;AACxB,IAAM,MAAA,MAAA,GAASC,4BAAc,MAAO,CAAA;AAAA,MAClC,IAAM,EAAA;AAAA,QACJ,OAAS,EAAA;AAAA,OACX;AAAA,MACA,KAAA,EAAO,OAAQ,CAAA,GAAA,CAAI,SAAa,IAAA,MAAA;AAAA,MAChC,MAAA,EACE,QAAQ,GAAI,CAAA,QAAA,KAAa,eACrBC,cAAO,CAAA,IAAA,EACP,GAAAD,2BAAA,CAAc,WAAY,EAAA;AAAA,MAChC,UAAY,EAAA,CAAC,IAAIE,kBAAA,CAAW,SAAS;AAAA,KACtC,CAAA;AAED,IAAA,MAAM,gBAAmB,GAAA,MAAMC,yDAA6B,CAAA,EAAE,QAAQ,CAAA;AACtE,IAAO,MAAA,CAAA,aAAA,CAAc,gBAAiB,CAAA,MAAM,CAAC,CAAA;AAC7C,IAAA,MAAA,CAAO,YAAY,MAAM,MAAA,CAAO,cAAc,gBAAiB,CAAA,MAAM,CAAC,CAAC,CAAA;AAEvE,IAAO,OAAA,MAAA;AAAA;AAEX,CAAC;;;;"}
1
+ {"version":3,"file":"rootLoggerServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLogger/rootLoggerServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { transports, format } from 'winston';\nimport { WinstonLogger } from '../rootLogger/WinstonLogger';\nimport { createConfigSecretEnumerator } from '../rootConfig/createConfigSecretEnumerator';\n\n/**\n * Root-level logging.\n *\n * See {@link @backstage/backend-plugin-api#RootLoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLoggerServiceFactory = createServiceFactory({\n service: coreServices.rootLogger,\n deps: {\n config: coreServices.rootConfig,\n },\n async factory({ config }) {\n const logger = WinstonLogger.create({\n meta: {\n service: 'backstage',\n },\n level: process.env.LOG_LEVEL || 'info',\n format:\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat(),\n transports: [new transports.Console()],\n });\n\n const secretEnumerator = await createConfigSecretEnumerator({ logger });\n logger.addRedactions(secretEnumerator(config));\n config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));\n\n return logger;\n },\n});\n"],"names":["createServiceFactory","coreServices","WinstonLogger","format","transports","createConfigSecretEnumerator"],"mappings":";;;;;;;AAiCO,MAAM,2BAA2BA,qCAAA,CAAqB;AAAA,EAC3D,SAASC,6BAAA,CAAa,UAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa;AAAA,GACvB;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAO,EAAG;AACxB,IAAA,MAAM,MAAA,GAASC,4BAAc,MAAA,CAAO;AAAA,MAClC,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS;AAAA,OACX;AAAA,MACA,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,SAAA,IAAa,MAAA;AAAA,MAChC,MAAA,EACE,QAAQ,GAAA,CAAI,QAAA,KAAa,eACrBC,cAAA,CAAO,IAAA,EAAK,GACZD,2BAAA,CAAc,WAAA,EAAY;AAAA,MAChC,UAAA,EAAY,CAAC,IAAIE,kBAAA,CAAW,SAAS;AAAA,KACtC,CAAA;AAED,IAAA,MAAM,gBAAA,GAAmB,MAAMC,yDAAA,CAA6B,EAAE,QAAQ,CAAA;AACtE,IAAA,MAAA,CAAO,aAAA,CAAc,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAC7C,IAAA,MAAA,CAAO,YAAY,MAAM,MAAA,CAAO,cAAc,gBAAA,CAAiB,MAAM,CAAC,CAAC,CAAA;AAEvE,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrateBackendTasks.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/migrateBackendTasks.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Knex } from 'knex';\nimport { DB_MIGRATIONS_TABLE } from './tables';\n\nexport const migrationsDir = resolvePackagePath(\n '@backstage/backend-defaults',\n 'migrations/scheduler',\n);\n\nexport async function migrateBackendTasks(knex: Knex): Promise<void> {\n await knex.migrate.latest({\n directory: migrationsDir,\n tableName: DB_MIGRATIONS_TABLE,\n });\n}\n"],"names":["resolvePackagePath","DB_MIGRATIONS_TABLE"],"mappings":";;;;;AAoBO,MAAM,aAAgB,GAAAA,mCAAA;AAAA,EAC3B,6BAAA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB,IAA2B,EAAA;AACnE,EAAM,MAAA,IAAA,CAAK,QAAQ,MAAO,CAAA;AAAA,IACxB,SAAW,EAAA,aAAA;AAAA,IACX,SAAW,EAAAC;AAAA,GACZ,CAAA;AACH;;;;;"}
1
+ {"version":3,"file":"migrateBackendTasks.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/migrateBackendTasks.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Knex } from 'knex';\nimport { DB_MIGRATIONS_TABLE } from './tables';\n\nexport const migrationsDir = resolvePackagePath(\n '@backstage/backend-defaults',\n 'migrations/scheduler',\n);\n\nexport async function migrateBackendTasks(knex: Knex): Promise<void> {\n await knex.migrate.latest({\n directory: migrationsDir,\n tableName: DB_MIGRATIONS_TABLE,\n });\n}\n"],"names":["resolvePackagePath","DB_MIGRATIONS_TABLE"],"mappings":";;;;;AAoBO,MAAM,aAAA,GAAgBA,mCAAA;AAAA,EAC3B,6BAAA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB,IAAA,EAA2B;AACnE,EAAA,MAAM,IAAA,CAAK,QAAQ,MAAA,CAAO;AAAA,IACxB,SAAA,EAAW,aAAA;AAAA,IACX,SAAA,EAAWC;AAAA,GACZ,CAAA;AACH;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"tables.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/tables.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const DB_MIGRATIONS_TABLE = 'backstage_backend_tasks__knex_migrations';\nexport const DB_TASKS_TABLE = 'backstage_backend_tasks__tasks';\n\nexport type DbTasksRow = {\n id: string;\n settings_json: string;\n next_run_start_at?: Date | string; // This can be null when in manual trigger mode\n current_run_ticket?: string;\n current_run_started_at?: Date | string;\n current_run_expires_at?: Date | string;\n last_run_error_json?: string;\n last_run_ended_at?: Date | string;\n};\n"],"names":[],"mappings":";;AAgBO,MAAM,mBAAsB,GAAA;AAC5B,MAAM,cAAiB,GAAA;;;;;"}
1
+ {"version":3,"file":"tables.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/tables.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const DB_MIGRATIONS_TABLE = 'backstage_backend_tasks__knex_migrations';\nexport const DB_TASKS_TABLE = 'backstage_backend_tasks__tasks';\n\nexport type DbTasksRow = {\n id: string;\n settings_json: string;\n next_run_start_at?: Date | string; // This can be null when in manual trigger mode\n current_run_ticket?: string;\n current_run_started_at?: Date | string;\n current_run_expires_at?: Date | string;\n last_run_error_json?: string;\n last_run_ended_at?: Date | string;\n};\n"],"names":[],"mappings":";;AAgBO,MAAM,mBAAA,GAAsB;AAC5B,MAAM,cAAA,GAAiB;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultSchedulerService.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/DefaultSchedulerService.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DatabaseService,\n HttpRouterService,\n LoggerService,\n PluginMetadataService,\n RootLifecycleService,\n SchedulerService,\n} from '@backstage/backend-plugin-api';\nimport { once } from 'lodash';\nimport { Duration } from 'luxon';\nimport { migrateBackendTasks } from '../database/migrateBackendTasks';\nimport { PluginTaskSchedulerImpl } from './PluginTaskSchedulerImpl';\nimport { PluginTaskSchedulerJanitor } from './PluginTaskSchedulerJanitor';\n\n/**\n * Default implementation of the task scheduler service.\n *\n * @public\n */\nexport class DefaultSchedulerService {\n static create(options: {\n database: DatabaseService;\n logger: LoggerService;\n rootLifecycle: RootLifecycleService;\n httpRouter: HttpRouterService;\n pluginMetadata: PluginMetadataService;\n }): SchedulerService {\n const databaseFactory = once(async () => {\n const knex = await options.database.getClient();\n\n if (!options.database.migrations?.skip) {\n await migrateBackendTasks(knex);\n }\n\n if (process.env.NODE_ENV !== 'test') {\n const abortController = new AbortController();\n const janitor = new PluginTaskSchedulerJanitor({\n knex,\n waitBetweenRuns: Duration.fromObject({ minutes: 1 }),\n logger: options.logger,\n });\n\n options.rootLifecycle.addShutdownHook(() => abortController.abort());\n janitor.start(abortController.signal);\n }\n\n return knex;\n });\n\n const scheduler = new PluginTaskSchedulerImpl(\n options.pluginMetadata.getId(),\n databaseFactory,\n options.logger,\n options.rootLifecycle,\n );\n\n options.httpRouter.use(scheduler.getRouter());\n\n return scheduler;\n }\n}\n"],"names":["once","migrateBackendTasks","PluginTaskSchedulerJanitor","Duration","PluginTaskSchedulerImpl"],"mappings":";;;;;;;;AAmCO,MAAM,uBAAwB,CAAA;AAAA,EACnC,OAAO,OAAO,OAMO,EAAA;AACnB,IAAM,MAAA,eAAA,GAAkBA,YAAK,YAAY;AACvC,MAAA,MAAM,IAAO,GAAA,MAAM,OAAQ,CAAA,QAAA,CAAS,SAAU,EAAA;AAE9C,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAS,CAAA,UAAA,EAAY,IAAM,EAAA;AACtC,QAAA,MAAMC,wCAAoB,IAAI,CAAA;AAAA;AAGhC,MAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,MAAQ,EAAA;AACnC,QAAM,MAAA,eAAA,GAAkB,IAAI,eAAgB,EAAA;AAC5C,QAAM,MAAA,OAAA,GAAU,IAAIC,qDAA2B,CAAA;AAAA,UAC7C,IAAA;AAAA,UACA,iBAAiBC,cAAS,CAAA,UAAA,CAAW,EAAE,OAAA,EAAS,GAAG,CAAA;AAAA,UACnD,QAAQ,OAAQ,CAAA;AAAA,SACjB,CAAA;AAED,QAAA,OAAA,CAAQ,aAAc,CAAA,eAAA,CAAgB,MAAM,eAAA,CAAgB,OAAO,CAAA;AACnE,QAAQ,OAAA,CAAA,KAAA,CAAM,gBAAgB,MAAM,CAAA;AAAA;AAGtC,MAAO,OAAA,IAAA;AAAA,KACR,CAAA;AAED,IAAA,MAAM,YAAY,IAAIC,+CAAA;AAAA,MACpB,OAAA,CAAQ,eAAe,KAAM,EAAA;AAAA,MAC7B,eAAA;AAAA,MACA,OAAQ,CAAA,MAAA;AAAA,MACR,OAAQ,CAAA;AAAA,KACV;AAEA,IAAA,OAAA,CAAQ,UAAW,CAAA,GAAA,CAAI,SAAU,CAAA,SAAA,EAAW,CAAA;AAE5C,IAAO,OAAA,SAAA;AAAA;AAEX;;;;"}
1
+ {"version":3,"file":"DefaultSchedulerService.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/DefaultSchedulerService.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DatabaseService,\n HttpRouterService,\n LoggerService,\n PluginMetadataService,\n RootLifecycleService,\n SchedulerService,\n} from '@backstage/backend-plugin-api';\nimport { once } from 'lodash';\nimport { Duration } from 'luxon';\nimport { migrateBackendTasks } from '../database/migrateBackendTasks';\nimport { PluginTaskSchedulerImpl } from './PluginTaskSchedulerImpl';\nimport { PluginTaskSchedulerJanitor } from './PluginTaskSchedulerJanitor';\n\n/**\n * Default implementation of the task scheduler service.\n *\n * @public\n */\nexport class DefaultSchedulerService {\n static create(options: {\n database: DatabaseService;\n logger: LoggerService;\n rootLifecycle: RootLifecycleService;\n httpRouter: HttpRouterService;\n pluginMetadata: PluginMetadataService;\n }): SchedulerService {\n const databaseFactory = once(async () => {\n const knex = await options.database.getClient();\n\n if (!options.database.migrations?.skip) {\n await migrateBackendTasks(knex);\n }\n\n if (process.env.NODE_ENV !== 'test') {\n const abortController = new AbortController();\n const janitor = new PluginTaskSchedulerJanitor({\n knex,\n waitBetweenRuns: Duration.fromObject({ minutes: 1 }),\n logger: options.logger,\n });\n\n options.rootLifecycle.addShutdownHook(() => abortController.abort());\n janitor.start(abortController.signal);\n }\n\n return knex;\n });\n\n const scheduler = new PluginTaskSchedulerImpl(\n options.pluginMetadata.getId(),\n databaseFactory,\n options.logger,\n options.rootLifecycle,\n );\n\n options.httpRouter.use(scheduler.getRouter());\n\n return scheduler;\n }\n}\n"],"names":["once","migrateBackendTasks","PluginTaskSchedulerJanitor","Duration","PluginTaskSchedulerImpl"],"mappings":";;;;;;;;AAmCO,MAAM,uBAAA,CAAwB;AAAA,EACnC,OAAO,OAAO,OAAA,EAMO;AACnB,IAAA,MAAM,eAAA,GAAkBA,YAAK,YAAY;AACvC,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,QAAA,CAAS,SAAA,EAAU;AAE9C,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,UAAA,EAAY,IAAA,EAAM;AACtC,QAAA,MAAMC,wCAAoB,IAAI,CAAA;AAAA,MAChC;AAEA,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,MAAA,EAAQ;AACnC,QAAA,MAAM,eAAA,GAAkB,IAAI,eAAA,EAAgB;AAC5C,QAAA,MAAM,OAAA,GAAU,IAAIC,qDAAA,CAA2B;AAAA,UAC7C,IAAA;AAAA,UACA,iBAAiBC,cAAA,CAAS,UAAA,CAAW,EAAE,OAAA,EAAS,GAAG,CAAA;AAAA,UACnD,QAAQ,OAAA,CAAQ;AAAA,SACjB,CAAA;AAED,QAAA,OAAA,CAAQ,aAAA,CAAc,eAAA,CAAgB,MAAM,eAAA,CAAgB,OAAO,CAAA;AACnE,QAAA,OAAA,CAAQ,KAAA,CAAM,gBAAgB,MAAM,CAAA;AAAA,MACtC;AAEA,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,MAAM,YAAY,IAAIC,+CAAA;AAAA,MACpB,OAAA,CAAQ,eAAe,KAAA,EAAM;AAAA,MAC7B,eAAA;AAAA,MACA,OAAA,CAAQ,MAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACV;AAEA,IAAA,OAAA,CAAQ,UAAA,CAAW,GAAA,CAAI,SAAA,CAAU,SAAA,EAAW,CAAA;AAE5C,IAAA,OAAO,SAAA;AAAA,EACT;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"LocalTaskWorker.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/LocalTaskWorker.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { SchedulerServiceTaskFunction } from '@backstage/backend-plugin-api';\nimport { ConflictError } from '@backstage/errors';\nimport { CronTime } from 'cron';\nimport { DateTime, Duration } from 'luxon';\nimport { TaskSettingsV2, TaskApiTasksResponse } from './types';\nimport { delegateAbortController, serializeError, sleep } from './util';\n\n/**\n * Implements tasks that run locally without cross-host collaboration.\n *\n * @private\n */\nexport class LocalTaskWorker {\n private abortWait: AbortController | undefined;\n #taskState: Exclude<TaskApiTasksResponse['taskState'], null> = {\n status: 'idle',\n };\n #workerState: TaskApiTasksResponse['workerState'] = {\n status: 'idle',\n };\n\n constructor(\n private readonly taskId: string,\n private readonly fn: SchedulerServiceTaskFunction,\n private readonly logger: LoggerService,\n ) {}\n\n start(settings: TaskSettingsV2, options: { signal: AbortSignal }) {\n this.logger.info(\n `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`,\n );\n\n (async () => {\n let attemptNum = 1;\n for (;;) {\n try {\n await this.performInitialWait(settings, options.signal);\n\n while (!options.signal.aborted) {\n const startTime = process.hrtime();\n await this.runOnce(settings, options.signal);\n const timeTaken = process.hrtime(startTime);\n await this.waitUntilNext(\n settings,\n (timeTaken[0] + timeTaken[1] / 1e9) * 1000,\n options.signal,\n );\n }\n\n this.logger.info(`Task worker finished: ${this.taskId}`);\n attemptNum = 0;\n break;\n } catch (e) {\n attemptNum += 1;\n this.logger.warn(\n `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`,\n );\n await sleep(Duration.fromObject({ seconds: 1 }));\n }\n }\n })();\n }\n\n trigger(): void {\n if (!this.abortWait) {\n throw new ConflictError(`Task ${this.taskId} is currently running`);\n }\n this.abortWait.abort();\n }\n\n taskState(): TaskApiTasksResponse['taskState'] {\n return this.#taskState;\n }\n\n workerState(): TaskApiTasksResponse['workerState'] {\n return this.#workerState;\n }\n\n /**\n * Does the once-at-startup initial wait, if configured.\n */\n private async performInitialWait(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n if (settings.initialDelayDuration) {\n const parsedDuration = Duration.fromISO(settings.initialDelayDuration);\n\n this.#taskState = {\n status: 'idle',\n startsAt: DateTime.utc().plus(parsedDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'initial-wait',\n };\n\n await this.sleep(parsedDuration, signal);\n }\n }\n\n /**\n * Makes a single attempt at running the task to completion.\n */\n private async runOnce(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n // Abort the task execution either if the worker is stopped, or if the\n // task timeout is hit\n const taskAbortController = delegateAbortController(signal);\n const timeoutDuration = Duration.fromISO(settings.timeoutAfterDuration);\n const timeoutHandle = setTimeout(() => {\n taskAbortController.abort();\n }, timeoutDuration.as('milliseconds'));\n\n this.#taskState = {\n status: 'running',\n startedAt: DateTime.utc().toISO()!,\n timesOutAt: DateTime.utc().plus(timeoutDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'running',\n };\n\n try {\n await this.fn(taskAbortController.signal);\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = undefined;\n } catch (e) {\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = serializeError(e);\n }\n\n // release resources\n clearTimeout(timeoutHandle);\n taskAbortController.abort();\n }\n\n /**\n * Sleeps until it's time to run the task again.\n */\n private async waitUntilNext(\n settings: TaskSettingsV2,\n lastRunMillis: number,\n signal: AbortSignal,\n ) {\n if (signal.aborted) {\n return;\n }\n\n const isCron = !settings.cadence.startsWith('P');\n let dt: number;\n\n if (isCron) {\n const nextRun = +new CronTime(settings.cadence).sendAt().toJSDate();\n dt = nextRun - Date.now();\n } else {\n dt =\n Duration.fromISO(settings.cadence).as('milliseconds') - lastRunMillis;\n }\n\n dt = Math.max(dt, 0);\n const startsAt = DateTime.now().plus(Duration.fromMillis(dt));\n\n this.#taskState = {\n status: 'idle',\n startsAt: startsAt.toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'idle',\n };\n\n this.logger.debug(\n `task: ${this.taskId} will next occur around ${startsAt}`,\n );\n\n await this.sleep(Duration.fromMillis(dt), signal);\n }\n\n private async sleep(\n duration: Duration,\n abortSignal: AbortSignal,\n ): Promise<void> {\n this.abortWait = delegateAbortController(abortSignal);\n await sleep(duration, this.abortWait.signal);\n this.abortWait.abort(); // cleans up resources\n this.abortWait = undefined;\n }\n}\n"],"names":["sleep","Duration","ConflictError","DateTime","delegateAbortController","serializeError","CronTime"],"mappings":"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"}
1
+ {"version":3,"file":"LocalTaskWorker.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/LocalTaskWorker.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { SchedulerServiceTaskFunction } from '@backstage/backend-plugin-api';\nimport { ConflictError } from '@backstage/errors';\nimport { CronTime } from 'cron';\nimport { DateTime, Duration } from 'luxon';\nimport { TaskSettingsV2, TaskApiTasksResponse } from './types';\nimport { delegateAbortController, serializeError, sleep } from './util';\n\n/**\n * Implements tasks that run locally without cross-host collaboration.\n *\n * @private\n */\nexport class LocalTaskWorker {\n private abortWait: AbortController | undefined;\n #taskState: Exclude<TaskApiTasksResponse['taskState'], null> = {\n status: 'idle',\n };\n #workerState: TaskApiTasksResponse['workerState'] = {\n status: 'idle',\n };\n\n constructor(\n private readonly taskId: string,\n private readonly fn: SchedulerServiceTaskFunction,\n private readonly logger: LoggerService,\n ) {}\n\n start(settings: TaskSettingsV2, options: { signal: AbortSignal }) {\n this.logger.info(\n `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`,\n );\n\n (async () => {\n let attemptNum = 1;\n for (;;) {\n try {\n await this.performInitialWait(settings, options.signal);\n\n while (!options.signal.aborted) {\n const startTime = process.hrtime();\n await this.runOnce(settings, options.signal);\n const timeTaken = process.hrtime(startTime);\n await this.waitUntilNext(\n settings,\n (timeTaken[0] + timeTaken[1] / 1e9) * 1000,\n options.signal,\n );\n }\n\n this.logger.info(`Task worker finished: ${this.taskId}`);\n attemptNum = 0;\n break;\n } catch (e) {\n attemptNum += 1;\n this.logger.warn(\n `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`,\n );\n await sleep(Duration.fromObject({ seconds: 1 }));\n }\n }\n })();\n }\n\n trigger(): void {\n if (!this.abortWait) {\n throw new ConflictError(`Task ${this.taskId} is currently running`);\n }\n this.abortWait.abort();\n }\n\n taskState(): TaskApiTasksResponse['taskState'] {\n return this.#taskState;\n }\n\n workerState(): TaskApiTasksResponse['workerState'] {\n return this.#workerState;\n }\n\n /**\n * Does the once-at-startup initial wait, if configured.\n */\n private async performInitialWait(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n if (settings.initialDelayDuration) {\n const parsedDuration = Duration.fromISO(settings.initialDelayDuration);\n\n this.#taskState = {\n status: 'idle',\n startsAt: DateTime.utc().plus(parsedDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'initial-wait',\n };\n\n await this.sleep(parsedDuration, signal);\n }\n }\n\n /**\n * Makes a single attempt at running the task to completion.\n */\n private async runOnce(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n // Abort the task execution either if the worker is stopped, or if the\n // task timeout is hit\n const taskAbortController = delegateAbortController(signal);\n const timeoutDuration = Duration.fromISO(settings.timeoutAfterDuration);\n const timeoutHandle = setTimeout(() => {\n taskAbortController.abort();\n }, timeoutDuration.as('milliseconds'));\n\n this.#taskState = {\n status: 'running',\n startedAt: DateTime.utc().toISO()!,\n timesOutAt: DateTime.utc().plus(timeoutDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'running',\n };\n\n try {\n await this.fn(taskAbortController.signal);\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = undefined;\n } catch (e) {\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = serializeError(e);\n }\n\n // release resources\n clearTimeout(timeoutHandle);\n taskAbortController.abort();\n }\n\n /**\n * Sleeps until it's time to run the task again.\n */\n private async waitUntilNext(\n settings: TaskSettingsV2,\n lastRunMillis: number,\n signal: AbortSignal,\n ) {\n if (signal.aborted) {\n return;\n }\n\n const isCron = !settings.cadence.startsWith('P');\n let dt: number;\n\n if (isCron) {\n const nextRun = +new CronTime(settings.cadence).sendAt().toJSDate();\n dt = nextRun - Date.now();\n } else {\n dt =\n Duration.fromISO(settings.cadence).as('milliseconds') - lastRunMillis;\n }\n\n dt = Math.max(dt, 0);\n const startsAt = DateTime.now().plus(Duration.fromMillis(dt));\n\n this.#taskState = {\n status: 'idle',\n startsAt: startsAt.toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'idle',\n };\n\n this.logger.debug(\n `task: ${this.taskId} will next occur around ${startsAt}`,\n );\n\n await this.sleep(Duration.fromMillis(dt), signal);\n }\n\n private async sleep(\n duration: Duration,\n abortSignal: AbortSignal,\n ): Promise<void> {\n this.abortWait = delegateAbortController(abortSignal);\n await sleep(duration, this.abortWait.signal);\n this.abortWait.abort(); // cleans up resources\n this.abortWait = undefined;\n }\n}\n"],"names":["sleep","Duration","ConflictError","DateTime","delegateAbortController","serializeError","CronTime"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PluginTaskSchedulerImpl.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootLifecycleService,\n SchedulerService,\n SchedulerServiceTaskDescriptor,\n SchedulerServiceTaskFunction,\n SchedulerServiceTaskInvocationDefinition,\n SchedulerServiceTaskRunner,\n SchedulerServiceTaskScheduleDefinition,\n} from '@backstage/backend-plugin-api';\nimport { Counter, Histogram, Gauge, metrics, trace } from '@opentelemetry/api';\nimport { Knex } from 'knex';\nimport { Duration } from 'luxon';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { LocalTaskWorker } from './LocalTaskWorker';\nimport { TaskWorker } from './TaskWorker';\nimport { TaskSettingsV2, TaskApiTasksResponse } from './types';\nimport { delegateAbortController, TRACER_ID, validateId } from './util';\n\nconst tracer = trace.getTracer(TRACER_ID);\n\n/**\n * Implements the actual task management.\n */\nexport class PluginTaskSchedulerImpl implements SchedulerService {\n private readonly localWorkersById = new Map<string, LocalTaskWorker>();\n private readonly globalWorkersById = new Map<string, TaskWorker>();\n private readonly allScheduledTasks: SchedulerServiceTaskDescriptor[] = [];\n private readonly shutdownInitiated: Promise<boolean>;\n\n private readonly counter: Counter;\n private readonly duration: Histogram;\n private readonly lastStarted: Gauge;\n private readonly lastCompleted: Gauge;\n\n constructor(\n private readonly pluginId: string,\n private readonly databaseFactory: () => Promise<Knex>,\n private readonly logger: LoggerService,\n rootLifecycle: RootLifecycleService,\n ) {\n const meter = metrics.getMeter('default');\n this.counter = meter.createCounter('backend_tasks.task.runs.count', {\n description: 'Total number of times a task has been run',\n });\n this.duration = meter.createHistogram('backend_tasks.task.runs.duration', {\n description: 'Histogram of task run durations',\n unit: 'seconds',\n });\n this.lastStarted = meter.createGauge('backend_tasks.task.runs.started', {\n description: 'Epoch timestamp seconds when the task was last started',\n unit: 'seconds',\n });\n this.lastCompleted = meter.createGauge(\n 'backend_tasks.task.runs.completed',\n {\n description: 'Epoch timestamp seconds when the task was last completed',\n unit: 'seconds',\n },\n );\n this.shutdownInitiated = new Promise(shutdownInitiated => {\n rootLifecycle.addShutdownHook(() => shutdownInitiated(true));\n });\n }\n\n async triggerTask(id: string): Promise<void> {\n const localTask = this.localWorkersById.get(id);\n if (localTask) {\n localTask.trigger();\n return;\n }\n\n const knex = await this.databaseFactory();\n await TaskWorker.trigger(knex, id);\n }\n\n async scheduleTask(\n task: SchedulerServiceTaskScheduleDefinition &\n SchedulerServiceTaskInvocationDefinition,\n ): Promise<void> {\n validateId(task.id);\n const scope = task.scope ?? 'global';\n\n const settings: TaskSettingsV2 = {\n version: 2,\n cadence: parseDuration(task.frequency),\n initialDelayDuration:\n task.initialDelay && parseDuration(task.initialDelay),\n timeoutAfterDuration: parseDuration(task.timeout),\n };\n\n // Delegated abort controller that will abort either when the provided\n // controller aborts, or when a root lifecycle shutdown happens\n const abortController = delegateAbortController(task.signal);\n this.shutdownInitiated.then(() => abortController.abort());\n\n if (scope === 'global') {\n const knex = await this.databaseFactory();\n const worker = new TaskWorker(\n task.id,\n this.instrumentedFunction(task, scope),\n knex,\n this.logger.child({ task: task.id }),\n );\n await worker.start(settings, { signal: abortController.signal });\n this.globalWorkersById.set(task.id, worker);\n } else {\n const worker = new LocalTaskWorker(\n task.id,\n this.instrumentedFunction(task, scope),\n this.logger.child({ task: task.id }),\n );\n worker.start(settings, { signal: abortController.signal });\n this.localWorkersById.set(task.id, worker);\n }\n\n this.allScheduledTasks.push({\n id: task.id,\n scope: scope,\n settings: settings,\n });\n }\n\n createScheduledTaskRunner(\n schedule: SchedulerServiceTaskScheduleDefinition,\n ): SchedulerServiceTaskRunner {\n return {\n run: async task => {\n await this.scheduleTask({ ...task, ...schedule });\n },\n };\n }\n\n async getScheduledTasks(): Promise<SchedulerServiceTaskDescriptor[]> {\n return this.allScheduledTasks;\n }\n\n getRouter(): express.Router {\n const router = Router();\n\n router.get('/.backstage/scheduler/v1/tasks', async (_, res) => {\n const globalState = await TaskWorker.taskStates(\n await this.databaseFactory(),\n );\n\n const tasks = new Array<TaskApiTasksResponse>();\n for (const task of this.allScheduledTasks) {\n tasks.push({\n taskId: task.id,\n pluginId: this.pluginId,\n scope: task.scope,\n settings: task.settings,\n taskState:\n this.localWorkersById.get(task.id)?.taskState() ??\n globalState.get(task.id) ??\n null,\n workerState:\n this.localWorkersById.get(task.id)?.workerState() ??\n this.globalWorkersById.get(task.id)?.workerState() ??\n null,\n });\n }\n\n res.json({ tasks });\n });\n\n router.post(\n '/.backstage/scheduler/v1/tasks/:id/trigger',\n async (req, res) => {\n const { id } = req.params;\n await this.triggerTask(id);\n res.status(200).end();\n },\n );\n\n return router;\n }\n\n private instrumentedFunction(\n task: SchedulerServiceTaskInvocationDefinition,\n scope: string,\n ): SchedulerServiceTaskFunction {\n return async abort => {\n const labels: Record<string, string> = {\n taskId: task.id,\n scope,\n };\n this.counter.add(1, { ...labels, result: 'started' });\n this.lastStarted.record(Date.now() / 1000, { taskId: task.id });\n\n const startTime = process.hrtime();\n\n try {\n await tracer.startActiveSpan(`task ${task.id}`, async span => {\n try {\n span.setAttributes(labels);\n await task.fn(abort);\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n }\n throw error;\n } finally {\n span.end();\n }\n });\n labels.result = 'completed';\n } catch (ex) {\n labels.result = 'failed';\n throw ex;\n } finally {\n const delta = process.hrtime(startTime);\n const endTime = delta[0] + delta[1] / 1e9;\n this.counter.add(1, labels);\n this.duration.record(endTime, labels);\n this.lastCompleted.record(Date.now() / 1000, labels);\n }\n };\n }\n}\n\nexport function parseDuration(\n frequency: SchedulerServiceTaskScheduleDefinition['frequency'],\n): string {\n if (typeof frequency === 'object' && 'cron' in frequency) {\n return frequency.cron;\n }\n if (typeof frequency === 'object' && 'trigger' in frequency) {\n return frequency.trigger;\n }\n\n const parsed = Duration.isDuration(frequency)\n ? frequency\n : Duration.fromObject(frequency);\n\n if (!parsed.isValid) {\n throw new Error(\n `Invalid duration, ${parsed.invalidReason}: ${parsed.invalidExplanation}`,\n );\n }\n\n return parsed.toISO()!;\n}\n"],"names":["trace","TRACER_ID","metrics","TaskWorker","validateId","delegateAbortController","LocalTaskWorker","Router","Duration"],"mappings":"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"}
1
+ {"version":3,"file":"PluginTaskSchedulerImpl.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootLifecycleService,\n SchedulerService,\n SchedulerServiceTaskDescriptor,\n SchedulerServiceTaskFunction,\n SchedulerServiceTaskInvocationDefinition,\n SchedulerServiceTaskRunner,\n SchedulerServiceTaskScheduleDefinition,\n} from '@backstage/backend-plugin-api';\nimport { Counter, Histogram, Gauge, metrics, trace } from '@opentelemetry/api';\nimport { Knex } from 'knex';\nimport { Duration } from 'luxon';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { LocalTaskWorker } from './LocalTaskWorker';\nimport { TaskWorker } from './TaskWorker';\nimport { TaskSettingsV2, TaskApiTasksResponse } from './types';\nimport { delegateAbortController, TRACER_ID, validateId } from './util';\n\nconst tracer = trace.getTracer(TRACER_ID);\n\n/**\n * Implements the actual task management.\n */\nexport class PluginTaskSchedulerImpl implements SchedulerService {\n private readonly localWorkersById = new Map<string, LocalTaskWorker>();\n private readonly globalWorkersById = new Map<string, TaskWorker>();\n private readonly allScheduledTasks: SchedulerServiceTaskDescriptor[] = [];\n private readonly shutdownInitiated: Promise<boolean>;\n\n private readonly counter: Counter;\n private readonly duration: Histogram;\n private readonly lastStarted: Gauge;\n private readonly lastCompleted: Gauge;\n\n constructor(\n private readonly pluginId: string,\n private readonly databaseFactory: () => Promise<Knex>,\n private readonly logger: LoggerService,\n rootLifecycle: RootLifecycleService,\n ) {\n const meter = metrics.getMeter('default');\n this.counter = meter.createCounter('backend_tasks.task.runs.count', {\n description: 'Total number of times a task has been run',\n });\n this.duration = meter.createHistogram('backend_tasks.task.runs.duration', {\n description: 'Histogram of task run durations',\n unit: 'seconds',\n });\n this.lastStarted = meter.createGauge('backend_tasks.task.runs.started', {\n description: 'Epoch timestamp seconds when the task was last started',\n unit: 'seconds',\n });\n this.lastCompleted = meter.createGauge(\n 'backend_tasks.task.runs.completed',\n {\n description: 'Epoch timestamp seconds when the task was last completed',\n unit: 'seconds',\n },\n );\n this.shutdownInitiated = new Promise(shutdownInitiated => {\n rootLifecycle.addShutdownHook(() => shutdownInitiated(true));\n });\n }\n\n async triggerTask(id: string): Promise<void> {\n const localTask = this.localWorkersById.get(id);\n if (localTask) {\n localTask.trigger();\n return;\n }\n\n const knex = await this.databaseFactory();\n await TaskWorker.trigger(knex, id);\n }\n\n async scheduleTask(\n task: SchedulerServiceTaskScheduleDefinition &\n SchedulerServiceTaskInvocationDefinition,\n ): Promise<void> {\n validateId(task.id);\n const scope = task.scope ?? 'global';\n\n const settings: TaskSettingsV2 = {\n version: 2,\n cadence: parseDuration(task.frequency),\n initialDelayDuration:\n task.initialDelay && parseDuration(task.initialDelay),\n timeoutAfterDuration: parseDuration(task.timeout),\n };\n\n // Delegated abort controller that will abort either when the provided\n // controller aborts, or when a root lifecycle shutdown happens\n const abortController = delegateAbortController(task.signal);\n this.shutdownInitiated.then(() => abortController.abort());\n\n if (scope === 'global') {\n const knex = await this.databaseFactory();\n const worker = new TaskWorker(\n task.id,\n this.instrumentedFunction(task, scope),\n knex,\n this.logger.child({ task: task.id }),\n );\n await worker.start(settings, { signal: abortController.signal });\n this.globalWorkersById.set(task.id, worker);\n } else {\n const worker = new LocalTaskWorker(\n task.id,\n this.instrumentedFunction(task, scope),\n this.logger.child({ task: task.id }),\n );\n worker.start(settings, { signal: abortController.signal });\n this.localWorkersById.set(task.id, worker);\n }\n\n this.allScheduledTasks.push({\n id: task.id,\n scope: scope,\n settings: settings,\n });\n }\n\n createScheduledTaskRunner(\n schedule: SchedulerServiceTaskScheduleDefinition,\n ): SchedulerServiceTaskRunner {\n return {\n run: async task => {\n await this.scheduleTask({ ...task, ...schedule });\n },\n };\n }\n\n async getScheduledTasks(): Promise<SchedulerServiceTaskDescriptor[]> {\n return this.allScheduledTasks;\n }\n\n getRouter(): express.Router {\n const router = Router();\n\n router.get('/.backstage/scheduler/v1/tasks', async (_, res) => {\n const globalState = await TaskWorker.taskStates(\n await this.databaseFactory(),\n );\n\n const tasks = new Array<TaskApiTasksResponse>();\n for (const task of this.allScheduledTasks) {\n tasks.push({\n taskId: task.id,\n pluginId: this.pluginId,\n scope: task.scope,\n settings: task.settings,\n taskState:\n this.localWorkersById.get(task.id)?.taskState() ??\n globalState.get(task.id) ??\n null,\n workerState:\n this.localWorkersById.get(task.id)?.workerState() ??\n this.globalWorkersById.get(task.id)?.workerState() ??\n null,\n });\n }\n\n res.json({ tasks });\n });\n\n router.post(\n '/.backstage/scheduler/v1/tasks/:id/trigger',\n async (req, res) => {\n const { id } = req.params;\n await this.triggerTask(id);\n res.status(200).end();\n },\n );\n\n return router;\n }\n\n private instrumentedFunction(\n task: SchedulerServiceTaskInvocationDefinition,\n scope: string,\n ): SchedulerServiceTaskFunction {\n return async abort => {\n const labels: Record<string, string> = {\n taskId: task.id,\n scope,\n };\n this.counter.add(1, { ...labels, result: 'started' });\n this.lastStarted.record(Date.now() / 1000, { taskId: task.id });\n\n const startTime = process.hrtime();\n\n try {\n await tracer.startActiveSpan(`task ${task.id}`, async span => {\n try {\n span.setAttributes(labels);\n await task.fn(abort);\n } catch (error) {\n if (error instanceof Error) {\n span.recordException(error);\n }\n throw error;\n } finally {\n span.end();\n }\n });\n labels.result = 'completed';\n } catch (ex) {\n labels.result = 'failed';\n throw ex;\n } finally {\n const delta = process.hrtime(startTime);\n const endTime = delta[0] + delta[1] / 1e9;\n this.counter.add(1, labels);\n this.duration.record(endTime, labels);\n this.lastCompleted.record(Date.now() / 1000, labels);\n }\n };\n }\n}\n\nexport function parseDuration(\n frequency: SchedulerServiceTaskScheduleDefinition['frequency'],\n): string {\n if (typeof frequency === 'object' && 'cron' in frequency) {\n return frequency.cron;\n }\n if (typeof frequency === 'object' && 'trigger' in frequency) {\n return frequency.trigger;\n }\n\n const parsed = Duration.isDuration(frequency)\n ? frequency\n : Duration.fromObject(frequency);\n\n if (!parsed.isValid) {\n throw new Error(\n `Invalid duration, ${parsed.invalidReason}: ${parsed.invalidExplanation}`,\n );\n }\n\n return parsed.toISO()!;\n}\n"],"names":["trace","TRACER_ID","metrics","TaskWorker","validateId","delegateAbortController","LocalTaskWorker","Router","Duration"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PluginTaskSchedulerJanitor.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { Knex } from 'knex';\nimport { Duration } from 'luxon';\nimport { DB_TASKS_TABLE, DbTasksRow } from '../database/tables';\nimport { serializeError, sleep } from './util';\n\n/**\n * Makes sure to auto-expire and clean up things that time out or for other\n * reasons should not be left lingering.\n */\nexport class PluginTaskSchedulerJanitor {\n private readonly knex: Knex;\n private readonly waitBetweenRuns: Duration;\n private readonly logger: LoggerService;\n\n constructor(options: {\n knex: Knex;\n waitBetweenRuns: Duration;\n logger: LoggerService;\n }) {\n this.knex = options.knex;\n this.waitBetweenRuns = options.waitBetweenRuns;\n this.logger = options.logger;\n }\n\n async start(abortSignal?: AbortSignal) {\n while (!abortSignal?.aborted) {\n try {\n await this.runOnce();\n } catch (e) {\n this.logger.warn(`Error while performing janitorial tasks, ${e}`);\n }\n\n await sleep(this.waitBetweenRuns, abortSignal);\n }\n }\n\n private async runOnce() {\n const dbNull = this.knex.raw('null');\n const configClient = this.knex.client.config.client;\n\n let tasks: Array<{ id: string }>;\n if (configClient.includes('sqlite3') || configClient.includes('mysql')) {\n tasks = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .select('id')\n .where('current_run_expires_at', '<', this.knex.fn.now());\n await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .whereIn(\n 'id',\n tasks.map(t => t.id),\n )\n .update({\n current_run_ticket: dbNull,\n current_run_started_at: dbNull,\n current_run_expires_at: dbNull,\n last_run_ended_at: this.knex.fn.now(),\n last_run_error_json: serializeError(new Error('Task timed out')),\n });\n } else {\n tasks = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('current_run_expires_at', '<', this.knex.fn.now())\n .update({\n current_run_ticket: dbNull,\n current_run_started_at: dbNull,\n current_run_expires_at: dbNull,\n last_run_ended_at: this.knex.fn.now(),\n last_run_error_json: serializeError(new Error('Task timed out')),\n })\n .returning(['id']);\n }\n\n // In rare cases, knex drivers may ignore \"returning\", and return the number\n // of rows changed instead\n if (typeof tasks === 'number') {\n if (tasks > 0) {\n this.logger.warn(`${tasks} tasks timed out and were lost`);\n }\n } else {\n for (const { id } of tasks) {\n this.logger.warn(`Task timed out and was lost: ${id}`);\n }\n }\n }\n}\n"],"names":["sleep","DB_TASKS_TABLE","serializeError"],"mappings":"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"}
1
+ {"version":3,"file":"PluginTaskSchedulerJanitor.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { Knex } from 'knex';\nimport { Duration } from 'luxon';\nimport { DB_TASKS_TABLE, DbTasksRow } from '../database/tables';\nimport { serializeError, sleep } from './util';\n\n/**\n * Makes sure to auto-expire and clean up things that time out or for other\n * reasons should not be left lingering.\n */\nexport class PluginTaskSchedulerJanitor {\n private readonly knex: Knex;\n private readonly waitBetweenRuns: Duration;\n private readonly logger: LoggerService;\n\n constructor(options: {\n knex: Knex;\n waitBetweenRuns: Duration;\n logger: LoggerService;\n }) {\n this.knex = options.knex;\n this.waitBetweenRuns = options.waitBetweenRuns;\n this.logger = options.logger;\n }\n\n async start(abortSignal?: AbortSignal) {\n while (!abortSignal?.aborted) {\n try {\n await this.runOnce();\n } catch (e) {\n this.logger.warn(`Error while performing janitorial tasks, ${e}`);\n }\n\n await sleep(this.waitBetweenRuns, abortSignal);\n }\n }\n\n private async runOnce() {\n const dbNull = this.knex.raw('null');\n const configClient = this.knex.client.config.client;\n\n let tasks: Array<{ id: string }>;\n if (configClient.includes('sqlite3') || configClient.includes('mysql')) {\n tasks = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .select('id')\n .where('current_run_expires_at', '<', this.knex.fn.now());\n await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .whereIn(\n 'id',\n tasks.map(t => t.id),\n )\n .update({\n current_run_ticket: dbNull,\n current_run_started_at: dbNull,\n current_run_expires_at: dbNull,\n last_run_ended_at: this.knex.fn.now(),\n last_run_error_json: serializeError(new Error('Task timed out')),\n });\n } else {\n tasks = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('current_run_expires_at', '<', this.knex.fn.now())\n .update({\n current_run_ticket: dbNull,\n current_run_started_at: dbNull,\n current_run_expires_at: dbNull,\n last_run_ended_at: this.knex.fn.now(),\n last_run_error_json: serializeError(new Error('Task timed out')),\n })\n .returning(['id']);\n }\n\n // In rare cases, knex drivers may ignore \"returning\", and return the number\n // of rows changed instead\n if (typeof tasks === 'number') {\n if (tasks > 0) {\n this.logger.warn(`${tasks} tasks timed out and were lost`);\n }\n } else {\n for (const { id } of tasks) {\n this.logger.warn(`Task timed out and was lost: ${id}`);\n }\n }\n }\n}\n"],"names":["sleep","DB_TASKS_TABLE","serializeError"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TaskWorker.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/TaskWorker.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { ConflictError, NotFoundError } from '@backstage/errors';\nimport { CronTime } from 'cron';\nimport { Knex } from 'knex';\nimport { DateTime, Duration } from 'luxon';\nimport { v4 as uuid } from 'uuid';\nimport { DB_TASKS_TABLE, DbTasksRow } from '../database/tables';\nimport {\n TaskSettingsV2,\n taskSettingsV2Schema,\n TaskApiTasksResponse,\n} from './types';\nimport {\n delegateAbortController,\n nowPlus,\n sleep,\n dbTime,\n serializeError,\n} from './util';\nimport { SchedulerServiceTaskFunction } from '@backstage/backend-plugin-api';\n\nconst DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 });\n\n/**\n * Implements tasks that run across worker hosts, with collaborative locking.\n *\n * @private\n */\nexport class TaskWorker {\n #workerState: TaskApiTasksResponse['workerState'] = {\n status: 'idle',\n };\n\n constructor(\n private readonly taskId: string,\n private readonly fn: SchedulerServiceTaskFunction,\n private readonly knex: Knex,\n private readonly logger: LoggerService,\n private readonly workCheckFrequency: Duration = DEFAULT_WORK_CHECK_FREQUENCY,\n ) {}\n\n async start(settings: TaskSettingsV2, options: { signal: AbortSignal }) {\n try {\n await this.persistTask(settings);\n } catch (e) {\n throw new Error(`Failed to persist task, ${e}`);\n }\n\n this.logger.info(\n `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`,\n );\n\n let workCheckFrequency = this.workCheckFrequency;\n const isDuration = settings?.cadence.startsWith('P');\n if (isDuration) {\n const cadence = Duration.fromISO(settings.cadence);\n if (cadence < workCheckFrequency) {\n workCheckFrequency = cadence;\n }\n }\n\n (async () => {\n let attemptNum = 1;\n for (;;) {\n try {\n await this.performInitialWait(settings, options.signal);\n\n while (!options.signal.aborted) {\n const runResult = await this.runOnce(options.signal);\n if (runResult.result === 'abort') {\n break;\n }\n await sleep(workCheckFrequency, options.signal);\n }\n\n this.logger.info(`Task worker finished: ${this.taskId}`);\n attemptNum = 0;\n break;\n } catch (e) {\n attemptNum += 1;\n this.logger.warn(\n `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`,\n );\n await sleep(Duration.fromObject({ seconds: 1 }));\n }\n }\n })();\n }\n\n /**\n * Does the once-at-startup initial wait, if configured.\n */\n private async performInitialWait(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n if (settings.initialDelayDuration) {\n this.#workerState = {\n status: 'initial-wait',\n };\n await sleep(Duration.fromISO(settings.initialDelayDuration), signal);\n }\n this.#workerState = {\n status: 'idle',\n };\n }\n\n static async trigger(knex: Knex, taskId: string): Promise<void> {\n // check if task exists\n const rows = await knex<DbTasksRow>(DB_TASKS_TABLE)\n .select(knex.raw(1))\n .where('id', '=', taskId);\n if (rows.length !== 1) {\n throw new NotFoundError(`Task ${taskId} does not exist`);\n }\n\n const updatedRows = await knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', taskId)\n .whereNull('current_run_ticket')\n .update({\n next_run_start_at: knex.fn.now(),\n });\n if (updatedRows < 1) {\n throw new ConflictError(`Task ${taskId} is currently running`);\n }\n }\n\n static async taskStates(\n knex: Knex,\n ): Promise<Map<string, TaskApiTasksResponse['taskState']>> {\n const rows = await knex<DbTasksRow>(DB_TASKS_TABLE);\n return new Map(\n rows.map(row => {\n const startedAt = row.current_run_started_at\n ? dbTime(row.current_run_started_at).toISO()!\n : undefined;\n const timesOutAt = row.current_run_expires_at\n ? dbTime(row.current_run_expires_at).toISO()!\n : undefined;\n const startsAt = row.next_run_start_at\n ? dbTime(row.next_run_start_at).toISO()!\n : undefined;\n const lastRunEndedAt = row.last_run_ended_at\n ? dbTime(row.last_run_ended_at).toISO()!\n : undefined;\n const lastRunError = row.last_run_error_json || undefined;\n\n return [\n row.id,\n startedAt\n ? {\n status: 'running',\n startedAt,\n timesOutAt,\n lastRunEndedAt,\n lastRunError,\n }\n : {\n status: 'idle',\n startsAt,\n lastRunEndedAt,\n lastRunError,\n },\n ];\n }),\n );\n }\n\n workerState(): TaskApiTasksResponse['workerState'] {\n return this.#workerState;\n }\n\n /**\n * Makes a single attempt at running the task to completion, if ready.\n *\n * @returns The outcome of the attempt\n */\n private async runOnce(\n signal: AbortSignal,\n ): Promise<\n | { result: 'not-ready-yet' }\n | { result: 'abort' }\n | { result: 'failed' }\n | { result: 'completed' }\n > {\n const findResult = await this.findReadyTask();\n if (\n findResult.result === 'not-ready-yet' ||\n findResult.result === 'abort'\n ) {\n return findResult;\n }\n\n const taskSettings = findResult.settings;\n const ticket = uuid();\n\n const claimed = await this.tryClaimTask(ticket, taskSettings);\n if (!claimed) {\n return { result: 'not-ready-yet' };\n }\n\n // Abort the task execution either if the worker is stopped, or if the\n // task timeout is hit\n const taskAbortController = delegateAbortController(signal);\n const timeoutHandle = setTimeout(() => {\n taskAbortController.abort();\n }, Duration.fromISO(taskSettings.timeoutAfterDuration).as('milliseconds'));\n\n try {\n this.#workerState = {\n status: 'running',\n };\n await this.fn(taskAbortController.signal);\n taskAbortController.abort(); // releases resources\n } catch (e) {\n this.logger.error(e);\n await this.tryReleaseTask(ticket, taskSettings, e);\n return { result: 'failed' };\n } finally {\n this.#workerState = {\n status: 'idle',\n };\n clearTimeout(timeoutHandle);\n }\n\n await this.tryReleaseTask(ticket, taskSettings);\n return { result: 'completed' };\n }\n\n /**\n * Perform the initial store of the task info\n */\n async persistTask(settings: TaskSettingsV2) {\n // Perform an initial parse to ensure that we will definitely be able to\n // read it back again.\n taskSettingsV2Schema.parse(settings);\n\n const isManual = settings?.cadence === 'manual';\n const isDuration = settings?.cadence.startsWith('P');\n const isCron = !isManual && !isDuration;\n\n let startAt: Knex.Raw | undefined;\n let nextStartAt: Knex.Raw | undefined;\n if (settings.initialDelayDuration) {\n startAt = nowPlus(\n Duration.fromISO(settings.initialDelayDuration),\n this.knex,\n );\n }\n\n if (isCron) {\n const time = new CronTime(settings.cadence)\n .sendAt()\n .minus({ seconds: 1 }) // immediately, if \"* * * * * *\"\n .toUTC();\n\n nextStartAt = this.nextRunAtRaw(time);\n startAt ||= nextStartAt;\n } else if (isManual) {\n nextStartAt = this.knex.raw('null');\n startAt ||= nextStartAt;\n } else {\n startAt ||= this.knex.fn.now();\n nextStartAt = nowPlus(Duration.fromISO(settings.cadence), this.knex);\n }\n\n this.logger.debug(`task: ${this.taskId} configured to run at: ${startAt}`);\n\n // It's OK if the task already exists; if it does, just replace its\n // settings with the new value and start the loop as usual.\n const settingsJson = JSON.stringify(settings);\n await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .insert({\n id: this.taskId,\n settings_json: settingsJson,\n next_run_start_at: startAt,\n })\n .onConflict('id')\n .merge(\n this.knex.client.config.client.includes('mysql')\n ? {\n settings_json: settingsJson,\n next_run_start_at: this.knex.raw(\n `CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,\n [\n nextStartAt,\n 'next_run_start_at',\n nextStartAt,\n 'next_run_start_at',\n ],\n ),\n }\n : {\n settings_json: this.knex.ref('excluded.settings_json'),\n next_run_start_at: this.knex.raw(\n `CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,\n [\n nextStartAt,\n `${DB_TASKS_TABLE}.next_run_start_at`,\n nextStartAt,\n `${DB_TASKS_TABLE}.next_run_start_at`,\n ],\n ),\n },\n );\n }\n\n /**\n * Check if the task is ready to run\n */\n async findReadyTask(): Promise<\n | { result: 'not-ready-yet' }\n | { result: 'abort' }\n | { result: 'ready'; settings: TaskSettingsV2 }\n > {\n const [row] = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', this.taskId)\n .select({\n settingsJson: 'settings_json',\n ready: this.knex.raw(\n `CASE\n WHEN next_run_start_at <= ? AND current_run_ticket IS NULL THEN TRUE\n ELSE FALSE\n END`,\n [this.knex.fn.now()],\n ),\n });\n\n if (!row) {\n this.logger.info(\n 'No longer able to find task; aborting and assuming that it has been unregistered or expired',\n );\n return { result: 'abort' };\n } else if (!row.ready) {\n return { result: 'not-ready-yet' };\n }\n\n try {\n const obj = JSON.parse(row.settingsJson);\n const settings = taskSettingsV2Schema.parse(obj);\n return { result: 'ready', settings };\n } catch (e) {\n this.logger.info(\n `Task \"${this.taskId}\" is no longer able to parse task settings; aborting and assuming that a ` +\n `newer version of the task has been issued and being handled by other workers, ${e}`,\n );\n return { result: 'abort' };\n }\n }\n\n /**\n * Attempts to claim a task that's ready for execution, on this worker's\n * behalf. We should not attempt to perform the work unless the claim really\n * goes through.\n *\n * @param ticket - A globally unique string that changes for each invocation\n * @param settings - The settings of the task to claim\n * @returns True if it was successfully claimed\n */\n async tryClaimTask(\n ticket: string,\n settings: TaskSettingsV2,\n ): Promise<boolean> {\n const startedAt = this.knex.fn.now();\n const expiresAt = settings.timeoutAfterDuration\n ? nowPlus(Duration.fromISO(settings.timeoutAfterDuration), this.knex)\n : this.knex.raw('null');\n\n const rows = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', this.taskId)\n .whereNull('current_run_ticket')\n .update({\n current_run_ticket: ticket,\n current_run_started_at: startedAt,\n current_run_expires_at: expiresAt,\n });\n\n return rows === 1;\n }\n\n async tryReleaseTask(\n ticket: string,\n settings: TaskSettingsV2,\n error?: Error,\n ): Promise<boolean> {\n const isManual = settings?.cadence === 'manual';\n const isDuration = settings?.cadence.startsWith('P');\n const isCron = !isManual && !isDuration;\n\n let nextRun: Knex.Raw;\n if (isCron) {\n const time = new CronTime(settings.cadence).sendAt().toUTC();\n this.logger.debug(`task: ${this.taskId} will next occur around ${time}`);\n\n nextRun = this.nextRunAtRaw(time);\n } else if (isManual) {\n nextRun = this.knex.raw('null');\n } else {\n const dt = Duration.fromISO(settings.cadence).as('seconds');\n this.logger.debug(\n `task: ${this.taskId} will next occur around ${DateTime.now().plus({\n seconds: dt,\n })}`,\n );\n\n if (this.knex.client.config.client.includes('sqlite3')) {\n nextRun = this.knex.raw(\n `max(datetime(next_run_start_at, ?), datetime('now'))`,\n [`+${dt} seconds`],\n );\n } else if (this.knex.client.config.client.includes('mysql')) {\n nextRun = this.knex.raw(\n `greatest(next_run_start_at + interval ${dt} second, now())`,\n );\n } else {\n nextRun = this.knex.raw(\n `greatest(next_run_start_at + interval '${dt} seconds', now())`,\n );\n }\n }\n\n const rows = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', this.taskId)\n .where('current_run_ticket', '=', ticket)\n .update({\n next_run_start_at: nextRun,\n current_run_ticket: this.knex.raw('null'),\n current_run_started_at: this.knex.raw('null'),\n current_run_expires_at: this.knex.raw('null'),\n last_run_ended_at: this.knex.fn.now(),\n last_run_error_json: error\n ? serializeError(error)\n : this.knex.raw('null'),\n });\n\n return rows === 1;\n }\n\n private nextRunAtRaw(time: DateTime): Knex.Raw {\n if (this.knex.client.config.client.includes('sqlite3')) {\n return this.knex.raw('datetime(?)', [time.toISO()]);\n } else if (this.knex.client.config.client.includes('mysql')) {\n return this.knex.raw(`?`, [time.toSQL({ includeOffset: false })]);\n }\n return this.knex.raw(`?`, [time.toISO()]);\n }\n}\n"],"names":["Duration","sleep","DB_TASKS_TABLE","NotFoundError","ConflictError","dbTime","uuid","delegateAbortController","taskSettingsV2Schema","nowPlus","CronTime","DateTime","serializeError"],"mappings":"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"}
1
+ {"version":3,"file":"TaskWorker.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/TaskWorker.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { ConflictError, NotFoundError } from '@backstage/errors';\nimport { CronTime } from 'cron';\nimport { Knex } from 'knex';\nimport { DateTime, Duration } from 'luxon';\nimport { v4 as uuid } from 'uuid';\nimport { DB_TASKS_TABLE, DbTasksRow } from '../database/tables';\nimport {\n TaskSettingsV2,\n taskSettingsV2Schema,\n TaskApiTasksResponse,\n} from './types';\nimport {\n delegateAbortController,\n nowPlus,\n sleep,\n dbTime,\n serializeError,\n} from './util';\nimport { SchedulerServiceTaskFunction } from '@backstage/backend-plugin-api';\n\nconst DEFAULT_WORK_CHECK_FREQUENCY = Duration.fromObject({ seconds: 5 });\n\n/**\n * Implements tasks that run across worker hosts, with collaborative locking.\n *\n * @private\n */\nexport class TaskWorker {\n #workerState: TaskApiTasksResponse['workerState'] = {\n status: 'idle',\n };\n\n constructor(\n private readonly taskId: string,\n private readonly fn: SchedulerServiceTaskFunction,\n private readonly knex: Knex,\n private readonly logger: LoggerService,\n private readonly workCheckFrequency: Duration = DEFAULT_WORK_CHECK_FREQUENCY,\n ) {}\n\n async start(settings: TaskSettingsV2, options: { signal: AbortSignal }) {\n try {\n await this.persistTask(settings);\n } catch (e) {\n throw new Error(`Failed to persist task, ${e}`);\n }\n\n this.logger.info(\n `Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`,\n );\n\n let workCheckFrequency = this.workCheckFrequency;\n const isDuration = settings?.cadence.startsWith('P');\n if (isDuration) {\n const cadence = Duration.fromISO(settings.cadence);\n if (cadence < workCheckFrequency) {\n workCheckFrequency = cadence;\n }\n }\n\n (async () => {\n let attemptNum = 1;\n for (;;) {\n try {\n await this.performInitialWait(settings, options.signal);\n\n while (!options.signal.aborted) {\n const runResult = await this.runOnce(options.signal);\n if (runResult.result === 'abort') {\n break;\n }\n await sleep(workCheckFrequency, options.signal);\n }\n\n this.logger.info(`Task worker finished: ${this.taskId}`);\n attemptNum = 0;\n break;\n } catch (e) {\n attemptNum += 1;\n this.logger.warn(\n `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`,\n );\n await sleep(Duration.fromObject({ seconds: 1 }));\n }\n }\n })();\n }\n\n /**\n * Does the once-at-startup initial wait, if configured.\n */\n private async performInitialWait(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n if (settings.initialDelayDuration) {\n this.#workerState = {\n status: 'initial-wait',\n };\n await sleep(Duration.fromISO(settings.initialDelayDuration), signal);\n }\n this.#workerState = {\n status: 'idle',\n };\n }\n\n static async trigger(knex: Knex, taskId: string): Promise<void> {\n // check if task exists\n const rows = await knex<DbTasksRow>(DB_TASKS_TABLE)\n .select(knex.raw(1))\n .where('id', '=', taskId);\n if (rows.length !== 1) {\n throw new NotFoundError(`Task ${taskId} does not exist`);\n }\n\n const updatedRows = await knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', taskId)\n .whereNull('current_run_ticket')\n .update({\n next_run_start_at: knex.fn.now(),\n });\n if (updatedRows < 1) {\n throw new ConflictError(`Task ${taskId} is currently running`);\n }\n }\n\n static async taskStates(\n knex: Knex,\n ): Promise<Map<string, TaskApiTasksResponse['taskState']>> {\n const rows = await knex<DbTasksRow>(DB_TASKS_TABLE);\n return new Map(\n rows.map(row => {\n const startedAt = row.current_run_started_at\n ? dbTime(row.current_run_started_at).toISO()!\n : undefined;\n const timesOutAt = row.current_run_expires_at\n ? dbTime(row.current_run_expires_at).toISO()!\n : undefined;\n const startsAt = row.next_run_start_at\n ? dbTime(row.next_run_start_at).toISO()!\n : undefined;\n const lastRunEndedAt = row.last_run_ended_at\n ? dbTime(row.last_run_ended_at).toISO()!\n : undefined;\n const lastRunError = row.last_run_error_json || undefined;\n\n return [\n row.id,\n startedAt\n ? {\n status: 'running',\n startedAt,\n timesOutAt,\n lastRunEndedAt,\n lastRunError,\n }\n : {\n status: 'idle',\n startsAt,\n lastRunEndedAt,\n lastRunError,\n },\n ];\n }),\n );\n }\n\n workerState(): TaskApiTasksResponse['workerState'] {\n return this.#workerState;\n }\n\n /**\n * Makes a single attempt at running the task to completion, if ready.\n *\n * @returns The outcome of the attempt\n */\n private async runOnce(\n signal: AbortSignal,\n ): Promise<\n | { result: 'not-ready-yet' }\n | { result: 'abort' }\n | { result: 'failed' }\n | { result: 'completed' }\n > {\n const findResult = await this.findReadyTask();\n if (\n findResult.result === 'not-ready-yet' ||\n findResult.result === 'abort'\n ) {\n return findResult;\n }\n\n const taskSettings = findResult.settings;\n const ticket = uuid();\n\n const claimed = await this.tryClaimTask(ticket, taskSettings);\n if (!claimed) {\n return { result: 'not-ready-yet' };\n }\n\n // Abort the task execution either if the worker is stopped, or if the\n // task timeout is hit\n const taskAbortController = delegateAbortController(signal);\n const timeoutHandle = setTimeout(() => {\n taskAbortController.abort();\n }, Duration.fromISO(taskSettings.timeoutAfterDuration).as('milliseconds'));\n\n try {\n this.#workerState = {\n status: 'running',\n };\n await this.fn(taskAbortController.signal);\n taskAbortController.abort(); // releases resources\n } catch (e) {\n this.logger.error(e);\n await this.tryReleaseTask(ticket, taskSettings, e);\n return { result: 'failed' };\n } finally {\n this.#workerState = {\n status: 'idle',\n };\n clearTimeout(timeoutHandle);\n }\n\n await this.tryReleaseTask(ticket, taskSettings);\n return { result: 'completed' };\n }\n\n /**\n * Perform the initial store of the task info\n */\n async persistTask(settings: TaskSettingsV2) {\n // Perform an initial parse to ensure that we will definitely be able to\n // read it back again.\n taskSettingsV2Schema.parse(settings);\n\n const isManual = settings?.cadence === 'manual';\n const isDuration = settings?.cadence.startsWith('P');\n const isCron = !isManual && !isDuration;\n\n let startAt: Knex.Raw | undefined;\n let nextStartAt: Knex.Raw | undefined;\n if (settings.initialDelayDuration) {\n startAt = nowPlus(\n Duration.fromISO(settings.initialDelayDuration),\n this.knex,\n );\n }\n\n if (isCron) {\n const time = new CronTime(settings.cadence)\n .sendAt()\n .minus({ seconds: 1 }) // immediately, if \"* * * * * *\"\n .toUTC();\n\n nextStartAt = this.nextRunAtRaw(time);\n startAt ||= nextStartAt;\n } else if (isManual) {\n nextStartAt = this.knex.raw('null');\n startAt ||= nextStartAt;\n } else {\n startAt ||= this.knex.fn.now();\n nextStartAt = nowPlus(Duration.fromISO(settings.cadence), this.knex);\n }\n\n this.logger.debug(`task: ${this.taskId} configured to run at: ${startAt}`);\n\n // It's OK if the task already exists; if it does, just replace its\n // settings with the new value and start the loop as usual.\n const settingsJson = JSON.stringify(settings);\n await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .insert({\n id: this.taskId,\n settings_json: settingsJson,\n next_run_start_at: startAt,\n })\n .onConflict('id')\n .merge(\n this.knex.client.config.client.includes('mysql')\n ? {\n settings_json: settingsJson,\n next_run_start_at: this.knex.raw(\n `CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,\n [\n nextStartAt,\n 'next_run_start_at',\n nextStartAt,\n 'next_run_start_at',\n ],\n ),\n }\n : {\n settings_json: this.knex.ref('excluded.settings_json'),\n next_run_start_at: this.knex.raw(\n `CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,\n [\n nextStartAt,\n `${DB_TASKS_TABLE}.next_run_start_at`,\n nextStartAt,\n `${DB_TASKS_TABLE}.next_run_start_at`,\n ],\n ),\n },\n );\n }\n\n /**\n * Check if the task is ready to run\n */\n async findReadyTask(): Promise<\n | { result: 'not-ready-yet' }\n | { result: 'abort' }\n | { result: 'ready'; settings: TaskSettingsV2 }\n > {\n const [row] = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', this.taskId)\n .select({\n settingsJson: 'settings_json',\n ready: this.knex.raw(\n `CASE\n WHEN next_run_start_at <= ? AND current_run_ticket IS NULL THEN TRUE\n ELSE FALSE\n END`,\n [this.knex.fn.now()],\n ),\n });\n\n if (!row) {\n this.logger.info(\n 'No longer able to find task; aborting and assuming that it has been unregistered or expired',\n );\n return { result: 'abort' };\n } else if (!row.ready) {\n return { result: 'not-ready-yet' };\n }\n\n try {\n const obj = JSON.parse(row.settingsJson);\n const settings = taskSettingsV2Schema.parse(obj);\n return { result: 'ready', settings };\n } catch (e) {\n this.logger.info(\n `Task \"${this.taskId}\" is no longer able to parse task settings; aborting and assuming that a ` +\n `newer version of the task has been issued and being handled by other workers, ${e}`,\n );\n return { result: 'abort' };\n }\n }\n\n /**\n * Attempts to claim a task that's ready for execution, on this worker's\n * behalf. We should not attempt to perform the work unless the claim really\n * goes through.\n *\n * @param ticket - A globally unique string that changes for each invocation\n * @param settings - The settings of the task to claim\n * @returns True if it was successfully claimed\n */\n async tryClaimTask(\n ticket: string,\n settings: TaskSettingsV2,\n ): Promise<boolean> {\n const startedAt = this.knex.fn.now();\n const expiresAt = settings.timeoutAfterDuration\n ? nowPlus(Duration.fromISO(settings.timeoutAfterDuration), this.knex)\n : this.knex.raw('null');\n\n const rows = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', this.taskId)\n .whereNull('current_run_ticket')\n .update({\n current_run_ticket: ticket,\n current_run_started_at: startedAt,\n current_run_expires_at: expiresAt,\n });\n\n return rows === 1;\n }\n\n async tryReleaseTask(\n ticket: string,\n settings: TaskSettingsV2,\n error?: Error,\n ): Promise<boolean> {\n const isManual = settings?.cadence === 'manual';\n const isDuration = settings?.cadence.startsWith('P');\n const isCron = !isManual && !isDuration;\n\n let nextRun: Knex.Raw;\n if (isCron) {\n const time = new CronTime(settings.cadence).sendAt().toUTC();\n this.logger.debug(`task: ${this.taskId} will next occur around ${time}`);\n\n nextRun = this.nextRunAtRaw(time);\n } else if (isManual) {\n nextRun = this.knex.raw('null');\n } else {\n const dt = Duration.fromISO(settings.cadence).as('seconds');\n this.logger.debug(\n `task: ${this.taskId} will next occur around ${DateTime.now().plus({\n seconds: dt,\n })}`,\n );\n\n if (this.knex.client.config.client.includes('sqlite3')) {\n nextRun = this.knex.raw(\n `max(datetime(next_run_start_at, ?), datetime('now'))`,\n [`+${dt} seconds`],\n );\n } else if (this.knex.client.config.client.includes('mysql')) {\n nextRun = this.knex.raw(\n `greatest(next_run_start_at + interval ${dt} second, now())`,\n );\n } else {\n nextRun = this.knex.raw(\n `greatest(next_run_start_at + interval '${dt} seconds', now())`,\n );\n }\n }\n\n const rows = await this.knex<DbTasksRow>(DB_TASKS_TABLE)\n .where('id', '=', this.taskId)\n .where('current_run_ticket', '=', ticket)\n .update({\n next_run_start_at: nextRun,\n current_run_ticket: this.knex.raw('null'),\n current_run_started_at: this.knex.raw('null'),\n current_run_expires_at: this.knex.raw('null'),\n last_run_ended_at: this.knex.fn.now(),\n last_run_error_json: error\n ? serializeError(error)\n : this.knex.raw('null'),\n });\n\n return rows === 1;\n }\n\n private nextRunAtRaw(time: DateTime): Knex.Raw {\n if (this.knex.client.config.client.includes('sqlite3')) {\n return this.knex.raw('datetime(?)', [time.toISO()]);\n } else if (this.knex.client.config.client.includes('mysql')) {\n return this.knex.raw(`?`, [time.toSQL({ includeOffset: false })]);\n }\n return this.knex.raw(`?`, [time.toISO()]);\n }\n}\n"],"names":["Duration","sleep","DB_TASKS_TABLE","NotFoundError","ConflictError","dbTime","uuid","delegateAbortController","taskSettingsV2Schema","nowPlus","CronTime","DateTime","serializeError"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JsonObject } from '@backstage/types';\nimport { CronTime } from 'cron';\nimport { Duration } from 'luxon';\nimport { z } from 'zod';\n\nfunction isValidOptionalDurationString(d: string | undefined): boolean {\n try {\n return !d || Duration.fromISO(d).isValid;\n } catch {\n return false;\n }\n}\n\nfunction isValidCronFormat(c: string | undefined): boolean {\n try {\n if (!c) {\n return false;\n }\n // parse cron format to ensure it's a valid format.\n // eslint-disable-next-line no-new\n new CronTime(c);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidTrigger(t: string): boolean {\n return t === 'manual';\n}\n\nexport const taskSettingsV1Schema = z.object({\n version: z.literal(1),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n recurringAtMostEveryDuration: z\n .string()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 1).\n */\nexport type TaskSettingsV1 = z.infer<typeof taskSettingsV1Schema>;\n\nexport const taskSettingsV2Schema = z.object({\n version: z.literal(2),\n cadence: z\n .string()\n .refine(isValidCronFormat, { message: 'Invalid cron' })\n .or(\n z.string().refine(isValidTrigger, {\n message: \"Invalid trigger, expecting 'manual'\",\n }),\n )\n .or(\n z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n ),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 2).\n */\nexport type TaskSettingsV2 = z.infer<typeof taskSettingsV2Schema>;\n\n/**\n * The shape of a task definition as returned by the service's REST API.\n */\nexport interface TaskApiTasksResponse {\n taskId: string;\n pluginId: string;\n scope: 'global' | 'local';\n settings: { version: number } & JsonObject;\n taskState:\n | {\n status: 'running';\n startedAt: string;\n timesOutAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | {\n status: 'idle';\n startsAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | null;\n workerState:\n | {\n status: 'initial-wait';\n }\n | {\n status: 'idle';\n }\n | {\n status: 'running';\n }\n | null;\n}\n"],"names":["Duration","CronTime","z"],"mappings":";;;;;;AAqBA,SAAS,8BAA8B,CAAgC,EAAA;AACrE,EAAI,IAAA;AACF,IAAA,OAAO,CAAC,CAAA,IAAKA,cAAS,CAAA,OAAA,CAAQ,CAAC,CAAE,CAAA,OAAA;AAAA,GAC3B,CAAA,MAAA;AACN,IAAO,OAAA,KAAA;AAAA;AAEX;AAEA,SAAS,kBAAkB,CAAgC,EAAA;AACzD,EAAI,IAAA;AACF,IAAA,IAAI,CAAC,CAAG,EAAA;AACN,MAAO,OAAA,KAAA;AAAA;AAIT,IAAA,IAAIC,cAAS,CAAC,CAAA;AACd,IAAO,OAAA,IAAA;AAAA,GACD,CAAA,MAAA;AACN,IAAO,OAAA,KAAA;AAAA;AAEX;AAEA,SAAS,eAAe,CAAoB,EAAA;AAC1C,EAAA,OAAO,CAAM,KAAA,QAAA;AACf;AAEoCC,MAAE,MAAO,CAAA;AAAA,EAC3C,OAAA,EAASA,KAAE,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,sBAAsBA,KACnB,CAAA,MAAA,GACA,QAAS,EAAA,CACT,OAAO,6BAA+B,EAAA;AAAA,IACrC,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACH,4BAA8B,EAAAA,KAAA,CAC3B,MAAO,EAAA,CACP,OAAO,6BAA+B,EAAA;AAAA,IACrC,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACH,oBAAsB,EAAAA,KAAA,CAAE,MAAO,EAAA,CAAE,OAAO,6BAA+B,EAAA;AAAA,IACrE,OAAS,EAAA;AAAA,GACV;AACH,CAAC;AAOY,MAAA,oBAAA,GAAuBA,MAAE,MAAO,CAAA;AAAA,EAC3C,OAAA,EAASA,KAAE,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,OAAA,EAASA,KACN,CAAA,MAAA,EACA,CAAA,MAAA,CAAO,mBAAmB,EAAE,OAAA,EAAS,cAAe,EAAC,CACrD,CAAA,EAAA;AAAA,IACCA,KAAE,CAAA,MAAA,EAAS,CAAA,MAAA,CAAO,cAAgB,EAAA;AAAA,MAChC,OAAS,EAAA;AAAA,KACV;AAAA,GAEF,CAAA,EAAA;AAAA,IACCA,KAAE,CAAA,MAAA,EAAS,CAAA,MAAA,CAAO,6BAA+B,EAAA;AAAA,MAC/C,OAAS,EAAA;AAAA,KACV;AAAA,GACH;AAAA,EACF,oBAAsB,EAAAA,KAAA,CAAE,MAAO,EAAA,CAAE,OAAO,6BAA+B,EAAA;AAAA,IACrE,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,sBAAsBA,KACnB,CAAA,MAAA,GACA,QAAS,EAAA,CACT,OAAO,6BAA+B,EAAA;AAAA,IACrC,OAAS,EAAA;AAAA,GACV;AACL,CAAC;;;;"}
1
+ {"version":3,"file":"types.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JsonObject } from '@backstage/types';\nimport { CronTime } from 'cron';\nimport { Duration } from 'luxon';\nimport { z } from 'zod';\n\nfunction isValidOptionalDurationString(d: string | undefined): boolean {\n try {\n return !d || Duration.fromISO(d).isValid;\n } catch {\n return false;\n }\n}\n\nfunction isValidCronFormat(c: string | undefined): boolean {\n try {\n if (!c) {\n return false;\n }\n // parse cron format to ensure it's a valid format.\n // eslint-disable-next-line no-new\n new CronTime(c);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidTrigger(t: string): boolean {\n return t === 'manual';\n}\n\nexport const taskSettingsV1Schema = z.object({\n version: z.literal(1),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n recurringAtMostEveryDuration: z\n .string()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 1).\n */\nexport type TaskSettingsV1 = z.infer<typeof taskSettingsV1Schema>;\n\nexport const taskSettingsV2Schema = z.object({\n version: z.literal(2),\n cadence: z\n .string()\n .refine(isValidCronFormat, { message: 'Invalid cron' })\n .or(\n z.string().refine(isValidTrigger, {\n message: \"Invalid trigger, expecting 'manual'\",\n }),\n )\n .or(\n z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n ),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 2).\n */\nexport type TaskSettingsV2 = z.infer<typeof taskSettingsV2Schema>;\n\n/**\n * The shape of a task definition as returned by the service's REST API.\n */\nexport interface TaskApiTasksResponse {\n taskId: string;\n pluginId: string;\n scope: 'global' | 'local';\n settings: { version: number } & JsonObject;\n taskState:\n | {\n status: 'running';\n startedAt: string;\n timesOutAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | {\n status: 'idle';\n startsAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | null;\n workerState:\n | {\n status: 'initial-wait';\n }\n | {\n status: 'idle';\n }\n | {\n status: 'running';\n }\n | null;\n}\n"],"names":["Duration","CronTime","z"],"mappings":";;;;;;AAqBA,SAAS,8BAA8B,CAAA,EAAgC;AACrE,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,CAAA,IAAKA,cAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,CAAA,EAAgC;AACzD,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,CAAA,EAAG;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,IAAIC,cAAS,CAAC,CAAA;AACd,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,eAAe,CAAA,EAAoB;AAC1C,EAAA,OAAO,CAAA,KAAM,QAAA;AACf;AAEoCC,MAAE,MAAA,CAAO;AAAA,EAC3C,OAAA,EAASA,KAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,sBAAsBA,KAAA,CACnB,MAAA,GACA,QAAA,EAAS,CACT,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACH,4BAAA,EAA8BA,KAAA,CAC3B,MAAA,EAAO,CACP,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACH,oBAAA,EAAsBA,KAAA,CAAE,MAAA,EAAO,CAAE,OAAO,6BAAA,EAA+B;AAAA,IACrE,OAAA,EAAS;AAAA,GACV;AACH,CAAC;AAOM,MAAM,oBAAA,GAAuBA,MAAE,MAAA,CAAO;AAAA,EAC3C,OAAA,EAASA,KAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,OAAA,EAASA,KAAA,CACN,MAAA,EAAO,CACP,MAAA,CAAO,mBAAmB,EAAE,OAAA,EAAS,cAAA,EAAgB,CAAA,CACrD,EAAA;AAAA,IACCA,KAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,cAAA,EAAgB;AAAA,MAChC,OAAA,EAAS;AAAA,KACV;AAAA,GACH,CACC,EAAA;AAAA,IACCA,KAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,6BAAA,EAA+B;AAAA,MAC/C,OAAA,EAAS;AAAA,KACV;AAAA,GACH;AAAA,EACF,oBAAA,EAAsBA,KAAA,CAAE,MAAA,EAAO,CAAE,OAAO,6BAAA,EAA+B;AAAA,IACrE,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACD,sBAAsBA,KAAA,CACnB,MAAA,GACA,QAAA,EAAS,CACT,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV;AACL,CAAC;;;;"}