@webiny/background-tasks 6.6.0-alpha.0 → 6.6.0-alpha.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.
Files changed (58) hide show
  1. package/admin/BackgroundTaskRoutes.js +16 -3
  2. package/admin/BackgroundTaskRoutes.js.map +1 -1
  3. package/admin/presentation/TaskDetail/components/TaskDetailDrawer.js +6 -0
  4. package/admin/presentation/TaskDetail/components/TaskDetailDrawer.js.map +1 -1
  5. package/admin/presentation/TaskExecutions/components/TaskExecutionsView.js +44 -24
  6. package/admin/presentation/TaskExecutions/components/TaskExecutionsView.js.map +1 -1
  7. package/api/BackgroundTasksFeature.js +2 -0
  8. package/api/BackgroundTasksFeature.js.map +1 -1
  9. package/api/crud/service.tasks.js +4 -2
  10. package/api/crud/service.tasks.js.map +1 -1
  11. package/api/decorators/RunnableTaskDecorator.d.ts +2 -1
  12. package/api/decorators/RunnableTaskDecorator.js +5 -6
  13. package/api/decorators/RunnableTaskDecorator.js.map +1 -1
  14. package/api/decorators/SelfCleaningTaskDecorator.d.ts +5 -2
  15. package/api/decorators/SelfCleaningTaskDecorator.js +14 -5
  16. package/api/decorators/SelfCleaningTaskDecorator.js.map +1 -1
  17. package/api/domain/errors.d.ts +10 -0
  18. package/api/domain/errors.js +11 -1
  19. package/api/domain/errors.js.map +1 -1
  20. package/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.d.ts +6 -3
  21. package/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.js +66 -5
  22. package/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.js.map +1 -1
  23. package/api/features/GetTaskDefinition/abstractions.d.ts +2 -1
  24. package/api/features/GetTaskDefinition/abstractions.js.map +1 -1
  25. package/api/features/TaskHandlerResolver/TaskHandlerResolver.d.ts +12 -0
  26. package/api/features/TaskHandlerResolver/TaskHandlerResolver.js +19 -0
  27. package/api/features/TaskHandlerResolver/TaskHandlerResolver.js.map +1 -0
  28. package/api/features/TaskHandlerResolver/abstractions.d.ts +17 -0
  29. package/api/features/TaskHandlerResolver/abstractions.js +5 -0
  30. package/api/features/TaskHandlerResolver/abstractions.js.map +1 -0
  31. package/api/features/TaskHandlerResolver/feature.d.ts +9 -0
  32. package/api/features/TaskHandlerResolver/feature.js +11 -0
  33. package/api/features/TaskHandlerResolver/feature.js.map +1 -0
  34. package/api/features/TaskHandlerResolver/index.d.ts +2 -0
  35. package/api/features/TaskHandlerResolver/index.js +2 -0
  36. package/api/runner/TaskControl.d.ts +25 -1
  37. package/api/runner/TaskControl.js +28 -18
  38. package/api/runner/TaskControl.js.map +1 -1
  39. package/api/runner/TaskManager.d.ts +12 -1
  40. package/api/runner/TaskManager.js +8 -7
  41. package/api/runner/TaskManager.js.map +1 -1
  42. package/api/runner/TaskManagerStore.d.ts +7 -0
  43. package/api/runner/TaskManagerStore.js +3 -3
  44. package/api/runner/TaskManagerStore.js.map +1 -1
  45. package/api/runner/TaskRunner.js +25 -4
  46. package/api/runner/TaskRunner.js.map +1 -1
  47. package/api/tasks/testingRunTask.d.ts +10 -2
  48. package/api/tasks/testingRunTask.js +10 -3
  49. package/api/tasks/testingRunTask.js.map +1 -1
  50. package/package.json +26 -28
  51. package/testing/index.d.ts +3 -0
  52. package/testing/index.js +2 -0
  53. package/testing/mockTaskTriggerTransportPlugin.d.ts +2 -0
  54. package/testing/mockTaskTriggerTransportPlugin.js +18 -0
  55. package/testing/mockTaskTriggerTransportPlugin.js.map +1 -0
  56. package/testing/runner.d.ts +19 -0
  57. package/testing/runner.js +44 -0
  58. package/testing/runner.js.map +1 -0
@@ -0,0 +1,2 @@
1
+ export { TaskHandlerResolver } from "./abstractions.js";
2
+ export { TaskHandlerResolverFeature } from "./feature.js";
@@ -0,0 +1,2 @@
1
+ export { TaskHandlerResolver } from "./abstractions.js";
2
+ export { TaskHandlerResolverFeature } from "./feature.js";
@@ -2,11 +2,35 @@ import type { ITaskEvent } from "../../api/handler/types.js";
2
2
  import type { Context } from "../../api/types.js";
3
3
  import type { ITaskControl, ITaskRunner } from "./abstractions/index.js";
4
4
  import type { IResponse, IResponseResult } from "../../api/response/abstractions/index.js";
