@backstage/backend-defaults 0.5.1-next.0 → 0.5.1-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/auth/package.json +1 -1
- package/cache/package.json +1 -1
- package/database/package.json +1 -1
- package/discovery/package.json +1 -1
- package/dist/CreateBackend.cjs.js +49 -0
- package/dist/CreateBackend.cjs.js.map +1 -0
- package/dist/PackageDiscoveryService.cjs.js +109 -0
- package/dist/PackageDiscoveryService.cjs.js.map +1 -0
- package/dist/auth.cjs.js +2 -996
- package/dist/auth.cjs.js.map +1 -1
- package/dist/cache.cjs.js +4 -204
- package/dist/cache.cjs.js.map +1 -1
- package/dist/database.cjs.js +4 -957
- package/dist/database.cjs.js.map +1 -1
- package/dist/database.d.ts +4 -1
- package/dist/discovery.cjs.js +4 -92
- package/dist/discovery.cjs.js.map +1 -1
- package/dist/discoveryFeatureLoader.cjs.js +19 -0
- package/dist/discoveryFeatureLoader.cjs.js.map +1 -0
- package/dist/entrypoints/auth/DefaultAuthService.cjs.js +130 -0
- package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -0
- package/dist/entrypoints/auth/JwksClient.cjs.js +49 -0
- package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -0
- package/dist/entrypoints/auth/authServiceFactory.cjs.js +57 -0
- package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js +78 -0
- package/dist/entrypoints/auth/external/ExternalTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/helpers.cjs.js +92 -0
- package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/jwks.cjs.js +63 -0
- package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/legacy.cjs.js +73 -0
- package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -0
- package/dist/entrypoints/auth/external/static.cjs.js +33 -0
- package/dist/entrypoints/auth/external/static.cjs.js.map +1 -0
- package/dist/{cjs/helpers-D2f1CG0o.cjs.js → entrypoints/auth/helpers.cjs.js} +1 -1
- package/dist/entrypoints/auth/helpers.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js +147 -0
- package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js +73 -0
- package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js +75 -0
- package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js +91 -0
- package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js +29 -0
- package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -0
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js +110 -0
- package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -0
- package/dist/entrypoints/cache/CacheClient.cjs.js +50 -0
- package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -0
- package/dist/entrypoints/cache/CacheManager.cjs.js +147 -0
- package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -0
- package/dist/entrypoints/cache/cacheServiceFactory.cjs.js +22 -0
- package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/cache/types.cjs.js +10 -0
- package/dist/entrypoints/cache/types.cjs.js.map +1 -0
- package/dist/entrypoints/database/DatabaseManager.cjs.js +173 -0
- package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js +14 -0
- package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js +12 -0
- package/dist/entrypoints/database/connectors/defaultSchemaOverride.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js +10 -0
- package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/mysql.cjs.js +278 -0
- package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/postgres.cjs.js +304 -0
- package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -0
- package/dist/entrypoints/database/connectors/sqlite3.cjs.js +251 -0
- package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -0
- package/dist/entrypoints/database/databaseServiceFactory.cjs.js +36 -0
- package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/discovery/HostDiscovery.cjs.js +86 -0
- package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -0
- package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js +192 -0
- package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js +19 -0
- package/dist/entrypoints/httpRouter/createAuthIntegrationRouter.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js +26 -0
- package/dist/entrypoints/httpRouter/createCookieAuthRefreshMiddleware.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js +63 -0
- package/dist/entrypoints/httpRouter/createCredentialsBarrier.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js +52 -0
- package/dist/entrypoints/httpRouter/createLifecycleMiddleware.cjs.js.map +1 -0
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js +48 -0
- package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js +88 -0
- package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/logger/loggerServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js +22 -0
- package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -0
- package/dist/{cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js → entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js} +1 -1
- package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -0
- package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js +26 -0
- package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js +41 -0
- package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js +77 -0
- package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js +29 -0
- package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js +187 -0
- package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js +28 -0
- package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -0
- package/dist/{cjs/config-BDOwXIyo.cjs.js → entrypoints/rootHttpRouter/http/config.cjs.js} +1 -1
- package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js +88 -0
- package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js +130 -0
- package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js +51 -0
- package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js +62 -0
- package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -0
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js +73 -0
- package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js +76 -0
- package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js +114 -0
- package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -0
- package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js +30 -0
- package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js +18 -0
- package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/database/tables.cjs.js +8 -0
- package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js +37 -0
- package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js +105 -0
- package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js +138 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js +59 -0
- package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js +275 -0
- package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/types.cjs.js +60 -0
- package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/lib/util.cjs.js +66 -0
- package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -0
- package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js +19 -0
- package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js +274 -0
- package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js +261 -0
- package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js +148 -0
- package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js +174 -0
- package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js +170 -0
- package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js +182 -0
- package/dist/entrypoints/urlReader/lib/BitbucketUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js +132 -0
- package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js +147 -0
- package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js +122 -0
- package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js +226 -0
- package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js +277 -0
- package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js +129 -0
- package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js +120 -0
- package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js +49 -0
- package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js +46 -0
- package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js +68 -0
- package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js +46 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js +78 -0
- package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js +147 -0
- package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js +161 -0
- package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/tree/util.cjs.js +28 -0
- package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/lib/util.cjs.js +11 -0
- package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -0
- package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js +29 -0
- package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -0
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js +59 -0
- package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -0
- package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js +17 -0
- package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -0
- package/dist/httpAuth.cjs.js +3 -187
- package/dist/httpAuth.cjs.js.map +1 -1
- package/dist/httpRouter.cjs.js +2 -166
- package/dist/httpRouter.cjs.js.map +1 -1
- package/dist/index.cjs.js +4 -160
- package/dist/index.cjs.js.map +1 -1
- package/dist/lib/escapeRegExp.cjs.js +8 -0
- package/dist/lib/escapeRegExp.cjs.js.map +1 -0
- package/dist/lifecycle.cjs.js +3 -58
- package/dist/lifecycle.cjs.js.map +1 -1
- package/dist/logger.cjs.js +3 -12
- package/dist/logger.cjs.js.map +1 -1
- package/dist/package.json.cjs.js +252 -0
- package/dist/package.json.cjs.js.map +1 -0
- package/dist/permissions.cjs.js +3 -17
- package/dist/permissions.cjs.js.map +1 -1
- package/dist/rootConfig.cjs.js +4 -22
- package/dist/rootConfig.cjs.js.map +1 -1
- package/dist/rootHealth.cjs.js +3 -35
- package/dist/rootHealth.cjs.js.map +1 -1
- package/dist/rootHttpRouter.cjs.js +15 -651
- package/dist/rootHttpRouter.cjs.js.map +1 -1
- package/dist/rootLifecycle.cjs.js +3 -70
- package/dist/rootLifecycle.cjs.js.map +1 -1
- package/dist/rootLogger.cjs.js +4 -137
- package/dist/rootLogger.cjs.js.map +1 -1
- package/dist/scheduler.cjs.js +4 -693
- package/dist/scheduler.cjs.js.map +1 -1
- package/dist/scheduler.d.ts +2 -1
- package/dist/urlReader.cjs.js +32 -2962
- package/dist/urlReader.cjs.js.map +1 -1
- package/dist/userInfo.cjs.js +2 -64
- package/dist/userInfo.cjs.js.map +1 -1
- package/httpAuth/package.json +1 -1
- package/httpRouter/package.json +1 -1
- package/lifecycle/package.json +1 -1
- package/logger/package.json +1 -1
- package/package.json +20 -20
- package/permissions/package.json +1 -1
- package/rootConfig/package.json +1 -1
- package/rootHealth/package.json +1 -1
- package/rootHttpRouter/package.json +1 -1
- package/rootLifecycle/package.json +1 -1
- package/rootLogger/package.json +1 -1
- package/scheduler/package.json +1 -1
- package/urlReader/package.json +1 -1
- package/userInfo/package.json +1 -1
- package/dist/cjs/config-BDOwXIyo.cjs.js.map +0 -1
- package/dist/cjs/createConfigSecretEnumerator-DShyoWWL.cjs.js.map +0 -1
- package/dist/cjs/helpers-D2f1CG0o.cjs.js.map +0 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
var cron = require('cron');
|
|
5
|
+
var luxon = require('luxon');
|
|
6
|
+
var uuid = require('uuid');
|
|
7
|
+
var tables = require('../database/tables.cjs.js');
|
|
8
|
+
var types = require('./types.cjs.js');
|
|
9
|
+
var util = require('./util.cjs.js');
|
|
10
|
+
|
|
11
|
+
const DEFAULT_WORK_CHECK_FREQUENCY = luxon.Duration.fromObject({ seconds: 5 });
|
|
12
|
+
class TaskWorker {
|
|
13
|
+
constructor(taskId, fn, knex, logger, workCheckFrequency = DEFAULT_WORK_CHECK_FREQUENCY) {
|
|
14
|
+
this.taskId = taskId;
|
|
15
|
+
this.fn = fn;
|
|
16
|
+
this.knex = knex;
|
|
17
|
+
this.logger = logger;
|
|
18
|
+
this.workCheckFrequency = workCheckFrequency;
|
|
19
|
+
}
|
|
20
|
+
async start(settings, options) {
|
|
21
|
+
try {
|
|
22
|
+
await this.persistTask(settings);
|
|
23
|
+
} catch (e) {
|
|
24
|
+
throw new Error(`Failed to persist task, ${e}`);
|
|
25
|
+
}
|
|
26
|
+
this.logger.info(
|
|
27
|
+
`Task worker starting: ${this.taskId}, ${JSON.stringify(settings)}`
|
|
28
|
+
);
|
|
29
|
+
let workCheckFrequency = this.workCheckFrequency;
|
|
30
|
+
const isDuration = settings?.cadence.startsWith("P");
|
|
31
|
+
if (isDuration) {
|
|
32
|
+
const cadence = luxon.Duration.fromISO(settings.cadence);
|
|
33
|
+
if (cadence < workCheckFrequency) {
|
|
34
|
+
workCheckFrequency = cadence;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
let attemptNum = 1;
|
|
38
|
+
(async () => {
|
|
39
|
+
for (; ; ) {
|
|
40
|
+
try {
|
|
41
|
+
if (settings.initialDelayDuration) {
|
|
42
|
+
await util.sleep(
|
|
43
|
+
luxon.Duration.fromISO(settings.initialDelayDuration),
|
|
44
|
+
options.signal
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
while (!options.signal.aborted) {
|
|
48
|
+
const runResult = await this.runOnce(options.signal);
|
|
49
|
+
if (runResult.result === "abort") {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
await util.sleep(workCheckFrequency, options.signal);
|
|
53
|
+
}
|
|
54
|
+
this.logger.info(`Task worker finished: ${this.taskId}`);
|
|
55
|
+
attemptNum = 0;
|
|
56
|
+
break;
|
|
57
|
+
} catch (e) {
|
|
58
|
+
attemptNum += 1;
|
|
59
|
+
this.logger.warn(
|
|
60
|
+
`Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`
|
|
61
|
+
);
|
|
62
|
+
await util.sleep(luxon.Duration.fromObject({ seconds: 1 }));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
}
|
|
67
|
+
static async trigger(knex, taskId) {
|
|
68
|
+
const rows = await knex(tables.DB_TASKS_TABLE).select(knex.raw(1)).where("id", "=", taskId);
|
|
69
|
+
if (rows.length !== 1) {
|
|
70
|
+
throw new errors.NotFoundError(`Task ${taskId} does not exist`);
|
|
71
|
+
}
|
|
72
|
+
const updatedRows = await knex(tables.DB_TASKS_TABLE).where("id", "=", taskId).whereNull("current_run_ticket").update({
|
|
73
|
+
next_run_start_at: knex.fn.now()
|
|
74
|
+
});
|
|
75
|
+
if (updatedRows < 1) {
|
|
76
|
+
throw new errors.ConflictError(`Task ${taskId} is currently running`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Makes a single attempt at running the task to completion, if ready.
|
|
81
|
+
*
|
|
82
|
+
* @returns The outcome of the attempt
|
|
83
|
+
*/
|
|
84
|
+
async runOnce(signal) {
|
|
85
|
+
const findResult = await this.findReadyTask();
|
|
86
|
+
if (findResult.result === "not-ready-yet" || findResult.result === "abort") {
|
|
87
|
+
return findResult;
|
|
88
|
+
}
|
|
89
|
+
const taskSettings = findResult.settings;
|
|
90
|
+
const ticket = uuid.v4();
|
|
91
|
+
const claimed = await this.tryClaimTask(ticket, taskSettings);
|
|
92
|
+
if (!claimed) {
|
|
93
|
+
return { result: "not-ready-yet" };
|
|
94
|
+
}
|
|
95
|
+
const taskAbortController = util.delegateAbortController(signal);
|
|
96
|
+
const timeoutHandle = setTimeout(() => {
|
|
97
|
+
taskAbortController.abort();
|
|
98
|
+
}, luxon.Duration.fromISO(taskSettings.timeoutAfterDuration).as("milliseconds"));
|
|
99
|
+
try {
|
|
100
|
+
await this.fn(taskAbortController.signal);
|
|
101
|
+
taskAbortController.abort();
|
|
102
|
+
} catch (e) {
|
|
103
|
+
this.logger.error(e);
|
|
104
|
+
await this.tryReleaseTask(ticket, taskSettings);
|
|
105
|
+
return { result: "failed" };
|
|
106
|
+
} finally {
|
|
107
|
+
clearTimeout(timeoutHandle);
|
|
108
|
+
}
|
|
109
|
+
await this.tryReleaseTask(ticket, taskSettings);
|
|
110
|
+
return { result: "completed" };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Perform the initial store of the task info
|
|
114
|
+
*/
|
|
115
|
+
async persistTask(settings) {
|
|
116
|
+
types.taskSettingsV2Schema.parse(settings);
|
|
117
|
+
const isManual = settings?.cadence === "manual";
|
|
118
|
+
const isDuration = settings?.cadence.startsWith("P");
|
|
119
|
+
const isCron = !isManual && !isDuration;
|
|
120
|
+
let startAt;
|
|
121
|
+
let nextStartAt;
|
|
122
|
+
if (settings.initialDelayDuration) {
|
|
123
|
+
startAt = util.nowPlus(
|
|
124
|
+
luxon.Duration.fromISO(settings.initialDelayDuration),
|
|
125
|
+
this.knex
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
if (isCron) {
|
|
129
|
+
const time = new cron.CronTime(settings.cadence).sendAt().minus({ seconds: 1 }).toUTC();
|
|
130
|
+
nextStartAt = this.nextRunAtRaw(time);
|
|
131
|
+
startAt ||= nextStartAt;
|
|
132
|
+
} else if (isManual) {
|
|
133
|
+
nextStartAt = this.knex.raw("null");
|
|
134
|
+
startAt ||= nextStartAt;
|
|
135
|
+
} else {
|
|
136
|
+
startAt ||= this.knex.fn.now();
|
|
137
|
+
nextStartAt = util.nowPlus(luxon.Duration.fromISO(settings.cadence), this.knex);
|
|
138
|
+
}
|
|
139
|
+
this.logger.debug(`task: ${this.taskId} configured to run at: ${startAt}`);
|
|
140
|
+
const settingsJson = JSON.stringify(settings);
|
|
141
|
+
await this.knex(tables.DB_TASKS_TABLE).insert({
|
|
142
|
+
id: this.taskId,
|
|
143
|
+
settings_json: settingsJson,
|
|
144
|
+
next_run_start_at: startAt
|
|
145
|
+
}).onConflict("id").merge(
|
|
146
|
+
this.knex.client.config.client.includes("mysql") ? {
|
|
147
|
+
settings_json: settingsJson,
|
|
148
|
+
next_run_start_at: this.knex.raw(
|
|
149
|
+
`CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,
|
|
150
|
+
[
|
|
151
|
+
nextStartAt,
|
|
152
|
+
"next_run_start_at",
|
|
153
|
+
nextStartAt,
|
|
154
|
+
"next_run_start_at"
|
|
155
|
+
]
|
|
156
|
+
)
|
|
157
|
+
} : {
|
|
158
|
+
settings_json: this.knex.ref("excluded.settings_json"),
|
|
159
|
+
next_run_start_at: this.knex.raw(
|
|
160
|
+
`CASE WHEN ?? < ?? THEN ?? ELSE ?? END`,
|
|
161
|
+
[
|
|
162
|
+
nextStartAt,
|
|
163
|
+
`${tables.DB_TASKS_TABLE}.next_run_start_at`,
|
|
164
|
+
nextStartAt,
|
|
165
|
+
`${tables.DB_TASKS_TABLE}.next_run_start_at`
|
|
166
|
+
]
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Check if the task is ready to run
|
|
173
|
+
*/
|
|
174
|
+
async findReadyTask() {
|
|
175
|
+
const [row] = await this.knex(tables.DB_TASKS_TABLE).where("id", "=", this.taskId).select({
|
|
176
|
+
settingsJson: "settings_json",
|
|
177
|
+
ready: this.knex.raw(
|
|
178
|
+
`CASE
|
|
179
|
+
WHEN next_run_start_at <= ? AND current_run_ticket IS NULL THEN TRUE
|
|
180
|
+
ELSE FALSE
|
|
181
|
+
END`,
|
|
182
|
+
[this.knex.fn.now()]
|
|
183
|
+
)
|
|
184
|
+
});
|
|
185
|
+
if (!row) {
|
|
186
|
+
this.logger.info(
|
|
187
|
+
"No longer able to find task; aborting and assuming that it has been unregistered or expired"
|
|
188
|
+
);
|
|
189
|
+
return { result: "abort" };
|
|
190
|
+
} else if (!row.ready) {
|
|
191
|
+
return { result: "not-ready-yet" };
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const obj = JSON.parse(row.settingsJson);
|
|
195
|
+
const settings = types.taskSettingsV2Schema.parse(obj);
|
|
196
|
+
return { result: "ready", settings };
|
|
197
|
+
} catch (e) {
|
|
198
|
+
this.logger.info(
|
|
199
|
+
`Task "${this.taskId}" is no longer able to parse task settings; aborting and assuming that a newer version of the task has been issued and being handled by other workers, ${e}`
|
|
200
|
+
);
|
|
201
|
+
return { result: "abort" };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Attempts to claim a task that's ready for execution, on this worker's
|
|
206
|
+
* behalf. We should not attempt to perform the work unless the claim really
|
|
207
|
+
* goes through.
|
|
208
|
+
*
|
|
209
|
+
* @param ticket - A globally unique string that changes for each invocation
|
|
210
|
+
* @param settings - The settings of the task to claim
|
|
211
|
+
* @returns True if it was successfully claimed
|
|
212
|
+
*/
|
|
213
|
+
async tryClaimTask(ticket, settings) {
|
|
214
|
+
const startedAt = this.knex.fn.now();
|
|
215
|
+
const expiresAt = settings.timeoutAfterDuration ? util.nowPlus(luxon.Duration.fromISO(settings.timeoutAfterDuration), this.knex) : this.knex.raw("null");
|
|
216
|
+
const rows = await this.knex(tables.DB_TASKS_TABLE).where("id", "=", this.taskId).whereNull("current_run_ticket").update({
|
|
217
|
+
current_run_ticket: ticket,
|
|
218
|
+
current_run_started_at: startedAt,
|
|
219
|
+
current_run_expires_at: expiresAt
|
|
220
|
+
});
|
|
221
|
+
return rows === 1;
|
|
222
|
+
}
|
|
223
|
+
async tryReleaseTask(ticket, settings) {
|
|
224
|
+
const isManual = settings?.cadence === "manual";
|
|
225
|
+
const isDuration = settings?.cadence.startsWith("P");
|
|
226
|
+
const isCron = !isManual && !isDuration;
|
|
227
|
+
let nextRun;
|
|
228
|
+
if (isCron) {
|
|
229
|
+
const time = new cron.CronTime(settings.cadence).sendAt().toUTC();
|
|
230
|
+
this.logger.debug(`task: ${this.taskId} will next occur around ${time}`);
|
|
231
|
+
nextRun = this.nextRunAtRaw(time);
|
|
232
|
+
} else if (isManual) {
|
|
233
|
+
nextRun = this.knex.raw("null");
|
|
234
|
+
} else {
|
|
235
|
+
const dt = luxon.Duration.fromISO(settings.cadence).as("seconds");
|
|
236
|
+
this.logger.debug(
|
|
237
|
+
`task: ${this.taskId} will next occur around ${luxon.DateTime.now().plus({
|
|
238
|
+
seconds: dt
|
|
239
|
+
})}`
|
|
240
|
+
);
|
|
241
|
+
if (this.knex.client.config.client.includes("sqlite3")) {
|
|
242
|
+
nextRun = this.knex.raw(
|
|
243
|
+
`max(datetime(next_run_start_at, ?), datetime('now'))`,
|
|
244
|
+
[`+${dt} seconds`]
|
|
245
|
+
);
|
|
246
|
+
} else if (this.knex.client.config.client.includes("mysql")) {
|
|
247
|
+
nextRun = this.knex.raw(
|
|
248
|
+
`greatest(next_run_start_at + interval ${dt} second, now())`
|
|
249
|
+
);
|
|
250
|
+
} else {
|
|
251
|
+
nextRun = this.knex.raw(
|
|
252
|
+
`greatest(next_run_start_at + interval '${dt} seconds', now())`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const rows = await this.knex(tables.DB_TASKS_TABLE).where("id", "=", this.taskId).where("current_run_ticket", "=", ticket).update({
|
|
257
|
+
next_run_start_at: nextRun,
|
|
258
|
+
current_run_ticket: this.knex.raw("null"),
|
|
259
|
+
current_run_started_at: this.knex.raw("null"),
|
|
260
|
+
current_run_expires_at: this.knex.raw("null")
|
|
261
|
+
});
|
|
262
|
+
return rows === 1;
|
|
263
|
+
}
|
|
264
|
+
nextRunAtRaw(time) {
|
|
265
|
+
if (this.knex.client.config.client.includes("sqlite3")) {
|
|
266
|
+
return this.knex.raw("datetime(?)", [time.toISO()]);
|
|
267
|
+
} else if (this.knex.client.config.client.includes("mysql")) {
|
|
268
|
+
return this.knex.raw(`?`, [time.toSQL({ includeOffset: false })]);
|
|
269
|
+
}
|
|
270
|
+
return this.knex.raw(`?`, [time.toISO()]);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
exports.TaskWorker = TaskWorker;
|
|
275
|
+
//# sourceMappingURL=TaskWorker.cjs.js.map
|
|
@@ -0,0 +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 { TaskSettingsV2, taskSettingsV2Schema } from './types';\nimport { delegateAbortController, nowPlus, sleep } 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 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 let attemptNum = 1;\n (async () => {\n for (;;) {\n try {\n if (settings.initialDelayDuration) {\n await sleep(\n Duration.fromISO(settings.initialDelayDuration),\n options.signal,\n );\n }\n\n while (!options.signal.aborted) {\n const runResult = await this.runOnce(options.signal);\n\n if (runResult.result === 'abort') {\n break;\n }\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 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 /**\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 await this.fn(taskAbortController.signal);\n taskAbortController.abort(); // releases resources\n } catch (e) {\n this.logger.error(e);\n await this.tryReleaseTask(ticket, taskSettings);\n return { result: 'failed' };\n } finally {\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 ): 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 });\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","uuid","delegateAbortController","taskSettingsV2Schema","nowPlus","CronTime","DateTime"],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var cron = require('cron');
|
|
4
|
+
var luxon = require('luxon');
|
|
5
|
+
var zod = require('zod');
|
|
6
|
+
|
|
7
|
+
function isValidOptionalDurationString(d) {
|
|
8
|
+
try {
|
|
9
|
+
return !d || luxon.Duration.fromISO(d).isValid;
|
|
10
|
+
} catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function isValidCronFormat(c) {
|
|
15
|
+
try {
|
|
16
|
+
if (!c) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
new cron.CronTime(c);
|
|
20
|
+
return true;
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function isValidTrigger(t) {
|
|
26
|
+
return t === "manual";
|
|
27
|
+
}
|
|
28
|
+
zod.z.object({
|
|
29
|
+
version: zod.z.literal(1),
|
|
30
|
+
initialDelayDuration: zod.z.string().optional().refine(isValidOptionalDurationString, {
|
|
31
|
+
message: "Invalid duration, expecting ISO Period"
|
|
32
|
+
}),
|
|
33
|
+
recurringAtMostEveryDuration: zod.z.string().refine(isValidOptionalDurationString, {
|
|
34
|
+
message: "Invalid duration, expecting ISO Period"
|
|
35
|
+
}),
|
|
36
|
+
timeoutAfterDuration: zod.z.string().refine(isValidOptionalDurationString, {
|
|
37
|
+
message: "Invalid duration, expecting ISO Period"
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
const taskSettingsV2Schema = zod.z.object({
|
|
41
|
+
version: zod.z.literal(2),
|
|
42
|
+
cadence: zod.z.string().refine(isValidCronFormat, { message: "Invalid cron" }).or(
|
|
43
|
+
zod.z.string().refine(isValidTrigger, {
|
|
44
|
+
message: "Invalid trigger, expecting 'manual'"
|
|
45
|
+
})
|
|
46
|
+
).or(
|
|
47
|
+
zod.z.string().refine(isValidOptionalDurationString, {
|
|
48
|
+
message: "Invalid duration, expecting ISO Period"
|
|
49
|
+
})
|
|
50
|
+
),
|
|
51
|
+
timeoutAfterDuration: zod.z.string().refine(isValidOptionalDurationString, {
|
|
52
|
+
message: "Invalid duration, expecting ISO Period"
|
|
53
|
+
}),
|
|
54
|
+
initialDelayDuration: zod.z.string().optional().refine(isValidOptionalDurationString, {
|
|
55
|
+
message: "Invalid duration, expecting ISO Period"
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
exports.taskSettingsV2Schema = taskSettingsV2Schema;
|
|
60
|
+
//# sourceMappingURL=types.cjs.js.map
|
|
@@ -0,0 +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 { 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"],"names":["Duration","CronTime","z"],"mappings":";;;;;;AAoBA,SAAS,8BAA8B,CAAgC,EAAA;AACrE,EAAI,IAAA;AACF,IAAA,OAAO,CAAC,CAAA,IAAKA,cAAS,CAAA,OAAA,CAAQ,CAAC,CAAE,CAAA,OAAA,CAAA;AAAA,GAC3B,CAAA,MAAA;AACN,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA;AAEA,SAAS,kBAAkB,CAAgC,EAAA;AACzD,EAAI,IAAA;AACF,IAAA,IAAI,CAAC,CAAG,EAAA;AACN,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AAGA,IAAA,IAAIC,cAAS,CAAC,CAAA,CAAA;AACd,IAAO,OAAA,IAAA,CAAA;AAAA,GACD,CAAA,MAAA;AACN,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA;AAEA,SAAS,eAAe,CAAoB,EAAA;AAC1C,EAAA,OAAO,CAAM,KAAA,QAAA,CAAA;AACf,CAAA;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,wCAAA;AAAA,GACV,CAAA;AAAA,EACH,4BAA8B,EAAAA,KAAA,CAC3B,MAAO,EAAA,CACP,OAAO,6BAA+B,EAAA;AAAA,IACrC,OAAS,EAAA,wCAAA;AAAA,GACV,CAAA;AAAA,EACH,oBAAsB,EAAAA,KAAA,CAAE,MAAO,EAAA,CAAE,OAAO,6BAA+B,EAAA;AAAA,IACrE,OAAS,EAAA,wCAAA;AAAA,GACV,CAAA;AACH,CAAC,EAAA;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,qCAAA;AAAA,KACV,CAAA;AAAA,GAEF,CAAA,EAAA;AAAA,IACCA,KAAE,CAAA,MAAA,EAAS,CAAA,MAAA,CAAO,6BAA+B,EAAA;AAAA,MAC/C,OAAS,EAAA,wCAAA;AAAA,KACV,CAAA;AAAA,GACH;AAAA,EACF,oBAAsB,EAAAA,KAAA,CAAE,MAAO,EAAA,CAAE,OAAO,6BAA+B,EAAA;AAAA,IACrE,OAAS,EAAA,wCAAA;AAAA,GACV,CAAA;AAAA,EACD,sBAAsBA,KACnB,CAAA,MAAA,GACA,QAAS,EAAA,CACT,OAAO,6BAA+B,EAAA;AAAA,IACrC,OAAS,EAAA,wCAAA;AAAA,GACV,CAAA;AACL,CAAC;;;;"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
require('luxon');
|
|
5
|
+
|
|
6
|
+
const TRACER_ID = "backstage-service-scheduler";
|
|
7
|
+
function validateId(id) {
|
|
8
|
+
if (typeof id !== "string" || !id.trim()) {
|
|
9
|
+
throw new errors.InputError(`${id} is not a valid ID, expected non-empty string`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function nowPlus(duration, knex) {
|
|
13
|
+
const seconds = duration?.as("seconds") ?? 0;
|
|
14
|
+
if (!seconds) {
|
|
15
|
+
return knex.fn.now();
|
|
16
|
+
}
|
|
17
|
+
if (knex.client.config.client.includes("sqlite3")) {
|
|
18
|
+
return knex.raw(`datetime('now', ?)`, [`${seconds} seconds`]);
|
|
19
|
+
}
|
|
20
|
+
if (knex.client.config.client.includes("mysql")) {
|
|
21
|
+
return knex.raw(`now() + interval ${seconds} second`);
|
|
22
|
+
}
|
|
23
|
+
return knex.raw(`now() + interval '${seconds} seconds'`);
|
|
24
|
+
}
|
|
25
|
+
async function sleep(duration, abortSignal) {
|
|
26
|
+
if (abortSignal?.aborted) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
await new Promise((resolve) => {
|
|
30
|
+
let timeoutHandle = void 0;
|
|
31
|
+
const done = () => {
|
|
32
|
+
if (timeoutHandle) {
|
|
33
|
+
clearTimeout(timeoutHandle);
|
|
34
|
+
}
|
|
35
|
+
abortSignal?.removeEventListener("abort", done);
|
|
36
|
+
resolve();
|
|
37
|
+
};
|
|
38
|
+
timeoutHandle = setTimeout(done, duration.as("milliseconds"));
|
|
39
|
+
abortSignal?.addEventListener("abort", done);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function delegateAbortController(parent) {
|
|
43
|
+
const delegate = new AbortController();
|
|
44
|
+
if (parent) {
|
|
45
|
+
if (parent.aborted) {
|
|
46
|
+
delegate.abort();
|
|
47
|
+
} else {
|
|
48
|
+
const onParentAborted = () => {
|
|
49
|
+
delegate.abort();
|
|
50
|
+
};
|
|
51
|
+
const onChildAborted = () => {
|
|
52
|
+
parent.removeEventListener("abort", onParentAborted);
|
|
53
|
+
};
|
|
54
|
+
parent.addEventListener("abort", onParentAborted, { once: true });
|
|
55
|
+
delegate.signal.addEventListener("abort", onChildAborted, { once: true });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return delegate;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
exports.TRACER_ID = TRACER_ID;
|
|
62
|
+
exports.delegateAbortController = delegateAbortController;
|
|
63
|
+
exports.nowPlus = nowPlus;
|
|
64
|
+
exports.sleep = sleep;
|
|
65
|
+
exports.validateId = validateId;
|
|
66
|
+
//# sourceMappingURL=util.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/util.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 { InputError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { DateTime, Duration } from 'luxon';\n\nexport const TRACER_ID = 'backstage-service-scheduler';\n\n// Keep the IDs compatible with e.g. Prometheus labels\nexport function validateId(id: string) {\n if (typeof id !== 'string' || !id.trim()) {\n throw new InputError(`${id} is not a valid ID, expected non-empty string`);\n }\n}\n\nexport function dbTime(t: Date | string): DateTime {\n if (typeof t === 'string') {\n return DateTime.fromSQL(t);\n }\n return DateTime.fromJSDate(t);\n}\n\nexport function nowPlus(duration: Duration | undefined, knex: Knex) {\n const seconds = duration?.as('seconds') ?? 0;\n if (!seconds) {\n return knex.fn.now();\n }\n\n if (knex.client.config.client.includes('sqlite3')) {\n return knex.raw(`datetime('now', ?)`, [`${seconds} seconds`]);\n }\n\n if (knex.client.config.client.includes('mysql')) {\n return knex.raw(`now() + interval ${seconds} second`);\n }\n\n return knex.raw(`now() + interval '${seconds} seconds'`);\n}\n\n/**\n * Sleep for the given duration, but return sooner if the abort signal\n * triggers.\n *\n * @param duration - The amount of time to sleep, at most\n * @param abortSignal - An optional abort signal that short circuits the wait\n */\nexport async function sleep(\n duration: Duration,\n abortSignal?: AbortSignal,\n): Promise<void> {\n if (abortSignal?.aborted) {\n return;\n }\n\n await new Promise<void>(resolve => {\n let timeoutHandle: NodeJS.Timeout | undefined = undefined;\n\n const done = () => {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n abortSignal?.removeEventListener('abort', done);\n resolve();\n };\n\n timeoutHandle = setTimeout(done, duration.as('milliseconds'));\n abortSignal?.addEventListener('abort', done);\n });\n}\n\n/**\n * Creates a new AbortController that, in addition to working as a regular\n * standalone controller, also gets aborted if the given parent signal\n * reaches aborted state.\n *\n * @param parent - The \"parent\" signal that can trigger the delegate\n */\nexport function delegateAbortController(parent?: AbortSignal): AbortController {\n const delegate = new AbortController();\n\n if (parent) {\n if (parent.aborted) {\n delegate.abort();\n } else {\n const onParentAborted = () => {\n delegate.abort();\n };\n\n const onChildAborted = () => {\n parent.removeEventListener('abort', onParentAborted);\n };\n\n parent.addEventListener('abort', onParentAborted, { once: true });\n delegate.signal.addEventListener('abort', onChildAborted, { once: true });\n }\n }\n\n return delegate;\n}\n"],"names":["InputError"],"mappings":";;;;;AAoBO,MAAM,SAAY,GAAA,8BAAA;AAGlB,SAAS,WAAW,EAAY,EAAA;AACrC,EAAA,IAAI,OAAO,EAAO,KAAA,QAAA,IAAY,CAAC,EAAA,CAAG,MAAQ,EAAA;AACxC,IAAA,MAAM,IAAIA,iBAAA,CAAW,CAAG,EAAA,EAAE,CAA+C,6CAAA,CAAA,CAAA,CAAA;AAAA,GAC3E;AACF,CAAA;AASgB,SAAA,OAAA,CAAQ,UAAgC,IAAY,EAAA;AAClE,EAAA,MAAM,OAAU,GAAA,QAAA,EAAU,EAAG,CAAA,SAAS,CAAK,IAAA,CAAA,CAAA;AAC3C,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAO,OAAA,IAAA,CAAK,GAAG,GAAI,EAAA,CAAA;AAAA,GACrB;AAEA,EAAA,IAAI,KAAK,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,QAAA,CAAS,SAAS,CAAG,EAAA;AACjD,IAAA,OAAO,KAAK,GAAI,CAAA,CAAA,kBAAA,CAAA,EAAsB,CAAC,CAAG,EAAA,OAAO,UAAU,CAAC,CAAA,CAAA;AAAA,GAC9D;AAEA,EAAA,IAAI,KAAK,MAAO,CAAA,MAAA,CAAO,MAAO,CAAA,QAAA,CAAS,OAAO,CAAG,EAAA;AAC/C,IAAA,OAAO,IAAK,CAAA,GAAA,CAAI,CAAoB,iBAAA,EAAA,OAAO,CAAS,OAAA,CAAA,CAAA,CAAA;AAAA,GACtD;AAEA,EAAA,OAAO,IAAK,CAAA,GAAA,CAAI,CAAqB,kBAAA,EAAA,OAAO,CAAW,SAAA,CAAA,CAAA,CAAA;AACzD,CAAA;AASsB,eAAA,KAAA,CACpB,UACA,WACe,EAAA;AACf,EAAA,IAAI,aAAa,OAAS,EAAA;AACxB,IAAA,OAAA;AAAA,GACF;AAEA,EAAM,MAAA,IAAI,QAAc,CAAW,OAAA,KAAA;AACjC,IAAA,IAAI,aAA4C,GAAA,KAAA,CAAA,CAAA;AAEhD,IAAA,MAAM,OAAO,MAAM;AACjB,MAAA,IAAI,aAAe,EAAA;AACjB,QAAA,YAAA,CAAa,aAAa,CAAA,CAAA;AAAA,OAC5B;AACA,MAAa,WAAA,EAAA,mBAAA,CAAoB,SAAS,IAAI,CAAA,CAAA;AAC9C,MAAQ,OAAA,EAAA,CAAA;AAAA,KACV,CAAA;AAEA,IAAA,aAAA,GAAgB,UAAW,CAAA,IAAA,EAAM,QAAS,CAAA,EAAA,CAAG,cAAc,CAAC,CAAA,CAAA;AAC5D,IAAa,WAAA,EAAA,gBAAA,CAAiB,SAAS,IAAI,CAAA,CAAA;AAAA,GAC5C,CAAA,CAAA;AACH,CAAA;AASO,SAAS,wBAAwB,MAAuC,EAAA;AAC7E,EAAM,MAAA,QAAA,GAAW,IAAI,eAAgB,EAAA,CAAA;AAErC,EAAA,IAAI,MAAQ,EAAA;AACV,IAAA,IAAI,OAAO,OAAS,EAAA;AAClB,MAAA,QAAA,CAAS,KAAM,EAAA,CAAA;AAAA,KACV,MAAA;AACL,MAAA,MAAM,kBAAkB,MAAM;AAC5B,QAAA,QAAA,CAAS,KAAM,EAAA,CAAA;AAAA,OACjB,CAAA;AAEA,MAAA,MAAM,iBAAiB,MAAM;AAC3B,QAAO,MAAA,CAAA,mBAAA,CAAoB,SAAS,eAAe,CAAA,CAAA;AAAA,OACrD,CAAA;AAEA,MAAA,MAAA,CAAO,iBAAiB,OAAS,EAAA,eAAA,EAAiB,EAAE,IAAA,EAAM,MAAM,CAAA,CAAA;AAChE,MAAA,QAAA,CAAS,OAAO,gBAAiB,CAAA,OAAA,EAAS,gBAAgB,EAAE,IAAA,EAAM,MAAM,CAAA,CAAA;AAAA,KAC1E;AAAA,GACF;AAEA,EAAO,OAAA,QAAA,CAAA;AACT;;;;;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
4
|
+
var DefaultSchedulerService = require('./lib/DefaultSchedulerService.cjs.js');
|
|
5
|
+
|
|
6
|
+
const schedulerServiceFactory = backendPluginApi.createServiceFactory({
|
|
7
|
+
service: backendPluginApi.coreServices.scheduler,
|
|
8
|
+
deps: {
|
|
9
|
+
database: backendPluginApi.coreServices.database,
|
|
10
|
+
logger: backendPluginApi.coreServices.logger,
|
|
11
|
+
rootLifecycle: backendPluginApi.coreServices.rootLifecycle
|
|
12
|
+
},
|
|
13
|
+
async factory({ database, logger, rootLifecycle }) {
|
|
14
|
+
return DefaultSchedulerService.DefaultSchedulerService.create({ database, logger, rootLifecycle });
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
exports.schedulerServiceFactory = schedulerServiceFactory;
|
|
19
|
+
//# sourceMappingURL=schedulerServiceFactory.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedulerServiceFactory.cjs.js","sources":["../../../src/entrypoints/scheduler/schedulerServiceFactory.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} from '@backstage/backend-plugin-api';\nimport { DefaultSchedulerService } from './lib/DefaultSchedulerService';\n\n/**\n * Scheduling of distributed background tasks.\n *\n * See {@link @backstage/code-plugin-api#SchedulerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/scheduler | the service docs}\n * for more information.\n *\n * @public\n */\nexport const schedulerServiceFactory = createServiceFactory({\n service: coreServices.scheduler,\n deps: {\n database: coreServices.database,\n logger: coreServices.logger,\n rootLifecycle: coreServices.rootLifecycle,\n },\n async factory({ database, logger, rootLifecycle }) {\n return DefaultSchedulerService.create({ database, logger, rootLifecycle });\n },\n});\n"],"names":["createServiceFactory","coreServices","DefaultSchedulerService"],"mappings":";;;;;AA+BO,MAAM,0BAA0BA,qCAAqB,CAAA;AAAA,EAC1D,SAASC,6BAAa,CAAA,SAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,UAAUA,6BAAa,CAAA,QAAA;AAAA,IACvB,QAAQA,6BAAa,CAAA,MAAA;AAAA,IACrB,eAAeA,6BAAa,CAAA,aAAA;AAAA,GAC9B;AAAA,EACA,MAAM,OAAQ,CAAA,EAAE,QAAU,EAAA,MAAA,EAAQ,eAAiB,EAAA;AACjD,IAAA,OAAOC,gDAAwB,MAAO,CAAA,EAAE,QAAU,EAAA,MAAA,EAAQ,eAAe,CAAA,CAAA;AAAA,GAC3E;AACF,CAAC;;;;"}
|