@webiny/background-tasks 6.4.5-beta.0 → 6.6.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/features/listLogs/ListLogsGateway.js +1 -1
- package/admin/features/listLogs/ListLogsGateway.js.map +1 -1
- package/admin/features/permissions/feature.d.ts +1 -1
- package/admin/presentation/BackgroundTaskSettings/BackgroundTaskSettingsPresenter.js +2 -2
- package/admin/presentation/BackgroundTaskSettings/BackgroundTaskSettingsPresenter.js.map +1 -1
- package/admin/presentation/TaskDetail/TaskDetailPresenter.js +1 -1
- package/admin/presentation/TaskDetail/TaskDetailPresenter.js.map +1 -1
- package/admin/presentation/TaskExecutions/TaskExecutionsDataSource.js +1 -1
- package/admin/presentation/TaskExecutions/TaskExecutionsDataSource.js.map +1 -1
- package/admin/presentation/TaskExecutions/TaskExecutionsPresenter.d.ts +2 -0
- package/admin/presentation/TaskExecutions/TaskExecutionsPresenter.js +3 -1
- package/admin/presentation/TaskExecutions/TaskExecutionsPresenter.js.map +1 -1
- package/api/BackgroundTasksFeature.d.ts +4 -0
- package/api/BackgroundTasksFeature.js +59 -0
- package/api/BackgroundTasksFeature.js.map +1 -0
- package/api/TasksCrud.d.ts +10 -0
- package/api/TasksCrud.js +5 -0
- package/api/TasksCrud.js.map +1 -0
- package/api/abstractions/Timer.d.ts +1 -0
- package/api/abstractions/Timer.js +0 -0
- package/api/abstractions/index.d.ts +1 -0
- package/api/abstractions/index.js +1 -0
- package/api/crud/cleanupTaskSubtree.d.ts +2 -2
- package/api/crud/cleanupTaskSubtree.js +8 -7
- package/api/crud/cleanupTaskSubtree.js.map +1 -1
- package/api/crud/crud.tasks.d.ts +3 -2
- package/api/crud/crud.tasks.js +37 -37
- package/api/crud/crud.tasks.js.map +1 -1
- package/api/crud/definition.tasks.d.ts +3 -2
- package/api/crud/definition.tasks.js +3 -3
- package/api/crud/definition.tasks.js.map +1 -1
- package/api/crud/service.tasks.d.ts +3 -2
- package/api/crud/service.tasks.js +21 -19
- package/api/crud/service.tasks.js.map +1 -1
- package/api/decorators/RunnableTaskDecorator.d.ts +1 -1
- package/api/decorators/RunnableTaskDecorator.js +2 -2
- package/api/decorators/RunnableTaskDecorator.js.map +1 -1
- package/api/decorators/SelfCleaningTaskDecorator.d.ts +1 -1
- package/api/domain/TaskService.d.ts +12 -0
- package/api/domain/TaskService.js +5 -0
- package/api/domain/TaskService.js.map +1 -0
- package/api/features/AbortTask/AbortTaskUseCase.d.ts +2 -3
- package/api/features/AbortTask/AbortTaskUseCase.js +3 -3
- package/api/features/AbortTask/AbortTaskUseCase.js.map +1 -1
- package/api/features/AbortTask/feature.d.ts +1 -2
- package/api/features/AbortTask/feature.js +3 -2
- package/api/features/AbortTask/feature.js.map +1 -1
- package/api/features/CleanupTaskSubtree/CleanupTaskSubtreeUseCase.d.ts +3 -3
- package/api/features/CleanupTaskSubtree/CleanupTaskSubtreeUseCase.js +3 -3
- package/api/features/CleanupTaskSubtree/CleanupTaskSubtreeUseCase.js.map +1 -1
- package/api/features/GetBackgroundTaskSettings/GetBackgroundTaskSettingsRepository.js +7 -4
- package/api/features/GetBackgroundTaskSettings/GetBackgroundTaskSettingsRepository.js.map +1 -1
- package/api/features/GetTask/GetTaskUseCase.d.ts +3 -3
- package/api/features/GetTask/GetTaskUseCase.js +3 -3
- package/api/features/GetTask/GetTaskUseCase.js.map +1 -1
- package/api/features/GetTask/feature.d.ts +1 -2
- package/api/features/GetTask/feature.js +3 -2
- package/api/features/GetTask/feature.js.map +1 -1
- package/api/features/ListTasks/ListTasksUseCase.d.ts +4 -3
- package/api/features/ListTasks/ListTasksUseCase.js +3 -3
- package/api/features/ListTasks/ListTasksUseCase.js.map +1 -1
- package/api/features/ListTasks/feature.d.ts +1 -2
- package/api/features/ListTasks/feature.js +3 -2
- package/api/features/ListTasks/feature.js.map +1 -1
- package/api/features/TaskController/TaskController.d.ts +2 -2
- package/api/features/TaskExecutionContext/TaskExecutionContext.d.ts +3 -3
- package/api/features/TaskExecutionContext/TaskExecutionContext.js.map +1 -1
- package/api/features/TaskExecutionContext/abstractions.d.ts +3 -3
- package/api/features/TaskExecutionContext/abstractions.js.map +1 -1
- package/api/features/TriggerTask/TriggerTaskUseCase.d.ts +2 -3
- package/api/features/TriggerTask/TriggerTaskUseCase.js +3 -3
- package/api/features/TriggerTask/TriggerTaskUseCase.js.map +1 -1
- package/api/features/TriggerTask/feature.d.ts +1 -2
- package/api/features/TriggerTask/feature.js +3 -2
- package/api/features/TriggerTask/feature.js.map +1 -1
- package/api/features/UpdateBackgroundTaskSettings/UpdateBackgroundTaskSettingsRepository.js +3 -2
- package/api/features/UpdateBackgroundTaskSettings/UpdateBackgroundTaskSettingsRepository.js.map +1 -1
- package/api/graphql/BackgroundTasksContextualSchema.d.ts +21 -0
- package/api/graphql/BackgroundTasksContextualSchema.js +369 -0
- package/api/graphql/BackgroundTasksContextualSchema.js.map +1 -0
- package/api/graphql/checkPermissions.js +2 -1
- package/api/graphql/checkPermissions.js.map +1 -1
- package/api/graphql/utils.d.ts +3 -3
- package/api/graphql/utils.js +1 -1
- package/api/graphql/utils.js.map +1 -1
- package/api/handler/types.d.ts +0 -2
- package/api/index.d.ts +10 -3
- package/api/index.js +9 -3
- package/api/response/DatabaseResponse.js +1 -1
- package/api/response/DatabaseResponse.js.map +1 -1
- package/api/runner/TaskControl.js +11 -8
- package/api/runner/TaskControl.js.map +1 -1
- package/api/runner/TaskManager.js +2 -1
- package/api/runner/TaskManager.js.map +1 -1
- package/api/runner/TaskManagerStore.d.ts +3 -2
- package/api/runner/TaskManagerStore.js +5 -3
- package/api/runner/TaskManagerStore.js.map +1 -1
- package/api/runner/TaskRunner.d.ts +3 -3
- package/api/runner/TaskRunner.js.map +1 -1
- package/api/runner/abstractions/TaskRunner.d.ts +2 -2
- package/api/service/createService.d.ts +3 -3
- package/api/service/createService.js +5 -10
- package/api/service/createService.js.map +1 -1
- package/api/service/index.d.ts +1 -4
- package/api/service/index.js +1 -12
- package/api/types.d.ts +2 -2
- package/api/types.js.map +1 -1
- package/package.json +26 -20
- package/api/context.d.ts +0 -2
- package/api/context.js +0 -66
- package/api/context.js.map +0 -1
- package/api/graphql/BackgroundTaskSettingsSchema.d.ts +0 -2
- package/api/graphql/BackgroundTaskSettingsSchema.js +0 -84
- package/api/graphql/BackgroundTaskSettingsSchema.js.map +0 -1
- package/api/graphql/index.d.ts +0 -2
- package/api/graphql/index.js +0 -302
- package/api/graphql/index.js.map +0 -1
- package/api/handler/index.d.ts +0 -6
- package/api/handler/index.js +0 -55
- package/api/handler/index.js.map +0 -1
- package/api/handler/register.d.ts +0 -1
- package/api/handler/register.js +0 -15
- package/api/handler/register.js.map +0 -1
- package/api/plugins/TaskServicePlugin.d.ts +0 -19
- package/api/plugins/TaskServicePlugin.js +0 -13
- package/api/plugins/TaskServicePlugin.js.map +0 -1
- package/api/plugins/index.d.ts +0 -1
- package/api/plugins/index.js +0 -1
- package/api/service/EventBridgeEventTransportPlugin.d.ts +0 -16
- package/api/service/EventBridgeEventTransportPlugin.js +0 -52
- package/api/service/EventBridgeEventTransportPlugin.js.map +0 -1
- package/api/service/StepFunctionServicePlugin.d.ts +0 -25
- package/api/service/StepFunctionServicePlugin.js +0 -77
- package/api/service/StepFunctionServicePlugin.js.map +0 -1
- package/api/service/index.js.map +0 -1
|
@@ -3,9 +3,11 @@ import { TaskManager } from "./TaskManager.js";
|
|
|
3
3
|
import { DatabaseResponse, TaskResponse } from "../response/index.js";
|
|
4
4
|
import { TaskManagerStore } from "./TaskManagerStore.js";
|
|
5
5
|
import { getErrorProperties } from "../utils/getErrorProperties.js";
|
|
6
|
-
import { AuthenticatedIdentity } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
6
|
+
import { AuthenticatedIdentity, IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
7
7
|
import { TaskExecutionContext } from "../features/TaskExecutionContext/index.js";
|
|
8
8
|
import { TaskResultStatus } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
9
|
+
import { TasksCrud } from "../TasksCrud.js";
|
|
10
|
+
import { GetTaskDefinitionUseCase } from "../features/GetTaskDefinition/abstractions.js";
|
|
9
11
|
class TaskControl {
|
|
10
12
|
constructor(runner, response, context){
|
|
11
13
|
this.runner = runner;
|
|
@@ -17,10 +19,10 @@ class TaskControl {
|
|
|
17
19
|
let task;
|
|
18
20
|
try {
|
|
19
21
|
task = await this.getTask(taskId);
|
|
20
|
-
this.context.
|
|
22
|
+
this.context.container.resolve(IdentityContext).setIdentity(new AuthenticatedIdentity({
|
|
21
23
|
id: task.createdBy.id,
|
|
22
24
|
type: task.createdBy.type,
|
|
23
|
-
displayName: task.createdBy.displayName
|
|
25
|
+
displayName: task.createdBy.displayName || "",
|
|
24
26
|
context: {
|
|
25
27
|
canAccessTenant: true
|
|
26
28
|
}
|
|
@@ -30,8 +32,8 @@ class TaskControl {
|
|
|
30
32
|
...getErrorProperties(error)
|
|
31
33
|
});
|
|
32
34
|
}
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
+
const definitionResult = this.context.container.resolve(GetTaskDefinitionUseCase).execute(task.definitionId);
|
|
36
|
+
if (definitionResult.isFail()) return this.response.error({
|
|
35
37
|
error: {
|
|
36
38
|
message: `Task "${task.id}" cannot be executed because there is no "${task.definitionId}" definition plugin.`,
|
|
37
39
|
code: "TASK_DEFINITION_ERROR",
|
|
@@ -40,6 +42,7 @@ class TaskControl {
|
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
});
|
|
45
|
+
const definition = definitionResult.value;
|
|
43
46
|
const databaseLogs = true === definition.databaseLogs;
|
|
44
47
|
let taskLog;
|
|
45
48
|
try {
|
|
@@ -117,7 +120,7 @@ class TaskControl {
|
|
|
117
120
|
}
|
|
118
121
|
async getTask(id) {
|
|
119
122
|
try {
|
|
120
|
-
const task = await this.
|
|
123
|
+
const task = await this.context.container.resolve(TasksCrud).getTask(id);
|
|
121
124
|
if (task) return task;
|
|
122
125
|
} catch (ex) {
|
|
123
126
|
throw this.response.error({
|
|
@@ -149,7 +152,7 @@ class TaskControl {
|
|
|
149
152
|
};
|
|
150
153
|
let taskLog = null;
|
|
151
154
|
try {
|
|
152
|
-
taskLog = await this.context.
|
|
155
|
+
taskLog = await this.context.container.resolve(TasksCrud).getLatestLog(task.id);
|
|
153
156
|
} catch (error) {
|
|
154
157
|
if ("NOT_FOUND" !== error.code) throw this.response.error({
|
|
155
158
|
error
|
|
@@ -157,7 +160,7 @@ class TaskControl {
|
|
|
157
160
|
}
|
|
158
161
|
const currentIteration = taskLog?.iteration || 0;
|
|
159
162
|
try {
|
|
160
|
-
return await this.context.
|
|
163
|
+
return await this.context.container.resolve(TasksCrud).createLog(task, {
|
|
161
164
|
executionName: this.response.event.executionName,
|
|
162
165
|
iteration: currentIteration + 1
|
|
163
166
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/runner/TaskControl.js","sources":["../../../src/api/runner/TaskControl.ts"],"sourcesContent":["import type { ITaskEvent } from \"~/api/handler/types.js\";\nimport type { Context, ITask, ITaskDataInput, ITaskLog } from \"~/api/types.js\";\nimport { TaskDataStatus } from \"~/api/types.js\";\nimport type { ITaskControl, ITaskRunner } from \"./abstractions/index.js\";\nimport { TaskManager } from \"./TaskManager.js\";\nimport type { IResponse, IResponseResult } from \"~/api/response/abstractions/index.js\";\nimport { DatabaseResponse, TaskResponse } from \"~/api/response/index.js\";\nimport { TaskManagerStore } from \"./TaskManagerStore.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\nimport { AuthenticatedIdentity } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { TaskExecutionContext } from \"~/api/features/TaskExecutionContext/index.js\";\nimport {\n TaskDefinition,\n TaskResultStatus\n} from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\ninterface IGetTaskLogParams {\n task: ITask;\n databaseLogs: boolean;\n}\n\nexport class TaskControl implements ITaskControl {\n public readonly runner: ITaskRunner;\n public readonly response: IResponse;\n public readonly context: Context;\n\n public constructor(runner: ITaskRunner, response: IResponse, context: Context) {\n this.runner = runner;\n this.context = context;\n this.response = response;\n }\n\n public async run(event: Pick<ITaskEvent, \"webinyTaskId\">): Promise<IResponseResult> {\n const taskId = event.webinyTaskId;\n /**\n * This is the initial getTask idea.\n * We will need to take care of child tasks:\n * * child tasks can be in multiple levels (child task creates a child task, etc...).\n * * child tasks could be executed in parallel.\n */\n let task: ITask<ITaskDataInput>;\n try {\n task = await this.getTask(taskId);\n this.context.security.setIdentity(\n new AuthenticatedIdentity({\n id: task.createdBy.id,\n type: task.createdBy.type,\n displayName: task.createdBy.displayName ?? \"\",\n context: {\n canAccessTenant: true\n }\n })\n );\n } catch (error) {\n /**\n * TODO Refactor error handling.\n */\n // @ts-expect-error\n return this.response.error({\n ...getErrorProperties(error)\n });\n }\n /**\n * Let's get the task definition.\n */\n const definition = this.context.tasks.getDefinition(task.definitionId);\n if (!definition) {\n return this.response.error({\n error: {\n message: `Task \"${task.id}\" cannot be executed because there is no \"${task.definitionId}\" definition plugin.`,\n code: \"TASK_DEFINITION_ERROR\",\n data: {\n definitionId: task.definitionId\n }\n }\n });\n }\n /**\n * Only enable logs if definition explicitly allows them.\n */\n const databaseLogs = definition.databaseLogs === true;\n\n /**\n * As this as a run of the task, we need to create a new log entry.\n */\n let taskLog: ITaskLog;\n try {\n taskLog = await this.getTaskLog({\n task,\n databaseLogs\n });\n } catch (error) {\n return this.response.error({\n error\n });\n }\n /**\n * Make sure that task does not run if it is aborted.\n * This will effectively end the Step Function execution with a \"success\" status.\n */\n if (task.taskStatus === TaskDataStatus.ABORTED) {\n return this.response.aborted();\n }\n /**\n * Do not run if already a success (done).\n */\n //\n else if (task.taskStatus === TaskDataStatus.SUCCESS) {\n return this.response.error({\n error: {\n message: \"Task is already done, cannot run it again.\"\n }\n });\n }\n /**\n * Do not run if already failed.\n */\n //\n else if (task.taskStatus === TaskDataStatus.FAILED) {\n return this.response.error({\n error: {\n message: \"Task has failed, cannot run it again.\"\n }\n });\n }\n\n const store = new TaskManagerStore({\n context: this.context,\n task,\n log: taskLog,\n databaseLogs\n });\n\n // Populate TaskExecutionContext BEFORE executing task\n const executionContext = this.context.container.resolve(TaskExecutionContext);\n executionContext.setStore(store);\n executionContext.setRunner(this.runner);\n executionContext.setTimer(this.runner.timer);\n executionContext.setResponse(new TaskResponse(this.response));\n\n const manager = new TaskManager(this.context, this.response, store);\n\n const databaseResponse = new DatabaseResponse(this.response, store);\n\n try {\n const result = await manager.run(definition);\n\n const responseResult = await databaseResponse.from(result);\n\n // Get the updated task from store (no database read needed - store maintains local cache)\n await this.runEvents(result, definition, store.getTask());\n\n return responseResult;\n } catch (ex) {\n /**\n * We always want to store the error in the task log.\n */\n return await databaseResponse.from(\n this.response.error({\n error: {\n message: ex.message,\n code: ex.code || \"TASK_ERROR\",\n stack: ex.stack,\n data: {\n ...ex.data,\n input: task.input\n }\n }\n })\n );\n } finally {\n // Clear execution context after task completes\n executionContext.clear();\n }\n }\n\n private async runEvents(\n result: IResponseResult,\n definition: TaskDefinition.Runnable,\n task: ITask\n ): Promise<void> {\n if (result.status === TaskResultStatus.ERROR && definition.onError) {\n try {\n await definition.onError({ task });\n } catch (ex) {\n console.error(`Error executing onError hook for task \"${task.id}\".`);\n console.log(getErrorProperties(ex));\n }\n } else if (result.status === TaskResultStatus.DONE && definition.onDone) {\n try {\n await definition.onDone({ task });\n } catch (ex) {\n console.error(`Error executing onDone hook for task \"${task.id}\".`);\n console.log(getErrorProperties(ex));\n }\n }\n }\n\n private async getTask<T extends TaskDefinition.TaskInput>(id: string): Promise<ITask<T>> {\n try {\n const task = await this.runner.context.tasks.getTask<T>(id);\n if (task) {\n return task;\n }\n } catch (ex) {\n throw this.response.error({\n error: {\n message: ex.message,\n code: ex.code || \"TASK_ERROR\",\n stack: ex.stack,\n data: ex.data\n }\n });\n }\n throw this.response.error({\n error: {\n message: `Task \"${id}\" cannot be executed because it does not exist.`,\n code: \"TASK_NOT_FOUND\"\n }\n });\n }\n\n private async getTaskLog(params: IGetTaskLogParams): Promise<ITaskLog> {\n const { task, databaseLogs } = params;\n /**\n * If logs are disabled, let's return a mocked one.\n */\n if (!databaseLogs) {\n return {\n id: `${task.id}-log`,\n createdOn: task.createdOn,\n createdBy: task.createdBy,\n executionName: task.executionName,\n task: task.id,\n iteration: task.iterations,\n items: []\n };\n }\n let taskLog: ITaskLog | null = null;\n /**\n * First we are trying to get existing latest log.\n */\n try {\n taskLog = await this.context.tasks.getLatestLog(task.id);\n } catch (error) {\n /**\n * If error is not the NotFoundError, we need to throw it.\n */\n if (error.code !== \"NOT_FOUND\") {\n throw this.response.error({\n error\n });\n }\n /**\n * Otherwise just continue and create a new log.\n */\n }\n\n const currentIteration = taskLog?.iteration || 0;\n\n try {\n return await this.context.tasks.createLog(task, {\n executionName: this.response.event.executionName,\n iteration: currentIteration + 1\n });\n } catch (error) {\n throw this.response.error({\n error\n });\n }\n }\n}\n"],"names":["TaskControl","runner","response","context","event","taskId","task","AuthenticatedIdentity","error","getErrorProperties","definition","databaseLogs","taskLog","TaskDataStatus","store","TaskManagerStore","executionContext","TaskExecutionContext","TaskResponse","manager","TaskManager","databaseResponse","DatabaseResponse","result","responseResult","ex","TaskResultStatus","console","id","params","currentIteration"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api/runner/TaskControl.js","sources":["../../../src/api/runner/TaskControl.ts"],"sourcesContent":["import type { ITaskEvent } from \"~/api/handler/types.js\";\nimport type { Context, ITask, ITaskDataInput, ITaskLog } from \"~/api/types.js\";\nimport { TaskDataStatus } from \"~/api/types.js\";\nimport type { ITaskControl, ITaskRunner } from \"./abstractions/index.js\";\nimport { TaskManager } from \"./TaskManager.js\";\nimport type { IResponse, IResponseResult } from \"~/api/response/abstractions/index.js\";\nimport { DatabaseResponse, TaskResponse } from \"~/api/response/index.js\";\nimport { TaskManagerStore } from \"./TaskManagerStore.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\nimport {\n AuthenticatedIdentity,\n IdentityContext\n} from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { TaskExecutionContext } from \"~/api/features/TaskExecutionContext/index.js\";\nimport {\n TaskDefinition,\n TaskResultStatus\n} from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { TasksCrud } from \"~/api/TasksCrud.js\";\nimport { GetTaskDefinitionUseCase } from \"~/api/features/GetTaskDefinition/abstractions.js\";\n\ninterface IGetTaskLogParams {\n task: ITask;\n databaseLogs: boolean;\n}\n\nexport class TaskControl implements ITaskControl {\n public readonly runner: ITaskRunner;\n public readonly response: IResponse;\n public readonly context: Context;\n\n public constructor(runner: ITaskRunner, response: IResponse, context: Context) {\n this.runner = runner;\n this.context = context;\n this.response = response;\n }\n\n public async run(event: Pick<ITaskEvent, \"webinyTaskId\">): Promise<IResponseResult> {\n const taskId = event.webinyTaskId;\n /**\n * This is the initial getTask idea.\n * We will need to take care of child tasks:\n * * child tasks can be in multiple levels (child task creates a child task, etc...).\n * * child tasks could be executed in parallel.\n */\n let task: ITask<ITaskDataInput>;\n try {\n task = await this.getTask(taskId);\n this.context.container.resolve(IdentityContext).setIdentity(\n new AuthenticatedIdentity({\n id: task.createdBy.id,\n type: task.createdBy.type,\n displayName: task.createdBy.displayName || \"\",\n context: {\n canAccessTenant: true\n }\n })\n );\n } catch (error) {\n /**\n * TODO Refactor error handling.\n */\n // @ts-expect-error\n return this.response.error({\n ...getErrorProperties(error)\n });\n }\n /**\n * Let's get the task definition.\n */\n const definitionResult = this.context.container\n .resolve(GetTaskDefinitionUseCase)\n .execute(task.definitionId);\n if (definitionResult.isFail()) {\n return this.response.error({\n error: {\n message: `Task \"${task.id}\" cannot be executed because there is no \"${task.definitionId}\" definition plugin.`,\n code: \"TASK_DEFINITION_ERROR\",\n data: {\n definitionId: task.definitionId\n }\n }\n });\n }\n const definition = definitionResult.value;\n /**\n * Only enable logs if definition explicitly allows them.\n */\n const databaseLogs = definition.databaseLogs === true;\n\n /**\n * As this as a run of the task, we need to create a new log entry.\n */\n let taskLog: ITaskLog;\n try {\n taskLog = await this.getTaskLog({\n task,\n databaseLogs\n });\n } catch (error) {\n return this.response.error({\n error\n });\n }\n /**\n * Make sure that task does not run if it is aborted.\n * This will effectively end the Step Function execution with a \"success\" status.\n */\n if (task.taskStatus === TaskDataStatus.ABORTED) {\n return this.response.aborted();\n }\n /**\n * Do not run if already a success (done).\n */\n //\n else if (task.taskStatus === TaskDataStatus.SUCCESS) {\n return this.response.error({\n error: {\n message: \"Task is already done, cannot run it again.\"\n }\n });\n }\n /**\n * Do not run if already failed.\n */\n //\n else if (task.taskStatus === TaskDataStatus.FAILED) {\n return this.response.error({\n error: {\n message: \"Task has failed, cannot run it again.\"\n }\n });\n }\n\n const store = new TaskManagerStore({\n context: this.context,\n task,\n log: taskLog,\n databaseLogs\n });\n\n // Populate TaskExecutionContext BEFORE executing task\n const executionContext = this.context.container.resolve(TaskExecutionContext);\n executionContext.setStore(store);\n executionContext.setRunner(this.runner);\n executionContext.setTimer(this.runner.timer);\n executionContext.setResponse(new TaskResponse(this.response));\n\n const manager = new TaskManager(this.context, this.response, store);\n\n const databaseResponse = new DatabaseResponse(this.response, store);\n\n try {\n const result = await manager.run(definition);\n\n const responseResult = await databaseResponse.from(result);\n\n // Get the updated task from store (no database read needed - store maintains local cache)\n await this.runEvents(result, definition, store.getTask());\n\n return responseResult;\n } catch (ex) {\n /**\n * We always want to store the error in the task log.\n */\n return await databaseResponse.from(\n this.response.error({\n error: {\n message: ex.message,\n code: ex.code || \"TASK_ERROR\",\n stack: ex.stack,\n data: {\n ...ex.data,\n input: task.input\n }\n }\n })\n );\n } finally {\n // Clear execution context after task completes\n executionContext.clear();\n }\n }\n\n private async runEvents(\n result: IResponseResult,\n definition: TaskDefinition.Runnable,\n task: ITask\n ): Promise<void> {\n if (result.status === TaskResultStatus.ERROR && definition.onError) {\n try {\n await definition.onError({ task });\n } catch (ex) {\n console.error(`Error executing onError hook for task \"${task.id}\".`);\n console.log(getErrorProperties(ex));\n }\n } else if (result.status === TaskResultStatus.DONE && definition.onDone) {\n try {\n await definition.onDone({ task });\n } catch (ex) {\n console.error(`Error executing onDone hook for task \"${task.id}\".`);\n console.log(getErrorProperties(ex));\n }\n }\n }\n\n private async getTask<T extends TaskDefinition.TaskInput>(id: string): Promise<ITask<T>> {\n try {\n const task = await this.context.container.resolve(TasksCrud).getTask<T>(id);\n if (task) {\n return task;\n }\n } catch (ex) {\n throw this.response.error({\n error: {\n message: ex.message,\n code: ex.code || \"TASK_ERROR\",\n stack: ex.stack,\n data: ex.data\n }\n });\n }\n throw this.response.error({\n error: {\n message: `Task \"${id}\" cannot be executed because it does not exist.`,\n code: \"TASK_NOT_FOUND\"\n }\n });\n }\n\n private async getTaskLog(params: IGetTaskLogParams): Promise<ITaskLog> {\n const { task, databaseLogs } = params;\n /**\n * If logs are disabled, let's return a mocked one.\n */\n if (!databaseLogs) {\n return {\n id: `${task.id}-log`,\n createdOn: task.createdOn,\n createdBy: task.createdBy,\n executionName: task.executionName,\n task: task.id,\n iteration: task.iterations,\n items: []\n };\n }\n let taskLog: ITaskLog | null = null;\n /**\n * First we are trying to get existing latest log.\n */\n try {\n taskLog = await this.context.container.resolve(TasksCrud).getLatestLog(task.id);\n } catch (error) {\n /**\n * If error is not the NotFoundError, we need to throw it.\n */\n if (error.code !== \"NOT_FOUND\") {\n throw this.response.error({\n error\n });\n }\n /**\n * Otherwise just continue and create a new log.\n */\n }\n\n const currentIteration = taskLog?.iteration || 0;\n\n try {\n return await this.context.container.resolve(TasksCrud).createLog(task, {\n executionName: this.response.event.executionName,\n iteration: currentIteration + 1\n });\n } catch (error) {\n throw this.response.error({\n error\n });\n }\n }\n}\n"],"names":["TaskControl","runner","response","context","event","taskId","task","IdentityContext","AuthenticatedIdentity","error","getErrorProperties","definitionResult","GetTaskDefinitionUseCase","definition","databaseLogs","taskLog","TaskDataStatus","store","TaskManagerStore","executionContext","TaskExecutionContext","TaskResponse","manager","TaskManager","databaseResponse","DatabaseResponse","result","responseResult","ex","TaskResultStatus","console","id","TasksCrud","params","currentIteration"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { TaskDataStatus } from "../types.js";
|
|
|
2
2
|
import { getErrorProperties } from "../utils/getErrorProperties.js";
|
|
3
3
|
import { TaskResultStatus } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
4
4
|
import { TaskController } from "@webiny/api-core/features/task/TaskController/abstractions.js";
|
|
5
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
|
|
5
6
|
class TaskManager {
|
|
6
7
|
constructor(context, response, store){
|
|
7
8
|
this.context = context;
|
|
@@ -53,7 +54,7 @@ class TaskManager {
|
|
|
53
54
|
try {
|
|
54
55
|
const input = structuredClone(this.store.getInput());
|
|
55
56
|
const controller = this.context.container.resolve(TaskController);
|
|
56
|
-
result = await this.context.
|
|
57
|
+
result = await this.context.container.resolve(IdentityContext).withoutAuthorization(async ()=>await definition.run({
|
|
57
58
|
input,
|
|
58
59
|
controller
|
|
59
60
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/runner/TaskManager.js","sources":["../../../src/api/runner/TaskManager.ts"],"sourcesContent":["import type { ITaskManager, ITaskManagerStorePrivate } from \"./abstractions/index.js\";\nimport type { Context } from \"~/api/types.js\";\nimport { TaskDataStatus } from \"~/api/types.js\";\nimport type { IResponse, IResponseResult } from \"~/api/response/abstractions/index.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\nimport {\n TaskDefinition,\n TaskResultStatus\n} from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { TaskController } from \"@webiny/api-core/features/task/TaskController/abstractions.js\";\n\nexport class TaskManager implements ITaskManager {\n private readonly context: Context;\n private readonly response: IResponse;\n private readonly store: ITaskManagerStorePrivate;\n\n public constructor(context: Context, response: IResponse, store: ITaskManagerStorePrivate) {\n this.context = context;\n this.response = response;\n this.store = store;\n }\n\n public async run(definition: TaskDefinition.Runnable): Promise<IResponseResult> {\n /**\n * If task was aborted, do not run it again, return as it was done.\n */\n if (this.store.getStatus() === TaskDataStatus.ABORTED) {\n return this.response.aborted();\n }\n /**\n * If the task status is pending, update it to running and add a log.\n */\n //\n else if (this.store.getStatus() === TaskDataStatus.PENDING) {\n try {\n await this.store.updateTask({\n taskStatus: TaskDataStatus.RUNNING,\n startedOn: new Date().toISOString(),\n executionName: this.response.event.executionName,\n iterations: 1\n });\n await this.store.save();\n } catch (error) {\n return this.response.error({\n error\n });\n }\n }\n /**\n * We do not want to run the task indefinitely.\n * If the task has reached the max iterations, we will stop it and execute the onMaxIterations handler, if any.\n */\n //\n else if (this.store.getTask().iterations >= definition.maxIterations) {\n try {\n if (definition.onMaxIterations) {\n await definition.onMaxIterations({\n task: this.store.getTask()\n });\n }\n return this.response.error({\n error: {\n message: \"Task reached max iterations.\"\n }\n });\n } catch (ex) {\n return this.response.error({\n error: {\n message: \"Failed to execute onMaxIterations handler.\",\n data: getErrorProperties(ex)\n }\n });\n }\n }\n /**\n * Always update the task iteration.\n */\n //\n else {\n try {\n await this.store.updateTask(task => {\n return {\n iterations: task.iterations + 1\n };\n });\n } catch (error) {\n return this.response.error({\n error\n });\n }\n }\n\n let result: TaskDefinition.Result;\n\n try {\n const input = structuredClone(this.store.getInput());\n const controller = this.context.container.resolve(TaskController);\n /**\n * We always run the task without authorization because we are running a task without a user - nothing to authorize against.\n */\n result = await this.context.
|
|
1
|
+
{"version":3,"file":"api/runner/TaskManager.js","sources":["../../../src/api/runner/TaskManager.ts"],"sourcesContent":["import type { ITaskManager, ITaskManagerStorePrivate } from \"./abstractions/index.js\";\nimport type { Context } from \"~/api/types.js\";\nimport { TaskDataStatus } from \"~/api/types.js\";\nimport type { IResponse, IResponseResult } from \"~/api/response/abstractions/index.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\nimport {\n TaskDefinition,\n TaskResultStatus\n} from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { TaskController } from \"@webiny/api-core/features/task/TaskController/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/abstractions.js\";\n\nexport class TaskManager implements ITaskManager {\n private readonly context: Context;\n private readonly response: IResponse;\n private readonly store: ITaskManagerStorePrivate;\n\n public constructor(context: Context, response: IResponse, store: ITaskManagerStorePrivate) {\n this.context = context;\n this.response = response;\n this.store = store;\n }\n\n public async run(definition: TaskDefinition.Runnable): Promise<IResponseResult> {\n /**\n * If task was aborted, do not run it again, return as it was done.\n */\n if (this.store.getStatus() === TaskDataStatus.ABORTED) {\n return this.response.aborted();\n }\n /**\n * If the task status is pending, update it to running and add a log.\n */\n //\n else if (this.store.getStatus() === TaskDataStatus.PENDING) {\n try {\n await this.store.updateTask({\n taskStatus: TaskDataStatus.RUNNING,\n startedOn: new Date().toISOString(),\n executionName: this.response.event.executionName,\n iterations: 1\n });\n await this.store.save();\n } catch (error) {\n return this.response.error({\n error\n });\n }\n }\n /**\n * We do not want to run the task indefinitely.\n * If the task has reached the max iterations, we will stop it and execute the onMaxIterations handler, if any.\n */\n //\n else if (this.store.getTask().iterations >= definition.maxIterations) {\n try {\n if (definition.onMaxIterations) {\n await definition.onMaxIterations({\n task: this.store.getTask()\n });\n }\n return this.response.error({\n error: {\n message: \"Task reached max iterations.\"\n }\n });\n } catch (ex) {\n return this.response.error({\n error: {\n message: \"Failed to execute onMaxIterations handler.\",\n data: getErrorProperties(ex)\n }\n });\n }\n }\n /**\n * Always update the task iteration.\n */\n //\n else {\n try {\n await this.store.updateTask(task => {\n return {\n iterations: task.iterations + 1\n };\n });\n } catch (error) {\n return this.response.error({\n error\n });\n }\n }\n\n let result: TaskDefinition.Result;\n\n try {\n const input = structuredClone(this.store.getInput());\n const controller = this.context.container.resolve(TaskController);\n /**\n * We always run the task without authorization because we are running a task without a user - nothing to authorize against.\n */\n result = await this.context.container\n .resolve(IdentityContext)\n .withoutAuthorization(async () => {\n return await definition.run({\n input,\n controller\n });\n });\n } catch (ex) {\n return this.response.error({\n error: getErrorProperties(ex)\n });\n }\n\n // Convert TaskDefinition.Result to IResponseResult\n if (result.status === TaskResultStatus.CONTINUE) {\n return this.response.continue({\n input: result.input,\n wait: result.wait\n });\n } else if (result.status === TaskResultStatus.ERROR) {\n return this.response.error({\n error: result.error\n });\n } else if (result.status === TaskResultStatus.ABORTED) {\n return this.response.aborted();\n }\n return this.response.done({\n message: result.message,\n output: result.output\n });\n }\n}\n"],"names":["TaskManager","context","response","store","definition","TaskDataStatus","Date","error","ex","getErrorProperties","task","result","input","structuredClone","controller","TaskController","IdentityContext","TaskResultStatus"],"mappings":";;;;;AAYO,MAAMA;IAKT,YAAmBC,OAAgB,EAAEC,QAAmB,EAAEC,KAA+B,CAAE;QACvF,IAAI,CAAC,OAAO,GAAGF;QACf,IAAI,CAAC,QAAQ,GAAGC;QAChB,IAAI,CAAC,KAAK,GAAGC;IACjB;IAEA,MAAa,IAAIC,UAAmC,EAA4B;QAI5E,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,OAAOC,eAAe,OAAO,EACjD,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO;QAM3B,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,OAAOA,eAAe,OAAO,EACtD,IAAI;YACA,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;gBACxB,YAAYA,eAAe,OAAO;gBAClC,WAAW,IAAIC,OAAO,WAAW;gBACjC,eAAe,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa;gBAChD,YAAY;YAChB;YACA,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI;QACzB,EAAE,OAAOC,OAAO;YACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvBA;YACJ;QACJ;aAOC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,UAAU,IAAIH,WAAW,aAAa,EAChE,IAAI;YACA,IAAIA,WAAW,eAAe,EAC1B,MAAMA,WAAW,eAAe,CAAC;gBAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO;YAC5B;YAEJ,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvB,OAAO;oBACH,SAAS;gBACb;YACJ;QACJ,EAAE,OAAOI,IAAI;YACT,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvB,OAAO;oBACH,SAAS;oBACT,MAAMC,mBAAmBD;gBAC7B;YACJ;QACJ;aAOA,IAAI;YACA,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAACE,CAAAA,OACjB;oBACH,YAAYA,KAAK,UAAU,GAAG;gBAClC;QAER,EAAE,OAAOH,OAAO;YACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvBA;YACJ;QACJ;QAGJ,IAAII;QAEJ,IAAI;YACA,MAAMC,QAAQC,gBAAgB,IAAI,CAAC,KAAK,CAAC,QAAQ;YACjD,MAAMC,aAAa,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAACC;YAIlDJ,SAAS,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAChC,OAAO,CAACK,iBACR,oBAAoB,CAAC,UACX,MAAMZ,WAAW,GAAG,CAAC;oBACxBQ;oBACAE;gBACJ;QAEZ,EAAE,OAAON,IAAI;YACT,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvB,OAAOC,mBAAmBD;YAC9B;QACJ;QAGA,IAAIG,OAAO,MAAM,KAAKM,iBAAiB,QAAQ,EAC3C,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC1B,OAAON,OAAO,KAAK;YACnB,MAAMA,OAAO,IAAI;QACrB;QACG,IAAIA,OAAO,MAAM,KAAKM,iBAAiB,KAAK,EAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAON,OAAO,KAAK;QACvB;QACG,IAAIA,OAAO,MAAM,KAAKM,iBAAiB,OAAO,EACjD,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO;QAEhC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YACtB,SAASN,OAAO,OAAO;YACvB,QAAQA,OAAO,MAAM;QACzB;IACJ;AACJ"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { ITask, ITaskDataInput, ITaskLog, ITaskManagerStoreInfoLog, ITaskManagerStorePrivate, ITaskManagerStoreSetOutputOptions, ITaskManagerStoreUpdateTaskInputOptions, ITaskManagerStoreUpdateTaskOptions,
|
|
1
|
+
import type { ITask, ITaskDataInput, ITaskLog, ITaskManagerStoreInfoLog, ITaskManagerStorePrivate, ITaskManagerStoreSetOutputOptions, ITaskManagerStoreUpdateTaskInputOptions, ITaskManagerStoreUpdateTaskOptions, TaskDataStatus } from "../../api/types.js";
|
|
2
|
+
import type { Container } from "@webiny/feature/api";
|
|
2
3
|
import type { ITaskManagerStoreAddLogOptions, ITaskManagerStoreErrorLog, ITaskManagerStoreUpdateTaskInputParam, ITaskManagerStoreUpdateTaskParams } from "./abstractions/index.js";
|
|
3
4
|
import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
4
5
|
export interface TaskManagerStoreContext {
|
|
5
|
-
|
|
6
|
+
container: Container;
|
|
6
7
|
}
|
|
7
8
|
export interface ITaskManagerStoreParams {
|
|
8
9
|
context: TaskManagerStoreContext;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TasksCrud } from "../TasksCrud.js";
|
|
1
2
|
import { TaskLogItemType } from "../types.js";
|
|
2
3
|
import deep_equal from "deep-equal";
|
|
3
4
|
import { getObjectProperties } from "../utils/getObjectProperties.js";
|
|
@@ -29,7 +30,7 @@ class TaskManagerStore {
|
|
|
29
30
|
parentId: this.task.id
|
|
30
31
|
};
|
|
31
32
|
if (definitionId) where.definitionId = definitionId;
|
|
32
|
-
const result = await this.context.
|
|
33
|
+
const result = await this.context.container.resolve(TasksCrud).listTasks({
|
|
33
34
|
where,
|
|
34
35
|
sort: [
|
|
35
36
|
"createdOn_ASC"
|
|
@@ -99,9 +100,10 @@ class TaskManagerStore {
|
|
|
99
100
|
await this.save();
|
|
100
101
|
}
|
|
101
102
|
async save() {
|
|
102
|
-
|
|
103
|
+
const tasksCrud = this.context.container.resolve(TasksCrud);
|
|
104
|
+
if (this.taskUpdater.isDirty()) this.task = await tasksCrud.updateTask(this.task.id, this.taskUpdater.fetch());
|
|
103
105
|
if (!this.databaseLogs) return;
|
|
104
|
-
if (this.taskLogUpdater.isDirty()) this.taskLog = await
|
|
106
|
+
if (this.taskLogUpdater.isDirty()) this.taskLog = await tasksCrud.updateLog(this.taskLog.id, this.taskLogUpdater.fetch());
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
export { TaskManagerStore };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/runner/TaskManagerStore.js","sources":["../../../src/api/runner/TaskManagerStore.ts"],"sourcesContent":["import type {\n IListTaskParamsWhere,\n ITask,\n ITaskDataInput,\n ITaskLog,\n ITaskManagerStoreInfoLog,\n ITaskManagerStorePrivate,\n ITaskManagerStoreSetOutputOptions,\n ITaskManagerStoreUpdateTaskInputOptions,\n ITaskManagerStoreUpdateTaskOptions,\n ITasksContextObject,\n TaskDataStatus\n} from \"~/api/types.js\";\nimport { TaskLogItemType } from \"~/api/types.js\";\nimport type {\n ITaskManagerStoreAddLogOptions,\n ITaskManagerStoreErrorLog,\n ITaskManagerStoreUpdateTaskInputParam,\n ITaskManagerStoreUpdateTaskParams\n} from \"./abstractions/index.js\";\n/**\n * Package deep-equal does not have types.\n */\nimport deepEqual from \"deep-equal\";\nimport { getObjectProperties } from \"~/api/utils/getObjectProperties.js\";\nimport { ObjectUpdater } from \"~/api/utils/ObjectUpdater.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nconst getInput = <T extends ITaskDataInput = ITaskDataInput>(\n originalInput: T,\n input: ITaskManagerStoreUpdateTaskInputParam<T>\n): T => {\n if (typeof input === \"function\") {\n return input(originalInput);\n }\n return {\n ...originalInput,\n ...input\n };\n};\n\nexport interface TaskManagerStoreContext {\n tasks: Pick<ITasksContextObject, \"updateTask\" | \"updateLog\" | \"listTasks\">;\n}\n\nexport interface ITaskManagerStoreParams {\n context: TaskManagerStoreContext;\n task: ITask;\n log: ITaskLog;\n databaseLogs: boolean;\n}\n\nexport class TaskManagerStore<\n T extends ITaskDataInput = ITaskDataInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n> implements ITaskManagerStorePrivate<T, O> {\n private readonly context: TaskManagerStoreContext;\n private task: ITask<T, O>;\n private taskLog: ITaskLog;\n private readonly databaseLogs: boolean;\n\n private readonly taskUpdater = new ObjectUpdater<ITask<T, O>>();\n private readonly taskLogUpdater = new ObjectUpdater<ITaskLog>();\n\n public constructor(params: ITaskManagerStoreParams) {\n this.context = params.context;\n this.task = params.task as ITask<T, O>;\n this.taskLog = params.log;\n this.databaseLogs = params.databaseLogs === true;\n }\n\n public getStatus(): TaskDataStatus {\n return this.task.taskStatus;\n }\n\n public getTask(): ITask<T, O> {\n return this.task as ITask<T, O>;\n }\n\n public async listChildTasks<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(definitionId?: string): Promise<ITask<I, O>[]> {\n const where: IListTaskParamsWhere = {\n parentId: this.task.id\n };\n if (definitionId) {\n where.definitionId = definitionId;\n }\n const result = await this.context.tasks.listTasks<I, O>({\n where,\n sort: [\"createdOn_ASC\"],\n limit: 1000000\n });\n return result.items;\n }\n\n public async updateTask(\n param: ITaskManagerStoreUpdateTaskParams<T, O>,\n options?: ITaskManagerStoreUpdateTaskOptions\n ): Promise<void> {\n const data = typeof param === \"function\" ? param(this.task) : param;\n\n /**\n * No need to update if nothing changed.\n */\n if (deepEqual(data, this.task)) {\n return;\n }\n\n this.taskUpdater.update(data);\n\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public async updateInput(\n param: ITaskManagerStoreUpdateTaskInputParam<T>,\n options?: ITaskManagerStoreUpdateTaskInputOptions\n ): Promise<void> {\n const input = getInput<T>(this.task.input, param);\n\n /**\n * No need to update if nothing changed.\n */\n if (deepEqual(input, this.task.input)) {\n return;\n }\n this.taskUpdater.update({\n input: input as T\n });\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public getInput(): T {\n return this.task.input as T;\n }\n\n public async updateOutput(\n values: Partial<O>,\n options: ITaskManagerStoreSetOutputOptions = {}\n ): Promise<void> {\n this.taskUpdater.update({\n output: values as O\n });\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public getOutput(): O {\n return this.task.output as O;\n }\n /**\n * Currently the methods throws an error if something goes wrong during the database update.\n * TODO: Maybe we should wrap it into try/catch and return error if any?\n */\n public async addInfoLog(\n log: ITaskManagerStoreInfoLog,\n options?: ITaskManagerStoreAddLogOptions\n ): Promise<void> {\n if (!this.databaseLogs) {\n return;\n }\n this.taskLogUpdater.update({\n items: [\n {\n message: log.message,\n data: log.data,\n type: TaskLogItemType.INFO,\n createdOn: new Date().toISOString()\n }\n ]\n });\n if (options?.save === false) {\n return;\n }\n\n await this.save();\n }\n /**\n * Currently the methods throws an error if something goes wrong during the database update.\n * TODO: Maybe we should wrap it into try/catch and return error if any?\n */\n public async addErrorLog(\n log: ITaskManagerStoreErrorLog,\n options?: ITaskManagerStoreAddLogOptions\n ): Promise<void> {\n if (!this.databaseLogs) {\n return;\n }\n /**\n * Let's log the error to the console as well.\n */\n console.error(log.error);\n /**\n * Then update the log object.\n */\n this.taskLogUpdater.update({\n items: [\n {\n message: log.message,\n error: log.error instanceof Error ? getObjectProperties(log.error) : log.error,\n type: TaskLogItemType.ERROR,\n createdOn: new Date().toISOString()\n }\n ]\n });\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public async save(): Promise<void> {\n /**\n * Update both task and the log, if anything to update.\n */\n if (this.taskUpdater.isDirty()) {\n this.task = await this.context.tasks.updateTask<T, O>(\n this.task.id,\n this.taskUpdater.fetch()\n );\n }\n if (!this.databaseLogs) {\n return;\n }\n if (this.taskLogUpdater.isDirty()) {\n this.taskLog = await this.context.tasks.updateLog(\n this.taskLog.id,\n this.taskLogUpdater.fetch()\n );\n }\n }\n}\n"],"names":["getInput","originalInput","input","TaskManagerStore","params","ObjectUpdater","definitionId","where","result","param","options","data","deepEqual","values","log","TaskLogItemType","Date","console","Error","getObjectProperties"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api/runner/TaskManagerStore.js","sources":["../../../src/api/runner/TaskManagerStore.ts"],"sourcesContent":["import type {\n IListTaskParamsWhere,\n ITask,\n ITaskDataInput,\n ITaskLog,\n ITaskManagerStoreInfoLog,\n ITaskManagerStorePrivate,\n ITaskManagerStoreSetOutputOptions,\n ITaskManagerStoreUpdateTaskInputOptions,\n ITaskManagerStoreUpdateTaskOptions,\n TaskDataStatus\n} from \"~/api/types.js\";\nimport { TasksCrud } from \"~/api/TasksCrud.js\";\nimport type { Container } from \"@webiny/feature/api\";\nimport { TaskLogItemType } from \"~/api/types.js\";\nimport type {\n ITaskManagerStoreAddLogOptions,\n ITaskManagerStoreErrorLog,\n ITaskManagerStoreUpdateTaskInputParam,\n ITaskManagerStoreUpdateTaskParams\n} from \"./abstractions/index.js\";\n/**\n * Package deep-equal does not have types.\n */\nimport deepEqual from \"deep-equal\";\nimport { getObjectProperties } from \"~/api/utils/getObjectProperties.js\";\nimport { ObjectUpdater } from \"~/api/utils/ObjectUpdater.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nconst getInput = <T extends ITaskDataInput = ITaskDataInput>(\n originalInput: T,\n input: ITaskManagerStoreUpdateTaskInputParam<T>\n): T => {\n if (typeof input === \"function\") {\n return input(originalInput);\n }\n return {\n ...originalInput,\n ...input\n };\n};\n\nexport interface TaskManagerStoreContext {\n container: Container;\n}\n\nexport interface ITaskManagerStoreParams {\n context: TaskManagerStoreContext;\n task: ITask;\n log: ITaskLog;\n databaseLogs: boolean;\n}\n\nexport class TaskManagerStore<\n T extends ITaskDataInput = ITaskDataInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n> implements ITaskManagerStorePrivate<T, O> {\n private readonly context: TaskManagerStoreContext;\n private task: ITask<T, O>;\n private taskLog: ITaskLog;\n private readonly databaseLogs: boolean;\n\n private readonly taskUpdater = new ObjectUpdater<ITask<T, O>>();\n private readonly taskLogUpdater = new ObjectUpdater<ITaskLog>();\n\n public constructor(params: ITaskManagerStoreParams) {\n this.context = params.context;\n this.task = params.task as ITask<T, O>;\n this.taskLog = params.log;\n this.databaseLogs = params.databaseLogs === true;\n }\n\n public getStatus(): TaskDataStatus {\n return this.task.taskStatus;\n }\n\n public getTask(): ITask<T, O> {\n return this.task as ITask<T, O>;\n }\n\n public async listChildTasks<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(definitionId?: string): Promise<ITask<I, O>[]> {\n const where: IListTaskParamsWhere = {\n parentId: this.task.id\n };\n if (definitionId) {\n where.definitionId = definitionId;\n }\n const result = await this.context.container.resolve(TasksCrud).listTasks<I, O>({\n where,\n sort: [\"createdOn_ASC\"],\n limit: 1000000\n });\n return result.items;\n }\n\n public async updateTask(\n param: ITaskManagerStoreUpdateTaskParams<T, O>,\n options?: ITaskManagerStoreUpdateTaskOptions\n ): Promise<void> {\n const data = typeof param === \"function\" ? param(this.task) : param;\n\n /**\n * No need to update if nothing changed.\n */\n if (deepEqual(data, this.task)) {\n return;\n }\n\n this.taskUpdater.update(data);\n\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public async updateInput(\n param: ITaskManagerStoreUpdateTaskInputParam<T>,\n options?: ITaskManagerStoreUpdateTaskInputOptions\n ): Promise<void> {\n const input = getInput<T>(this.task.input, param);\n\n /**\n * No need to update if nothing changed.\n */\n if (deepEqual(input, this.task.input)) {\n return;\n }\n this.taskUpdater.update({\n input: input as T\n });\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public getInput(): T {\n return this.task.input as T;\n }\n\n public async updateOutput(\n values: Partial<O>,\n options: ITaskManagerStoreSetOutputOptions = {}\n ): Promise<void> {\n this.taskUpdater.update({\n output: values as O\n });\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public getOutput(): O {\n return this.task.output as O;\n }\n /**\n * Currently the methods throws an error if something goes wrong during the database update.\n * TODO: Maybe we should wrap it into try/catch and return error if any?\n */\n public async addInfoLog(\n log: ITaskManagerStoreInfoLog,\n options?: ITaskManagerStoreAddLogOptions\n ): Promise<void> {\n if (!this.databaseLogs) {\n return;\n }\n this.taskLogUpdater.update({\n items: [\n {\n message: log.message,\n data: log.data,\n type: TaskLogItemType.INFO,\n createdOn: new Date().toISOString()\n }\n ]\n });\n if (options?.save === false) {\n return;\n }\n\n await this.save();\n }\n /**\n * Currently the methods throws an error if something goes wrong during the database update.\n * TODO: Maybe we should wrap it into try/catch and return error if any?\n */\n public async addErrorLog(\n log: ITaskManagerStoreErrorLog,\n options?: ITaskManagerStoreAddLogOptions\n ): Promise<void> {\n if (!this.databaseLogs) {\n return;\n }\n /**\n * Let's log the error to the console as well.\n */\n console.error(log.error);\n /**\n * Then update the log object.\n */\n this.taskLogUpdater.update({\n items: [\n {\n message: log.message,\n error: log.error instanceof Error ? getObjectProperties(log.error) : log.error,\n type: TaskLogItemType.ERROR,\n createdOn: new Date().toISOString()\n }\n ]\n });\n if (options?.save === false) {\n return;\n }\n await this.save();\n }\n\n public async save(): Promise<void> {\n /**\n * Update both task and the log, if anything to update.\n */\n const tasksCrud = this.context.container.resolve(TasksCrud);\n if (this.taskUpdater.isDirty()) {\n this.task = await tasksCrud.updateTask<T, O>(this.task.id, this.taskUpdater.fetch());\n }\n if (!this.databaseLogs) {\n return;\n }\n if (this.taskLogUpdater.isDirty()) {\n this.taskLog = await tasksCrud.updateLog(this.taskLog.id, this.taskLogUpdater.fetch());\n }\n }\n}\n"],"names":["getInput","originalInput","input","TaskManagerStore","params","ObjectUpdater","definitionId","where","result","TasksCrud","param","options","data","deepEqual","values","log","TaskLogItemType","Date","console","Error","getObjectProperties","tasksCrud"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import type { ITaskRawEvent } from "../../api/handler/types.js";
|
|
|
2
2
|
import type { ITaskEventValidation, ITaskRunner } from "./abstractions/index.js";
|
|
3
3
|
import type { Context } from "../../api/types.js";
|
|
4
4
|
import type { IResponseResult } from "../../api/response/abstractions/index.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { Timer } from "../../api/abstractions/Timer.js";
|
|
6
6
|
export declare class TaskRunner<C extends Context = Context> implements ITaskRunner<C> {
|
|
7
7
|
/**
|
|
8
8
|
* When DI is introduced, these will get injected.
|
|
@@ -13,12 +13,12 @@ export declare class TaskRunner<C extends Context = Context> implements ITaskRun
|
|
|
13
13
|
* Follow the same example for the rest of the properties.
|
|
14
14
|
*/
|
|
15
15
|
readonly context: C;
|
|
16
|
-
readonly timer:
|
|
16
|
+
readonly timer: Timer.Interface;
|
|
17
17
|
private readonly validation;
|
|
18
18
|
/**
|
|
19
19
|
* We take all required variables separately because they will get injected via DI - so less refactoring is required in the future.
|
|
20
20
|
*/
|
|
21
|
-
constructor(context: C, timer:
|
|
21
|
+
constructor(context: C, timer: Timer.Interface, validation: ITaskEventValidation);
|
|
22
22
|
isCloseToTimeout(seconds?: number): boolean;
|
|
23
23
|
run(rawEvent: ITaskRawEvent): Promise<IResponseResult>;
|
|
24
24
|
private getIsCloseToTimeoutMilliseconds;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/runner/TaskRunner.js","sources":["../../../src/api/runner/TaskRunner.ts"],"sourcesContent":["import type { ITaskEvent, ITaskRawEvent } from \"~/api/handler/types.js\";\nimport type { ITaskEventValidation, ITaskRunner } from \"./abstractions/index.js\";\nimport type { Context } from \"~/api/types.js\";\nimport { Response, ResponseErrorResult } from \"~/api/response/index.js\";\nimport { TaskControl } from \"./TaskControl.js\";\nimport type { IResponseResult } from \"~/api/response/abstractions/index.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\nimport type {
|
|
1
|
+
{"version":3,"file":"api/runner/TaskRunner.js","sources":["../../../src/api/runner/TaskRunner.ts"],"sourcesContent":["import type { ITaskEvent, ITaskRawEvent } from \"~/api/handler/types.js\";\nimport type { ITaskEventValidation, ITaskRunner } from \"./abstractions/index.js\";\nimport type { Context } from \"~/api/types.js\";\nimport { Response, ResponseErrorResult } from \"~/api/response/index.js\";\nimport { TaskControl } from \"./TaskControl.js\";\nimport type { IResponseResult } from \"~/api/response/abstractions/index.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\nimport type { Timer } from \"~/api/abstractions/Timer.js\";\n\nconst transformMinutesIntoMilliseconds = (minutes: number) => {\n return minutes * 60000;\n};\n\nconst DEFAULT_TASKS_TIMEOUT_CLOSE_MINUTES = 3;\n\nexport class TaskRunner<C extends Context = Context> implements ITaskRunner<C> {\n /**\n * When DI is introduced, these will get injected.\n *\n * container.bind<Request>(\"Request\").toConstantValue(request);\n * @inject(\"Request\") public readonly request: Request;\n *\n * Follow the same example for the rest of the properties.\n */\n public readonly context: C;\n public readonly timer: Timer.Interface;\n private readonly validation: ITaskEventValidation;\n\n /**\n * We take all required variables separately because they will get injected via DI - so less refactoring is required in the future.\n */\n public constructor(context: C, timer: Timer.Interface, validation: ITaskEventValidation) {\n this.context = context;\n this.timer = timer;\n this.validation = validation;\n }\n\n public isCloseToTimeout(seconds?: number) {\n const milliseconds = seconds ? seconds * 1000 : this.getIsCloseToTimeoutMilliseconds();\n return this.timer.getRemainingMilliseconds() < milliseconds;\n }\n\n public async run(rawEvent: ITaskRawEvent): Promise<IResponseResult> {\n const response = new Response({\n ...rawEvent\n });\n\n let event: ITaskEvent;\n try {\n event = this.validation.validate(rawEvent);\n } catch (ex) {\n return response.error({\n error: getErrorProperties(ex)\n });\n }\n response.setEvent(event);\n /**\n * If we received a delay when initiating the task, we need to send the continue response immediately.\n */\n if (rawEvent.delay && rawEvent.delay > 0) {\n return response.continue({\n input: {},\n wait: rawEvent.delay\n });\n }\n\n const control = new TaskControl(this, response, this.context);\n\n try {\n const result = await control.run(event);\n if (result instanceof ResponseErrorResult === false) {\n return result;\n }\n console.error(result);\n return result;\n } catch (ex) {\n console.error(`Failed to execute task \"${event.webinyTaskId}\".`);\n console.error(ex);\n return response.error({\n error: getErrorProperties(ex)\n });\n }\n }\n\n private getIsCloseToTimeoutMilliseconds() {\n const value = parseInt(process.env[\"WEBINY_TASKS_TIMEOUT_CLOSE_MINUTES\"] || \"\");\n const result = value > 0 ? value : DEFAULT_TASKS_TIMEOUT_CLOSE_MINUTES;\n return transformMinutesIntoMilliseconds(result);\n }\n}\n"],"names":["transformMinutesIntoMilliseconds","minutes","DEFAULT_TASKS_TIMEOUT_CLOSE_MINUTES","TaskRunner","context","timer","validation","seconds","milliseconds","rawEvent","response","Response","event","ex","getErrorProperties","control","TaskControl","result","ResponseErrorResult","console","value","parseInt","process"],"mappings":";;;AASA,MAAMA,mCAAmC,CAACC,UAC/BA,AAAU,QAAVA;AAGX,MAAMC,sCAAsC;AAErC,MAAMC;IAgBT,YAAmBC,OAAU,EAAEC,KAAsB,EAAEC,UAAgC,CAAE;QACrF,IAAI,CAAC,OAAO,GAAGF;QACf,IAAI,CAAC,KAAK,GAAGC;QACb,IAAI,CAAC,UAAU,GAAGC;IACtB;IAEO,iBAAiBC,OAAgB,EAAE;QACtC,MAAMC,eAAeD,UAAUA,AAAU,OAAVA,UAAiB,IAAI,CAAC,+BAA+B;QACpF,OAAO,IAAI,CAAC,KAAK,CAAC,wBAAwB,KAAKC;IACnD;IAEA,MAAa,IAAIC,QAAuB,EAA4B;QAChE,MAAMC,WAAW,IAAIC,SAAS;YAC1B,GAAGF,QAAQ;QACf;QAEA,IAAIG;QACJ,IAAI;YACAA,QAAQ,IAAI,CAAC,UAAU,CAAC,QAAQ,CAACH;QACrC,EAAE,OAAOI,IAAI;YACT,OAAOH,SAAS,KAAK,CAAC;gBAClB,OAAOI,mBAAmBD;YAC9B;QACJ;QACAH,SAAS,QAAQ,CAACE;QAIlB,IAAIH,SAAS,KAAK,IAAIA,SAAS,KAAK,GAAG,GACnC,OAAOC,SAAS,QAAQ,CAAC;YACrB,OAAO,CAAC;YACR,MAAMD,SAAS,KAAK;QACxB;QAGJ,MAAMM,UAAU,IAAIC,YAAY,IAAI,EAAEN,UAAU,IAAI,CAAC,OAAO;QAE5D,IAAI;YACA,MAAMO,SAAS,MAAMF,QAAQ,GAAG,CAACH;YACjC,IAAIK,kBAAkBC,wBAAwB,OAC1C,OAAOD;YAEXE,QAAQ,KAAK,CAACF;YACd,OAAOA;QACX,EAAE,OAAOJ,IAAI;YACTM,QAAQ,KAAK,CAAC,CAAC,wBAAwB,EAAEP,MAAM,YAAY,CAAC,EAAE,CAAC;YAC/DO,QAAQ,KAAK,CAACN;YACd,OAAOH,SAAS,KAAK,CAAC;gBAClB,OAAOI,mBAAmBD;YAC9B;QACJ;IACJ;IAEQ,kCAAkC;QACtC,MAAMO,QAAQC,SAASC,QAAQ,GAAG,CAAC,qCAAqC,IAAI;QAC5E,MAAML,SAASG,QAAQ,IAAIA,QAAQlB;QACnC,OAAOF,iCAAiCiB;IAC5C;AACJ"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Context } from "../../../api/types.js";
|
|
2
2
|
import type { ITaskEvent } from "../../../api/handler/types.js";
|
|
3
3
|
import type { IResponseResult } from "../../../api/response/abstractions/index.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { Timer } from "../../../api/abstractions/Timer.js";
|
|
5
5
|
export interface IIsCloseToTimeoutCallable {
|
|
6
6
|
(seconds?: number): boolean;
|
|
7
7
|
}
|
|
8
8
|
export interface ITaskRunner<C extends Context = Context> {
|
|
9
9
|
context: C;
|
|
10
10
|
isCloseToTimeout: IIsCloseToTimeoutCallable;
|
|
11
|
-
timer:
|
|
11
|
+
timer: Timer.Interface;
|
|
12
12
|
run(event: ITaskEvent): Promise<IResponseResult>;
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Context } from "../../api/types.js";
|
|
2
|
-
import
|
|
2
|
+
import { TaskService } from "../../api/domain/TaskService.js";
|
|
3
3
|
export interface ICreateTransport {
|
|
4
|
-
|
|
4
|
+
container: Context["container"];
|
|
5
5
|
}
|
|
6
|
-
export declare const createService: (params: ICreateTransport) =>
|
|
6
|
+
export declare const createService: (params: ICreateTransport) => TaskService.Interface;
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import { TaskServicePlugin } from "../plugins/index.js";
|
|
2
1
|
import { WebinyError } from "@webiny/error";
|
|
2
|
+
import { TaskService } from "../domain/TaskService.js";
|
|
3
3
|
const createService = (params)=>{
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
});
|
|
9
|
-
const getTenant = ()=>params.context.tenancy.getCurrentTenant().id;
|
|
10
|
-
return plugin.createService({
|
|
11
|
-
getTenant
|
|
12
|
-
});
|
|
4
|
+
const { container } = params;
|
|
5
|
+
const service = container.resolveAll(TaskService);
|
|
6
|
+
if (0 === service.length) throw new WebinyError("Missing TaskService.", "TASK_SERVICE_ERROR");
|
|
7
|
+
return service[service.length - 1];
|
|
13
8
|
};
|
|
14
9
|
export { createService };
|
|
15
10
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/service/createService.js","sources":["../../../src/api/service/createService.ts"],"sourcesContent":["import type { Context } from \"~/api/types.js\";\nimport
|
|
1
|
+
{"version":3,"file":"api/service/createService.js","sources":["../../../src/api/service/createService.ts"],"sourcesContent":["import type { Context } from \"~/api/types.js\";\nimport { WebinyError } from \"@webiny/error\";\nimport { TaskService } from \"~/api/domain/TaskService.js\";\n\nexport interface ICreateTransport {\n container: Context[\"container\"];\n}\n\nexport const createService = (params: ICreateTransport): TaskService.Interface => {\n const { container } = params;\n const service = container.resolveAll(TaskService);\n if (service.length === 0) {\n throw new WebinyError(\"Missing TaskService.\", \"TASK_SERVICE_ERROR\");\n }\n return service[service.length - 1];\n};\n"],"names":["createService","params","container","service","TaskService","WebinyError"],"mappings":";;AAQO,MAAMA,gBAAgB,CAACC;IAC1B,MAAM,EAAEC,SAAS,EAAE,GAAGD;IACtB,MAAME,UAAUD,UAAU,UAAU,CAACE;IACrC,IAAID,AAAmB,MAAnBA,QAAQ,MAAM,EACd,MAAM,IAAIE,YAAY,wBAAwB;IAElD,OAAOF,OAAO,CAACA,QAAQ,MAAM,GAAG,EAAE;AACtC"}
|
package/api/service/index.d.ts
CHANGED
|
@@ -1,4 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { StepFunctionServicePlugin } from "./StepFunctionServicePlugin.js";
|
|
3
|
-
export declare const createServicePlugins: () => (StepFunctionServicePlugin | EventBridgeEventTransportPlugin)[];
|
|
4
|
-
export * from "./createService.js";
|
|
1
|
+
export { createService } from "./createService.js";
|
package/api/service/index.js
CHANGED
|
@@ -1,12 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { StepFunctionServicePlugin } from "./StepFunctionServicePlugin.js";
|
|
3
|
-
export * from "./createService.js";
|
|
4
|
-
const createServicePlugins = ()=>[
|
|
5
|
-
new StepFunctionServicePlugin({
|
|
6
|
-
default: true
|
|
7
|
-
}),
|
|
8
|
-
new EventBridgeEventTransportPlugin()
|
|
9
|
-
];
|
|
10
|
-
export { createServicePlugins };
|
|
11
|
-
|
|
12
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { createService } from "./createService.js";
|
package/api/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CmsContext as BaseContext, CmsEntryListParams, CmsEntryMeta, CmsModel } from "@webiny/api-headless-cms/types/index.js";
|
|
2
2
|
import type { IResponseError } from "../api/response/abstractions/index.js";
|
|
3
3
|
import type { GenericRecord } from "@webiny/api/types.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { IServiceInfo } from "@webiny/api-core/features/task/TaskService/abstractions.js";
|
|
5
5
|
import type { SecurityPermission } from "@webiny/api-core/types/security.js";
|
|
6
6
|
import type { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
7
7
|
import { TaskService } from "@webiny/api-core/features/task/TaskService/index.js";
|
|
@@ -151,7 +151,7 @@ export interface ITaskAbortParams {
|
|
|
151
151
|
export interface ITasksContextServiceObject {
|
|
152
152
|
trigger: <T extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, O extends TaskService.GenericOutput = TaskService.GenericOutput>(params: ITaskTriggerParams<T>) => Promise<Result<ITask<T, O>, BaseError>>;
|
|
153
153
|
abort: <T extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, O extends TaskService.GenericOutput = TaskService.GenericOutput>(params: ITaskAbortParams) => Promise<Result<ITask<T, O>, BaseError>>;
|
|
154
|
-
fetchServiceInfo: (input: ITask<any, any> | string) => Promise<Result<
|
|
154
|
+
fetchServiceInfo: (input: ITask<any, any> | string) => Promise<Result<IServiceInfo, BaseError>>;
|
|
155
155
|
}
|
|
156
156
|
export interface ITasksContextObject extends ITasksContextCrudObject, ITasksContextDefinitionObject, ITasksContextServiceObject {
|
|
157
157
|
}
|
package/api/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/types.js","sources":["../../src/api/types.ts"],"sourcesContent":["import type {\n CmsContext as BaseContext,\n CmsEntryListParams,\n CmsEntryMeta,\n CmsModel\n} from \"@webiny/api-headless-cms/types/index.js\";\nimport type { IResponseError } from \"~/api/response/abstractions/index.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\nimport type {
|
|
1
|
+
{"version":3,"file":"api/types.js","sources":["../../src/api/types.ts"],"sourcesContent":["import type {\n CmsContext as BaseContext,\n CmsEntryListParams,\n CmsEntryMeta,\n CmsModel\n} from \"@webiny/api-headless-cms/types/index.js\";\nimport type { IResponseError } from \"~/api/response/abstractions/index.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\nimport type { IServiceInfo } from \"@webiny/api-core/features/task/TaskService/abstractions.js\";\nimport type { SecurityPermission } from \"@webiny/api-core/types/security.js\";\nimport type { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { TaskService } from \"@webiny/api-core/features/task/TaskService/index.js\";\nimport { BaseError, Result } from \"@webiny/feature/api\";\nimport type { IdInterfaceGenerator, NumericInterfaceGenerator } from \"@webiny/api\";\n// TODO had to import for augmentation to work, but is there a better way to do this?\nimport \"./features/TaskController/augmentation.js\";\n\nexport * from \"./handler/types.js\";\nexport * from \"./response/abstractions/index.js\";\nexport * from \"./runner/abstractions/index.js\";\n\nexport type ITaskDataInput = GenericRecord;\n\nexport enum TaskLogItemType {\n INFO = \"info\",\n ERROR = \"error\"\n}\n\nexport interface ITaskLogItemData {\n [key: string]: any;\n}\n\nexport interface ITaskLogItemBase {\n message: string;\n createdOn: string;\n type: TaskLogItemType;\n data?: ITaskLogItemData;\n}\n\nexport interface ITaskLogItemInfo extends ITaskLogItemBase {\n type: TaskLogItemType.INFO;\n}\n\nexport interface ITaskLogItemError extends ITaskLogItemBase {\n type: TaskLogItemType.ERROR;\n error?: IResponseError;\n}\n\nexport type ITaskLogItem = ITaskLogItemInfo | ITaskLogItemError;\n\nexport interface ITaskLog {\n /**\n * ID without the revision number (for example: #0001).\n */\n id: string;\n createdOn: string;\n createdBy: ITaskIdentity;\n executionName: string;\n task: string;\n iteration: number;\n items: ITaskLogItem[];\n}\n\nexport enum TaskDataStatus {\n PENDING = \"pending\",\n RUNNING = \"running\",\n FAILED = \"failed\",\n SUCCESS = \"success\",\n ABORTED = \"aborted\"\n}\n\nexport interface ITaskIdentity {\n id: string;\n displayName: string;\n type: string;\n}\n\nexport type IGetTaskResponse<\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n> = ITask<T, O> | null;\n\nexport interface IListTasksResponse<\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n> {\n items: ITask<T, O>[];\n meta: CmsEntryMeta;\n}\n\nexport interface IListTaskLogsResponse {\n items: ITaskLog[];\n meta: CmsEntryMeta;\n}\n\nexport type ICreateTaskResponse<\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n> = ITask<T, O>;\nexport type IUpdateTaskResponse<\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n> = ITask<T, O>;\nexport type IDeleteTaskResponse = boolean;\n\nexport interface IListTaskParamsWhere\n extends\n IdInterfaceGenerator<\"id\">,\n IdInterfaceGenerator<\"parentId\">,\n IdInterfaceGenerator<\"definitionId\">,\n IdInterfaceGenerator<\"taskStatus\"> {\n //\n}\n\nexport interface IListTaskParams extends Omit<CmsEntryListParams, \"fields\" | \"search\"> {\n where?: IListTaskParamsWhere;\n}\n\nexport interface IListTaskLogParamsWhere\n extends\n IdInterfaceGenerator<\"id\">,\n IdInterfaceGenerator<\"task\">,\n NumericInterfaceGenerator<\"iteration\"> {}\n\nexport interface IListTaskLogParams extends Omit<\n CmsEntryListParams,\n \"fields\" | \"search\" | \"where\"\n> {\n where?: IListTaskLogParamsWhere;\n}\n\nexport interface ITaskCreateData<T extends TaskDefinition.TaskInput = TaskDefinition.TaskInput> {\n definitionId: string;\n name: string;\n input: T;\n parentId?: string;\n}\n\nexport interface ITaskUpdateData<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n> {\n name?: string;\n input?: I;\n output?: O;\n taskStatus?: TaskDataStatus;\n executionName?: string;\n startedOn?: string;\n finishedOn?: string;\n eventResponse?: GenericRecord;\n iterations?: number;\n}\n\nexport interface ITaskLogCreateInput {\n executionName: string;\n iteration: number;\n}\n\nexport interface ITaskLogUpdateInput {\n items?: ITaskLogItem[];\n}\n\nexport interface ITasksContextCrudObject {\n /**\n * Models\n */\n getTaskModel(): Promise<CmsModel>;\n getLogModel(): Promise<CmsModel>;\n /**\n * Tasks\n */\n getTask<\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n id: string\n ): Promise<IGetTaskResponse<T, O> | null>;\n listTasks<\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n params?: IListTaskParams\n ): Promise<IListTasksResponse<T, O>>;\n createTask<T extends TaskService.TaskInput = TaskService.TaskInput>(\n task: ITaskCreateData<T>\n ): Promise<ICreateTaskResponse<T>>;\n updateTask<\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n id: string,\n data: Partial<ITaskUpdateData<T, O>>\n ): Promise<IUpdateTaskResponse<T, O>>;\n deleteTask(id: string): Promise<IDeleteTaskResponse>;\n /**\n * Recursively delete a task, its logs (if any were written), and its entire\n * descendant subtree. Best-effort: per-record failures are logged and swallowed,\n * the method never throws.\n */\n cleanupTaskSubtree(id: string): Promise<void>;\n /**\n * Logs\n */\n createLog(task: Pick<ITask, \"id\">, data: ITaskLogCreateInput): Promise<ITaskLog>;\n updateLog(id: string, data: ITaskLogUpdateInput): Promise<ITaskLog>;\n deleteLog(id: string): Promise<boolean>;\n getLog(id: string): Promise<ITaskLog | null>;\n getLatestLog(taskId: string): Promise<ITaskLog>;\n listLogs(params: IListTaskLogParams): Promise<IListTaskLogsResponse>;\n}\n\nexport interface ITasksContextDefinitionObject {\n getDefinition: <\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(\n id: string\n ) => TaskDefinition.Runnable<I, O> | null;\n listDefinitions: () => TaskDefinition.Interface[];\n}\n\nexport interface ITaskTriggerParams<I = ITaskDataInput> {\n parent?: Pick<ITask, \"id\">;\n definition: string;\n name?: string;\n input?: I;\n delay?: number;\n}\n\nexport interface ITaskAbortParams {\n id: string;\n message?: string;\n}\n\nexport interface ITasksContextServiceObject {\n trigger: <\n T extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n params: ITaskTriggerParams<T>\n ) => Promise<Result<ITask<T, O>, BaseError>>;\n abort: <\n T extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n params: ITaskAbortParams\n ) => Promise<Result<ITask<T, O>, BaseError>>;\n fetchServiceInfo: (input: ITask<any, any> | string) => Promise<Result<IServiceInfo, BaseError>>;\n}\n\nexport interface ITasksContextObject\n extends ITasksContextCrudObject, ITasksContextDefinitionObject, ITasksContextServiceObject {}\n\nexport interface Context extends BaseContext {\n tasks: ITasksContextObject;\n}\n\nexport interface TaskPermission extends SecurityPermission {\n name: \"task\";\n rwd?: string;\n}\n\nexport type ITask<\n I extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n> = TaskService.Task<I, O>;\n\nexport type SelfCleanup = TaskDefinition.SelfCleanup;\nexport type SelfCleanupEvent = TaskDefinition.SelfCleanupEvent;\n"],"names":["TaskLogItemType","TaskDataStatus"],"mappings":";;;;AAuBO,IAAKA,wBAAeA,WAAAA,GAAAA,SAAfA,eAAe;;;WAAfA;;AAwCL,IAAKC,uBAAcA,WAAAA,GAAAA,SAAdA,cAAc;;;;;;WAAdA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/background-tasks",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.6.0-alpha.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -19,23 +19,25 @@
|
|
|
19
19
|
},
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
-
"@webiny/
|
|
25
|
-
"@webiny/api
|
|
26
|
-
"@webiny/
|
|
27
|
-
"@webiny/
|
|
28
|
-
"@webiny/
|
|
29
|
-
"@webiny/
|
|
30
|
-
"@webiny/
|
|
31
|
-
"@webiny/
|
|
32
|
-
"@webiny/handler-
|
|
33
|
-
"@webiny/
|
|
34
|
-
"@webiny/
|
|
35
|
-
"@webiny/
|
|
36
|
-
"@webiny/
|
|
37
|
-
"@webiny/
|
|
22
|
+
"@graphql-tools/merge": "9.2.2",
|
|
23
|
+
"@graphql-tools/schema": "10.0.38",
|
|
24
|
+
"@webiny/admin-ui": "6.6.0-alpha.0",
|
|
25
|
+
"@webiny/api": "6.6.0-alpha.0",
|
|
26
|
+
"@webiny/api-core": "6.6.0-alpha.0",
|
|
27
|
+
"@webiny/api-graphql": "6.6.0-alpha.0",
|
|
28
|
+
"@webiny/api-headless-cms": "6.6.0-alpha.0",
|
|
29
|
+
"@webiny/app": "6.6.0-alpha.0",
|
|
30
|
+
"@webiny/app-admin": "6.6.0-alpha.0",
|
|
31
|
+
"@webiny/error": "6.6.0-alpha.0",
|
|
32
|
+
"@webiny/event-handler-core": "6.6.0-alpha.0",
|
|
33
|
+
"@webiny/feature": "6.6.0-alpha.0",
|
|
34
|
+
"@webiny/handler": "6.6.0-alpha.0",
|
|
35
|
+
"@webiny/icons": "6.6.0-alpha.0",
|
|
36
|
+
"@webiny/plugins": "6.6.0-alpha.0",
|
|
37
|
+
"@webiny/sdk": "6.6.0-alpha.0",
|
|
38
|
+
"@webiny/utils": "6.6.0-alpha.0",
|
|
38
39
|
"deep-equal": "2.2.3",
|
|
40
|
+
"graphql": "16.14.2",
|
|
39
41
|
"lodash": "4.18.1",
|
|
40
42
|
"mobx": "6.16.1",
|
|
41
43
|
"mobx-react-lite": "4.1.1",
|
|
@@ -46,11 +48,15 @@
|
|
|
46
48
|
"zod": "4.4.3"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@webiny/
|
|
50
|
-
"@webiny/
|
|
51
|
+
"@webiny/api-core-testing": "6.6.0-alpha.0",
|
|
52
|
+
"@webiny/aws-sdk": "6.6.0-alpha.0",
|
|
53
|
+
"@webiny/build-tools": "6.6.0-alpha.0",
|
|
54
|
+
"@webiny/di": "1.0.2",
|
|
55
|
+
"@webiny/project-utils": "6.6.0-alpha.0",
|
|
56
|
+
"@webiny/wcp": "6.6.0-alpha.0",
|
|
51
57
|
"rimraf": "6.1.3",
|
|
52
58
|
"type-fest": "5.8.0",
|
|
53
|
-
"typescript": "
|
|
59
|
+
"typescript": "7.0.2",
|
|
54
60
|
"vitest": "4.1.10"
|
|
55
61
|
},
|
|
56
62
|
"publishConfig": {
|
package/api/context.d.ts
DELETED