5
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
6
+ import { TaskExecutionContext } from "../../api/features/TaskExecutionContext/index.js";
7
+ import { TasksCrud } from "../../api/TasksCrud.js";
8
+ import { GetTaskDefinitionUseCase } from "../../api/features/GetTaskDefinition/abstractions.js";
9
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
10
+ import { TaskController } from "@webiny/api-core/features/task/TaskController/abstractions.js";
11
+ /**
12
+ * What TaskControl needs from the container, declared in one place.
13
+ *
14
+ * TaskControl is built by hand (TaskRunner does it), so it cannot take these through DI the way a
15
+ * registered class would. Naming them here is the next best thing: the class states what it uses,
16
+ * TaskRunner resolves them once where it assembles the object, and a test can pass fakes. Reaching
17
+ * into `context.container` from inside a method instead would leave the class with dependencies
18
+ * nothing can see or substitute.
19
+ */
20
+ export interface ITaskControlDependencies {
21
+ logger: Logger.Interface;
22
+ identityContext: IdentityContext.Interface;
23
+ taskExecutionContext: TaskExecutionContext.Interface;
24
+ tasksCrud: TasksCrud.Interface;
25
+ taskController: TaskController.Interface;
26
+ getTaskDefinition: GetTaskDefinitionUseCase.Interface;
27
+ }
5
28
  export declare class TaskControl implements ITaskControl {
6
29
  readonly runner: ITaskRunner;
7
30
  readonly response: IResponse;
8
31
  readonly context: Context;
9
- constructor(runner: ITaskRunner, response: IResponse, context: Context);
32
+ private readonly deps;
33
+ constructor(runner: ITaskRunner, response: IResponse, context: Context, deps: ITaskControlDependencies);
10
34
  run(event: Pick<ITaskEvent, "webinyTaskId">): Promise<IResponseResult>;
11
35
  private runEvents;
12
36
  private getTask;
@@ -3,23 +3,21 @@ 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, IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
7
- import { TaskExecutionContext } from "../features/TaskExecutionContext/index.js";
6
+ import { AuthenticatedIdentity } from "@webiny/api-core/features/security/IdentityContext/index.js";
8
7
  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";
11
8
  class TaskControl {
12
- constructor(runner, response, context){
9
+ constructor(runner, response, context, deps){
13
10
  this.runner = runner;
14
11
  this.context = context;
15
12
  this.response = response;
13
+ this.deps = deps;
16
14
  }
17
15
  async run(event) {
18
16
  const taskId = event.webinyTaskId;
19
17
  let task;
20
18
  try {
21
19
  task = await this.getTask(taskId);
22
- this.context.container.resolve(IdentityContext).setIdentity(new AuthenticatedIdentity({
20
+ this.deps.identityContext.setIdentity(new AuthenticatedIdentity({
23
21
  id: task.createdBy.id,
24
22
  type: task.createdBy.type,
25
23
  displayName: task.createdBy.displayName || "",
@@ -32,7 +30,7 @@ class TaskControl {
32
30
  ...getErrorProperties(error)
33
31
  });
34
32
  }
35
- const definitionResult = this.context.container.resolve(GetTaskDefinitionUseCase).execute(task.definitionId);
33
+ const definitionResult = this.deps.getTaskDefinition.execute(task.definitionId);
36
34
  if (definitionResult.isFail()) return this.response.error({
37
35
  error: {
38
36
  message: `Task "${task.id}" cannot be executed because there is no "${task.definitionId}" definition plugin.`,
@@ -68,16 +66,20 @@ class TaskControl {
68
66
  });
69
67
  const store = new TaskManagerStore({
70
68
  context: this.context,
69
+ tasksCrud: this.deps.tasksCrud,
71
70
  task,
72
71
  log: taskLog,
73
72
  databaseLogs
74
73
  });
75
- const executionContext = this.context.container.resolve(TaskExecutionContext);
74
+ const executionContext = this.deps.taskExecutionContext;
76
75
  executionContext.setStore(store);
77
76
  executionContext.setRunner(this.runner);
78
77
  executionContext.setTimer(this.runner.timer);
79
78
  executionContext.setResponse(new TaskResponse(this.response));
80
- const manager = new TaskManager(this.context, this.response, store);
79
+ const manager = new TaskManager(this.context, this.response, store, {
80
+ taskController: this.deps.taskController,
81
+ identityContext: this.deps.identityContext
82
+ });
81
83
  const databaseResponse = new DatabaseResponse(this.response, store);
82
84
  try {
83
85
  const result = await manager.run(definition);
@@ -103,24 +105,32 @@ class TaskControl {
103
105
  async runEvents(result, definition, task) {
104
106
  if (result.status === TaskResultStatus.ERROR && definition.onError) try {
105
107
  await definition.onError({
106
- task
108
+ task,
109
+ definition
107
110
  });
108
111
  } catch (ex) {
109
- console.error(`Error executing onError hook for task "${task.id}".`);
110
- console.log(getErrorProperties(ex));
112
+ this.deps.logger.error({
113
+ error: getErrorProperties(ex),
114
+ taskId: task.id,
115
+ hook: "onError"
116
+ }, "Error executing task lifecycle hook.");
111
117
  }
112
118
  else if (result.status === TaskResultStatus.DONE && definition.onDone) try {
113
119
  await definition.onDone({
114
- task
120
+ task,
121
+ definition
115
122
  });
116
123
  } catch (ex) {
117
- console.error(`Error executing onDone hook for task "${task.id}".`);
118
- console.log(getErrorProperties(ex));
124
+ this.deps.logger.error({
125
+ error: getErrorProperties(ex),
126
+ taskId: task.id,
127
+ hook: "onDone"
128
+ }, "Error executing task lifecycle hook.");
119
129
  }
120
130
  }
121
131
  async getTask(id) {
122
132
  try {
123
- const task = await this.context.container.resolve(TasksCrud).getTask(id);
133
+ const task = await this.deps.tasksCrud.getTask(id);
124
134
  if (task) return task;
125
135
  } catch (ex) {
126
136
  throw this.response.error({
@@ -152,7 +162,7 @@ class TaskControl {
152
162
  };
153
163
  let taskLog = null;
154
164
  try {
155
- taskLog = await this.context.container.resolve(TasksCrud).getLatestLog(task.id);
165
+ taskLog = await this.deps.tasksCrud.getLatestLog(task.id);
156
166
  } catch (error) {
157
167
  if ("NOT_FOUND" !== error.code) throw this.response.error({
158
168
  error
@@ -160,7 +170,7 @@ class TaskControl {
160
170
  }
161
171
  const currentIteration = taskLog?.iteration || 0;
162
172
  try {
163
- return await this.context.container.resolve(TasksCrud).createLog(task, {
173
+ return await this.deps.tasksCrud.createLog(task, {
164
174
  executionName: this.response.event.executionName,
165
175
  iteration: currentIteration + 1
166
176
  });
@@ -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 {\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":";;;;;;;;;;AA0BO,MAAMA;IAKT,YAAmBC,MAAmB,EAAEC,QAAmB,EAAEC,OAAgB,CAAE;QAC3E,IAAI,CAAC,MAAM,GAAGF;QACd,IAAI,CAAC,OAAO,GAAGE;QACf,IAAI,CAAC,QAAQ,GAAGD;IACpB;IAEA,MAAa,IAAIE,KAAuC,EAA4B;QAChF,MAAMC,SAASD,MAAM,YAAY;QAOjC,IAAIE;QACJ,IAAI;YACAA,OAAO,MAAM,IAAI,CAAC,OAAO,CAACD;YAC1B,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAACE,iBAAiB,WAAW,CACvD,IAAIC,sBAAsB;gBACtB,IAAIF,KAAK,SAAS,CAAC,EAAE;gBACrB,MAAMA,KAAK,SAAS,CAAC,IAAI;gBACzB,aAAaA,KAAK,SAAS,CAAC,WAAW,IAAI;gBAC3C,SAAS;oBACL,iBAAiB;gBACrB;YACJ;QAER,EAAE,OAAOG,OAAO;YAKZ,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvB,GAAGC,mBAAmBD,MAAM;YAChC;QACJ;QAIA,MAAME,mBAAmB,IAAI,CAAC,OAAO,CAAC,SAAS,CAC1C,OAAO,CAACC,0BACR,OAAO,CAACN,KAAK,YAAY;QAC9B,IAAIK,iBAAiB,MAAM,IACvB,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAO;gBACH,SAAS,CAAC,MAAM,EAAEL,KAAK,EAAE,CAAC,0CAA0C,EAAEA,KAAK,YAAY,CAAC,oBAAoB,CAAC;gBAC7G,MAAM;gBACN,MAAM;oBACF,cAAcA,KAAK,YAAY;gBACnC;YACJ;QACJ;QAEJ,MAAMO,aAAaF,iBAAiB,KAAK;QAIzC,MAAMG,eAAeD,AAA4B,SAA5BA,WAAW,YAAY;QAK5C,IAAIE;QACJ,IAAI;YACAA,UAAU,MAAM,IAAI,CAAC,UAAU,CAAC;gBAC5BT;gBACAQ;YACJ;QACJ,EAAE,OAAOL,OAAO;YACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvBA;YACJ;QACJ;QAKA,IAAIH,KAAK,UAAU,KAAKU,eAAe,OAAO,EAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO;QAM3B,IAAIV,KAAK,UAAU,KAAKU,eAAe,OAAO,EAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAO;gBACH,SAAS;YACb;QACJ;QAMC,IAAIV,KAAK,UAAU,KAAKU,eAAe,MAAM,EAC9C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAO;gBACH,SAAS;YACb;QACJ;QAGJ,MAAMC,QAAQ,IAAIC,iBAAiB;YAC/B,SAAS,IAAI,CAAC,OAAO;YACrBZ;YACA,KAAKS;YACLD;QACJ;QAGA,MAAMK,mBAAmB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAACC;QACxDD,iBAAiB,QAAQ,CAACF;QAC1BE,iBAAiB,SAAS,CAAC,IAAI,CAAC,MAAM;QACtCA,iBAAiB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK;QAC3CA,iBAAiB,WAAW,CAAC,IAAIE,aAAa,IAAI,CAAC,QAAQ;QAE3D,MAAMC,UAAU,IAAIC,YAAY,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAEN;QAE7D,MAAMO,mBAAmB,IAAIC,iBAAiB,IAAI,CAAC,QAAQ,EAAER;QAE7D,IAAI;YACA,MAAMS,SAAS,MAAMJ,QAAQ,GAAG,CAACT;YAEjC,MAAMc,iBAAiB,MAAMH,iBAAiB,IAAI,CAACE;YAGnD,MAAM,IAAI,CAAC,SAAS,CAACA,QAAQb,YAAYI,MAAM,OAAO;YAEtD,OAAOU;QACX,EAAE,OAAOC,IAAI;YAIT,OAAO,MAAMJ,iBAAiB,IAAI,CAC9B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAChB,OAAO;oBACH,SAASI,GAAG,OAAO;oBACnB,MAAMA,GAAG,IAAI,IAAI;oBACjB,OAAOA,GAAG,KAAK;oBACf,MAAM;wBACF,GAAGA,GAAG,IAAI;wBACV,OAAOtB,KAAK,KAAK;oBACrB;gBACJ;YACJ;QAER,SAAU;YAENa,iBAAiB,KAAK;QAC1B;IACJ;IAEA,MAAc,UACVO,MAAuB,EACvBb,UAAmC,EACnCP,IAAW,EACE;QACb,IAAIoB,OAAO,MAAM,KAAKG,iBAAiB,KAAK,IAAIhB,WAAW,OAAO,EAC9D,IAAI;YACA,MAAMA,WAAW,OAAO,CAAC;gBAAEP;YAAK;QACpC,EAAE,OAAOsB,IAAI;YACTE,QAAQ,KAAK,CAAC,CAAC,uCAAuC,EAAExB,KAAK,EAAE,CAAC,EAAE,CAAC;YACnEwB,QAAQ,GAAG,CAACpB,mBAAmBkB;QACnC;aACG,IAAIF,OAAO,MAAM,KAAKG,iBAAiB,IAAI,IAAIhB,WAAW,MAAM,EACnE,IAAI;YACA,MAAMA,WAAW,MAAM,CAAC;gBAAEP;YAAK;QACnC,EAAE,OAAOsB,IAAI;YACTE,QAAQ,KAAK,CAAC,CAAC,sCAAsC,EAAExB,KAAK,EAAE,CAAC,EAAE,CAAC;YAClEwB,QAAQ,GAAG,CAACpB,mBAAmBkB;QACnC;IAER;IAEA,MAAc,QAA4CG,EAAU,EAAqB;QACrF,IAAI;YACA,MAAMzB,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC0B,WAAW,OAAO,CAAID;YACxE,IAAIzB,MACA,OAAOA;QAEf,EAAE,OAAOsB,IAAI;YACT,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACtB,OAAO;oBACH,SAASA,GAAG,OAAO;oBACnB,MAAMA,GAAG,IAAI,IAAI;oBACjB,OAAOA,GAAG,KAAK;oBACf,MAAMA,GAAG,IAAI;gBACjB;YACJ;QACJ;QACA,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACtB,OAAO;gBACH,SAAS,CAAC,MAAM,EAAEG,GAAG,+CAA+C,CAAC;gBACrE,MAAM;YACV;QACJ;IACJ;IAEA,MAAc,WAAWE,MAAyB,EAAqB;QACnE,MAAM,EAAE3B,IAAI,EAAEQ,YAAY,EAAE,GAAGmB;QAI/B,IAAI,CAACnB,cACD,OAAO;YACH,IAAI,GAAGR,KAAK,EAAE,CAAC,IAAI,CAAC;YACpB,WAAWA,KAAK,SAAS;YACzB,WAAWA,KAAK,SAAS;YACzB,eAAeA,KAAK,aAAa;YACjC,MAAMA,KAAK,EAAE;YACb,WAAWA,KAAK,UAAU;YAC1B,OAAO,EAAE;QACb;QAEJ,IAAIS,UAA2B;QAI/B,IAAI;YACAA,UAAU,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAACiB,WAAW,YAAY,CAAC1B,KAAK,EAAE;QAClF,EAAE,OAAOG,OAAO;YAIZ,IAAIA,AAAe,gBAAfA,MAAM,IAAI,EACV,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACtBA;YACJ;QAKR;QAEA,MAAMyB,mBAAmBnB,SAAS,aAAa;QAE/C,IAAI;YACA,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAACiB,WAAW,SAAS,CAAC1B,MAAM;gBACnE,eAAe,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa;gBAChD,WAAW4B,mBAAmB;YAClC;QACJ,EAAE,OAAOzB,OAAO;YACZ,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACtBA;YACJ;QACJ;IACJ;AACJ"}
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\";\nimport { Logger } from \"@webiny/api-core/features/logger/index.js\";\nimport { TaskController } from \"@webiny/api-core/features/task/TaskController/abstractions.js\";\n\ninterface IGetTaskLogParams {\n task: ITask;\n databaseLogs: boolean;\n}\n\n/**\n * What TaskControl needs from the container, declared in one place.\n *\n * TaskControl is built by hand (TaskRunner does it), so it cannot take these through DI the way a\n * registered class would. Naming them here is the next best thing: the class states what it uses,\n * TaskRunner resolves them once where it assembles the object, and a test can pass fakes. Reaching\n * into `context.container` from inside a method instead would leave the class with dependencies\n * nothing can see or substitute.\n */\nexport interface ITaskControlDependencies {\n logger: Logger.Interface;\n identityContext: IdentityContext.Interface;\n taskExecutionContext: TaskExecutionContext.Interface;\n tasksCrud: TasksCrud.Interface;\n taskController: TaskController.Interface;\n getTaskDefinition: GetTaskDefinitionUseCase.Interface;\n}\n\nexport class TaskControl implements ITaskControl {\n public readonly runner: ITaskRunner;\n public readonly response: IResponse;\n public readonly context: Context;\n private readonly deps: ITaskControlDependencies;\n\n public constructor(\n runner: ITaskRunner,\n response: IResponse,\n context: Context,\n deps: ITaskControlDependencies\n ) {\n this.runner = runner;\n this.context = context;\n this.response = response;\n this.deps = deps;\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.deps.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.deps.getTaskDefinition.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 tasksCrud: this.deps.tasksCrud,\n task,\n log: taskLog,\n databaseLogs\n });\n\n // Populate TaskExecutionContext BEFORE executing task\n const executionContext = this.deps.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 taskController: this.deps.taskController,\n identityContext: this.deps.identityContext\n });\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, definition });\n } catch (ex) {\n this.deps.logger.error(\n { error: getErrorProperties(ex), taskId: task.id, hook: \"onError\" },\n \"Error executing task lifecycle hook.\"\n );\n }\n } else if (result.status === TaskResultStatus.DONE && definition.onDone) {\n try {\n await definition.onDone({ task, definition });\n } catch (ex) {\n this.deps.logger.error(\n { error: getErrorProperties(ex), taskId: task.id, hook: \"onDone\" },\n \"Error executing task lifecycle hook.\"\n );\n }\n }\n }\n\n private async getTask<T extends TaskDefinition.TaskInput>(id: string): Promise<ITask<T>> {\n try {\n const task = await this.deps.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.deps.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.deps.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","deps","event","taskId","task","AuthenticatedIdentity","error","getErrorProperties","definitionResult","definition","databaseLogs","taskLog","TaskDataStatus","store","TaskManagerStore","executionContext","TaskResponse","manager","TaskManager","databaseResponse","DatabaseResponse","result","responseResult","ex","TaskResultStatus","id","params","currentIteration"],"mappings":"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"}
@@ -2,10 +2,21 @@ import type { ITaskManager, ITaskManagerStorePrivate } from "./abstractions/inde
2
2
  import type { Context } from "../../api/types.js";
3
3
  import type { IResponse, IResponseResult } from "../../api/response/abstractions/index.js";
4
4
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
5
+ import { TaskController } from "@webiny/api-core/features/task/TaskController/abstractions.js";
6
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
7
+ /**
8
+ * What TaskManager needs from the container. Same reasoning as ITaskControlDependencies: the class
9
+ * is built by hand, so it states what it uses and the caller supplies it.
10
+ */
11
+ export interface ITaskManagerDependencies {
12
+ taskController: TaskController.Interface;
13
+ identityContext: IdentityContext.Interface;
14
+ }
5
15
  export declare class TaskManager implements ITaskManager {
6
16
  private readonly context;
7
17
  private readonly response;
8
18
  private readonly store;
9
- constructor(context: Context, response: IResponse, store: ITaskManagerStorePrivate);
19
+ private readonly deps;
20
+ constructor(context: Context, response: IResponse, store: ITaskManagerStorePrivate, deps: ITaskManagerDependencies);
10
21
  run(definition: TaskDefinition.Runnable): Promise<IResponseResult>;
11
22
  }
@@ -1,13 +1,12 @@
1
1
  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
- import { TaskController } from "@webiny/api-core/features/task/TaskController/abstractions.js";
5
- import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/abstractions.js";
6
4
  class TaskManager {
7
- constructor(context, response, store){
5
+ constructor(context, response, store, deps){
8
6
  this.context = context;
9
7
  this.response = response;
10
8
  this.store = store;
9
+ this.deps = deps;
11
10
  }
12
11
  async run(definition) {
13
12
  if (this.store.getStatus() === TaskDataStatus.ABORTED) return this.response.aborted();
@@ -26,7 +25,8 @@ class TaskManager {
26
25
  }
27
26
  else if (this.store.getTask().iterations >= definition.maxIterations) try {
28
27
  if (definition.onMaxIterations) await definition.onMaxIterations({
29
- task: this.store.getTask()
28
+ task: this.store.getTask(),
29
+ definition
30
30
  });
31
31
  return this.response.error({
32
32
  error: {
@@ -53,10 +53,11 @@ class TaskManager {
53
53
  let result;
54
54
  try {
55
55
  const input = structuredClone(this.store.getInput());
56
- const controller = this.context.container.resolve(TaskController);
57
- result = await this.context.container.resolve(IdentityContext).withoutAuthorization(async ()=>await definition.run({
56
+ const controller = this.deps.taskController;
57
+ result = await this.deps.identityContext.withoutAuthorization(async ()=>await definition.run({
58
58
  input,
59
- controller
59
+ controller,
60
+ definition
60
61
  }));
61
62
  } catch (ex) {
62
63
  return this.response.error({
@@ -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\";\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
+ {"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\n/**\n * What TaskManager needs from the container. Same reasoning as ITaskControlDependencies: the class\n * is built by hand, so it states what it uses and the caller supplies it.\n */\nexport interface ITaskManagerDependencies {\n taskController: TaskController.Interface;\n identityContext: IdentityContext.Interface;\n}\n\nexport class TaskManager implements ITaskManager {\n private readonly context: Context;\n private readonly response: IResponse;\n private readonly store: ITaskManagerStorePrivate;\n\n private readonly deps: ITaskManagerDependencies;\n\n public constructor(\n context: Context,\n response: IResponse,\n store: ITaskManagerStorePrivate,\n deps: ITaskManagerDependencies\n ) {\n this.context = context;\n this.response = response;\n this.store = store;\n this.deps = deps;\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 definition\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.deps.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.deps.identityContext.withoutAuthorization(async () => {\n return await definition.run({\n input,\n controller,\n definition\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","deps","definition","TaskDataStatus","Date","error","ex","getErrorProperties","task","result","input","structuredClone","controller","TaskResultStatus"],"mappings":";;;AAqBO,MAAMA;IAOT,YACIC,OAAgB,EAChBC,QAAmB,EACnBC,KAA+B,EAC/BC,IAA8B,CAChC;QACE,IAAI,CAAC,OAAO,GAAGH;QACf,IAAI,CAAC,QAAQ,GAAGC;QAChB,IAAI,CAAC,KAAK,GAAGC;QACb,IAAI,CAAC,IAAI,GAAGC;IAChB;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;gBACxBA;YACJ;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,IAAI,CAAC,cAAc;YAI3CH,SAAS,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,UACnD,MAAMP,WAAW,GAAG,CAAC;oBACxBQ;oBACAE;oBACAV;gBACJ;QAER,EAAE,OAAOI,IAAI;YACT,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvB,OAAOC,mBAAmBD;YAC9B;QACJ;QAGA,IAAIG,OAAO,MAAM,KAAKI,iBAAiB,QAAQ,EAC3C,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC1B,OAAOJ,OAAO,KAAK;YACnB,MAAMA,OAAO,IAAI;QACrB;QACG,IAAIA,OAAO,MAAM,KAAKI,iBAAiB,KAAK,EAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,OAAOJ,OAAO,KAAK;QACvB;QACG,IAAIA,OAAO,MAAM,KAAKI,iBAAiB,OAAO,EACjD,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO;QAEhC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YACtB,SAASJ,OAAO,OAAO;YACvB,QAAQA,OAAO,MAAM;QACzB;IACJ;AACJ"}
@@ -1,4 +1,5 @@
1
1
  import type { ITask, ITaskDataInput, ITaskLog, ITaskManagerStoreInfoLog, ITaskManagerStorePrivate, ITaskManagerStoreSetOutputOptions, ITaskManagerStoreUpdateTaskInputOptions, ITaskManagerStoreUpdateTaskOptions, TaskDataStatus } from "../../api/types.js";
2
+ import { TasksCrud } from "../../api/TasksCrud.js";
2
3
  import type { Container } from "@webiny/feature/api";
3
4
  import type { ITaskManagerStoreAddLogOptions, ITaskManagerStoreErrorLog, ITaskManagerStoreUpdateTaskInputParam, ITaskManagerStoreUpdateTaskParams } from "./abstractions/index.js";
4
5
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
@@ -10,9 +11,15 @@ export interface ITaskManagerStoreParams {
10
11
  task: ITask;
11
12
  log: ITaskLog;
12
13
  databaseLogs: boolean;
14
+ /**
15
+ * Supplied by the caller rather than pulled from `context.container`, so the store's one real
16
+ * collaborator is visible in its signature and a test can substitute it.
17
+ */
18
+ tasksCrud: TasksCrud.Interface;
13
19
  }
14
20
  export declare class TaskManagerStore<T extends ITaskDataInput = ITaskDataInput, O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput> implements ITaskManagerStorePrivate<T, O> {
15
21
  private readonly context;
22
+ private readonly tasksCrud;
16
23
  private task;
17
24
  private taskLog;
18
25
  private readonly databaseLogs;
@@ -1,4 +1,3 @@
1
- import { TasksCrud } from "../TasksCrud.js";
2
1
  import { TaskLogItemType } from "../types.js";
3
2
  import deep_equal from "deep-equal";
4
3
  import { getObjectProperties } from "../utils/getObjectProperties.js";
@@ -15,6 +14,7 @@ class TaskManagerStore {
15
14
  this.taskUpdater = new ObjectUpdater();
16
15
  this.taskLogUpdater = new ObjectUpdater();
17
16
  this.context = params.context;
17
+ this.tasksCrud = params.tasksCrud;
18
18
  this.task = params.task;
19
19
  this.taskLog = params.log;
20
20
  this.databaseLogs = true === params.databaseLogs;
@@ -30,7 +30,7 @@ class TaskManagerStore {
30
30
  parentId: this.task.id
31
31
  };
32
32
  if (definitionId) where.definitionId = definitionId;
33
- const result = await this.context.container.resolve(TasksCrud).listTasks({
33
+ const result = await this.tasksCrud.listTasks({
34
34
  where,
35
35
  sort: [
36
36
  "createdOn_ASC"
@@ -100,7 +100,7 @@ class TaskManagerStore {
100
100
  await this.save();
101
101
  }
102
102
  async save() {
103
- const tasksCrud = this.context.container.resolve(TasksCrud);
103
+ const tasksCrud = this.tasksCrud;
104
104
  if (this.taskUpdater.isDirty()) this.task = await tasksCrud.updateTask(this.task.id, this.taskUpdater.fetch());
105
105
  if (!this.databaseLogs) return;
106
106
  if (this.taskLogUpdater.isDirty()) this.taskLog = await tasksCrud.updateLog(this.taskLog.id, this.taskLogUpdater.fetch());
@@ -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 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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"}
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 * Supplied by the caller rather than pulled from `context.container`, so the store's one real\n * collaborator is visible in its signature and a test can substitute it.\n */\n tasksCrud: TasksCrud.Interface;\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 readonly tasksCrud: TasksCrud.Interface;\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.tasksCrud = params.tasksCrud;\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.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.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","param","options","data","deepEqual","values","log","TaskLogItemType","Date","console","Error","getObjectProperties","tasksCrud"],"mappings":"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"}
@@ -1,6 +1,12 @@
1
1
  import { Response, ResponseErrorResult } from "../response/index.js";
2
2
  import { TaskControl } from "./TaskControl.js";
3
3
  import { getErrorProperties } from "../utils/getErrorProperties.js";
4
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
5
+ import { TaskController } from "@webiny/api-core/features/task/TaskController/abstractions.js";
6
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
7
+ import { TaskExecutionContext } from "../features/TaskExecutionContext/index.js";
8
+ import { TasksCrud } from "../TasksCrud.js";
9
+ import { GetTaskDefinitionUseCase } from "../features/GetTaskDefinition/abstractions.js";
4
10
  const transformMinutesIntoMilliseconds = (minutes)=>60000 * minutes;
5
11
  const DEFAULT_TASKS_TIMEOUT_CLOSE_MINUTES = 3;
6
12
  class TaskRunner {
@@ -30,15 +36,30 @@ class TaskRunner {
30
36
  input: {},
31
37
  wait: rawEvent.delay
32
38
  });
33
- const control = new TaskControl(this, response, this.context);
39
+ const container = this.context.container;
40
+ const deps = {
41
+ logger: container.resolve(Logger),
42
+ identityContext: container.resolve(IdentityContext),
43
+ taskExecutionContext: container.resolve(TaskExecutionContext),
44
+ tasksCrud: container.resolve(TasksCrud),
45
+ taskController: container.resolve(TaskController),
46
+ getTaskDefinition: container.resolve(GetTaskDefinitionUseCase)
47
+ };
48
+ const logger = deps.logger;
49
+ const control = new TaskControl(this, response, this.context, deps);
34
50
  try {
35
51
  const result = await control.run(event);
36
52
  if (result instanceof ResponseErrorResult === false) return result;
37
- console.error(result);
53
+ logger.error({
54
+ taskId: event.webinyTaskId,
55
+ result
56
+ }, "Task returned an error result.");
38
57
  return result;
39
58
  } catch (ex) {
40
- console.error(`Failed to execute task "${event.webinyTaskId}".`);
41
- console.error(ex);
59
+ logger.error({
60
+ error: getErrorProperties(ex),
61
+ taskId: event.webinyTaskId
62
+ }, "Failed to execute task.");
42
63
  return response.error({
43
64
  error: getErrorProperties(ex)
44
65
  });
@@ -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 { 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
+ {"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\";\nimport { Logger } from \"@webiny/api-core/features/logger/index.js\";\nimport { TaskController } from \"@webiny/api-core/features/task/TaskController/abstractions.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { TaskExecutionContext } from \"~/api/features/TaskExecutionContext/index.js\";\nimport { TasksCrud } from \"~/api/TasksCrud.js\";\nimport { GetTaskDefinitionUseCase } from \"~/api/features/GetTaskDefinition/abstractions.js\";\nimport type { ITaskControlDependencies } from \"./TaskControl.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 // Resolved here, where the control's collaborators are assembled. TaskControl is built\n // by hand rather than by DI, so this is the one place that knows how to satisfy it; doing\n // it inside TaskControl's methods instead would leave the class with dependencies nothing\n // reading its signature can see, and nothing in a test can substitute.\n const container = this.context.container;\n const deps: ITaskControlDependencies = {\n logger: container.resolve(Logger),\n identityContext: container.resolve(IdentityContext),\n taskExecutionContext: container.resolve(TaskExecutionContext),\n tasksCrud: container.resolve(TasksCrud),\n taskController: container.resolve(TaskController),\n getTaskDefinition: container.resolve(GetTaskDefinitionUseCase)\n };\n const logger = deps.logger;\n const control = new TaskControl(this, response, this.context, deps);\n\n try {\n const result = await control.run(event);\n if (result instanceof ResponseErrorResult === false) {\n return result;\n }\n logger.error({ taskId: event.webinyTaskId, result }, \"Task returned an error result.\");\n return result;\n } catch (ex) {\n logger.error(\n { error: getErrorProperties(ex), taskId: event.webinyTaskId },\n \"Failed to execute task.\"\n );\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","container","deps","Logger","IdentityContext","TaskExecutionContext","TasksCrud","TaskController","GetTaskDefinitionUseCase","logger","control","TaskControl","result","ResponseErrorResult","value","parseInt","process"],"mappings":";;;;;;;;;AAgBA,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;QAOJ,MAAMM,YAAY,IAAI,CAAC,OAAO,CAAC,SAAS;QACxC,MAAMC,OAAiC;YACnC,QAAQD,UAAU,OAAO,CAACE;YAC1B,iBAAiBF,UAAU,OAAO,CAACG;YACnC,sBAAsBH,UAAU,OAAO,CAACI;YACxC,WAAWJ,UAAU,OAAO,CAACK;YAC7B,gBAAgBL,UAAU,OAAO,CAACM;YAClC,mBAAmBN,UAAU,OAAO,CAACO;QACzC;QACA,MAAMC,SAASP,KAAK,MAAM;QAC1B,MAAMQ,UAAU,IAAIC,YAAY,IAAI,EAAEf,UAAU,IAAI,CAAC,OAAO,EAAEM;QAE9D,IAAI;YACA,MAAMU,SAAS,MAAMF,QAAQ,GAAG,CAACZ;YACjC,IAAIc,kBAAkBC,wBAAwB,OAC1C,OAAOD;YAEXH,OAAO,KAAK,CAAC;gBAAE,QAAQX,MAAM,YAAY;gBAAEc;YAAO,GAAG;YACrD,OAAOA;QACX,EAAE,OAAOb,IAAI;YACTU,OAAO,KAAK,CACR;gBAAE,OAAOT,mBAAmBD;gBAAK,QAAQD,MAAM,YAAY;YAAC,GAC5D;YAEJ,OAAOF,SAAS,KAAK,CAAC;gBAClB,OAAOI,mBAAmBD;YAC9B;QACJ;IACJ;IAEQ,kCAAkC;QACtC,MAAMe,QAAQC,SAASC,QAAQ,GAAG,CAAC,qCAAqC,IAAI;QAC5E,MAAMJ,SAASE,QAAQ,IAAIA,QAAQ1B;QACnC,OAAOF,iCAAiC0B;IAC5C;AACJ"}
@@ -1,9 +1,17 @@
1
- import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
1
+ import { TaskDefinition, TaskHandler } from "@webiny/api-core/features/task/TaskDefinition/index.js";
2
+ declare class TestingRunTaskHandler implements TaskHandler.Interface {
3
+ run({ controller }: TaskHandler.RunParams): Promise<TaskDefinition.ResultDone<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
4
+ }
5
+ export declare const TestingRunTaskHandlerImplementation: typeof TestingRunTaskHandler & {
6
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskHandler<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
7
+ };
2
8
  declare class TestingRunTask implements TaskDefinition.Interface {
3
9
  id: string;
4
10
  title: string;
5
11
  description: string;
6
- run({ controller }: TaskDefinition.RunParams): Promise<TaskDefinition.ResultDone<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
12
+ handler: typeof TestingRunTaskHandler & {
13
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskHandler<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
14
+ };
7
15
  }
8
16
  export declare const TestingRunTaskDefinition: typeof TestingRunTask & {
9
17
  __abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskDefinition<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
@@ -1,18 +1,25 @@
1
- import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
2
- class TestingRunTask {
1
+ import { TaskDefinition, TaskHandler } from "@webiny/api-core/features/task/TaskDefinition/index.js";
2
+ class TestingRunTaskHandler {
3
3
  async run({ controller }) {
4
4
  return controller.response.done("Task successfully finished.");
5
5
  }
6
+ }
7
+ const TestingRunTaskHandlerImplementation = TaskHandler.createImplementation({
8
+ implementation: TestingRunTaskHandler,
9
+ dependencies: []
10
+ });
11
+ class TestingRunTask {
6
12
  constructor(){
7
13
  this.id = "testingRun";
8
14
  this.title = "Test Step Function Permissions";
9
15
  this.description = "A task to test the step function permissions.";
16
+ this.handler = TestingRunTaskHandlerImplementation;
10
17
  }
11
18
  }
12
19
  const TestingRunTaskDefinition = TaskDefinition.createImplementation({
13
20
  implementation: TestingRunTask,
14
21
  dependencies: []
15
22
  });
16
- export { TestingRunTaskDefinition };
23
+ export { TestingRunTaskDefinition, TestingRunTaskHandlerImplementation };
17
24
 
18
25
  //# sourceMappingURL=testingRunTask.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api/tasks/testingRunTask.js","sources":["../../../src/api/tasks/testingRunTask.ts"],"sourcesContent":["import { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nclass TestingRunTask implements TaskDefinition.Interface {\n id = \"testingRun\";\n title = \"Test Step Function Permissions\";\n description = \"A task to test the step function permissions.\";\n\n async run({ controller }: TaskDefinition.RunParams) {\n return controller.response.done(\"Task successfully finished.\");\n }\n}\n\nexport const TestingRunTaskDefinition = TaskDefinition.createImplementation({\n implementation: TestingRunTask,\n dependencies: []\n});\n"],"names":["TestingRunTask","controller","TestingRunTaskDefinition","TaskDefinition"],"mappings":";AAEA,MAAMA;IAKF,MAAM,IAAI,EAAEC,UAAU,EAA4B,EAAE;QAChD,OAAOA,WAAW,QAAQ,CAAC,IAAI,CAAC;IACpC;;aANA,EAAE,GAAG;aACL,KAAK,GAAG;aACR,WAAW,GAAG;;AAKlB;AAEO,MAAMC,2BAA2BC,eAAe,oBAAoB,CAAC;IACxE,gBAAgBH;IAChB,cAAc,EAAE;AACpB"}
1
+ {"version":3,"file":"api/tasks/testingRunTask.js","sources":["../../../src/api/tasks/testingRunTask.ts"],"sourcesContent":["import {\n TaskDefinition,\n TaskHandler\n} from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nclass TestingRunTaskHandler implements TaskHandler.Interface {\n async run({ controller }: TaskHandler.RunParams) {\n return controller.response.done(\"Task successfully finished.\");\n }\n}\n\nexport const TestingRunTaskHandlerImplementation = TaskHandler.createImplementation({\n implementation: TestingRunTaskHandler,\n dependencies: []\n});\n\nclass TestingRunTask implements TaskDefinition.Interface {\n id = \"testingRun\";\n title = \"Test Step Function Permissions\";\n description = \"A task to test the step function permissions.\";\n handler = TestingRunTaskHandlerImplementation;\n}\n\nexport const TestingRunTaskDefinition = TaskDefinition.createImplementation({\n implementation: TestingRunTask,\n dependencies: []\n});\n"],"names":["TestingRunTaskHandler","controller","TestingRunTaskHandlerImplementation","TaskHandler","TestingRunTask","TestingRunTaskDefinition","TaskDefinition"],"mappings":";AAKA,MAAMA;IACF,MAAM,IAAI,EAAEC,UAAU,EAAyB,EAAE;QAC7C,OAAOA,WAAW,QAAQ,CAAC,IAAI,CAAC;IACpC;AACJ;AAEO,MAAMC,sCAAsCC,YAAY,oBAAoB,CAAC;IAChF,gBAAgBH;IAChB,cAAc,EAAE;AACpB;AAEA,MAAMI;;aACF,EAAE,GAAG;aACL,KAAK,GAAG;aACR,WAAW,GAAG;aACd,OAAO,GAAGF;;AACd;AAEO,MAAMG,2BAA2BC,eAAe,oBAAoB,CAAC;IACxE,gBAAgBF;IAChB,cAAc,EAAE;AACpB"}