Skip to content

Commit a8d58ae

Browse files
committed
add bind tasks
1 parent f11dd7d commit a8d58ae

9 files changed

Lines changed: 134 additions & 139 deletions

File tree

x-pack/platform/plugins/shared/alerting_v2/server/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { bindOnStart } from './setup/bind_on_start';
1414
import { bindRoutes } from './setup/bind_routes';
1515
import { bindServices } from './setup/bind_services';
1616
import { bindRuleExecutionServices } from './setup/bind_rule_executor';
17+
import { bindTasks } from './setup/bind_tasks';
1718

1819
export const config: PluginConfigDescriptor<PluginConfig> = {
1920
schema: configSchema,
@@ -25,6 +26,7 @@ export const module = new ContainerModule((options) => {
2526
bindRoutes(options);
2627
bindServices(options);
2728
bindRuleExecutionServices(options);
29+
bindTasks(options);
2830
});
2931

3032
export type { PluginConfig as AlertingV2Config } from './config';

x-pack/platform/plugins/shared/alerting_v2/server/lib/dispatcher/task_definition.ts

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,21 @@
55
* 2.0.
66
*/
77

8-
import type { AlertingServerSetupDependencies } from '../../types';
9-
import type { TaskRunnerInternalFactory } from '../services/task_run_scope_service/create_task_runner_internal';
8+
import type { AlertingTaskDefinition } from '../services/task_run_scope_service/create_task_runner';
109
import { DispatcherTaskRunner } from './task_runner';
1110

1211
export const DISPATCHER_TASK_TYPE = 'alerting_v2:dispatcher' as const;
1312
export const DISPATCHER_TASK_ID = 'alerting_v2:dispatcher:1.0.0' as const;
1413

15-
export function registerDispatcherTaskDefinition({
16-
taskManager,
17-
taskRunnerInternalFactory,
18-
}: {
19-
taskManager: AlertingServerSetupDependencies['taskManager'];
20-
taskRunnerInternalFactory: TaskRunnerInternalFactory;
21-
}) {
22-
const createTaskRunner = taskRunnerInternalFactory({
23-
taskRunnerClass: DispatcherTaskRunner,
24-
});
25-
26-
taskManager.registerTaskDefinitions({
27-
[DISPATCHER_TASK_TYPE]: {
28-
title: 'Alerting v2 dispatcher (ES|QL)',
29-
timeout: '1m',
30-
maxAttempts: 1,
31-
createTaskRunner,
32-
},
33-
});
34-
}
14+
/**
15+
* Task definition for dispatcher.
16+
* Bound to TaskDefinition token and automatically registered with Task Manager on setup.
17+
*/
18+
export const DispatcherTaskDefinition: AlertingTaskDefinition<DispatcherTaskRunner> = {
19+
taskType: DISPATCHER_TASK_TYPE,
20+
title: 'Alerting v2 dispatcher (ES|QL)',
21+
timeout: '1m',
22+
maxAttempts: 1,
23+
taskRunnerClass: DispatcherTaskRunner,
24+
requiresFakeRequest: false,
25+
};

x-pack/platform/plugins/shared/alerting_v2/server/lib/rule_executor/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@
55
* 2.0.
66
*/
77

8-
export { registerRuleExecutorTaskDefinition } from './task_definition';
9-
export { ALERTING_RULE_EXECUTOR_TASK_TYPE } from './task_definition';
8+
export { RuleExecutorTaskDefinition, ALERTING_RULE_EXECUTOR_TASK_TYPE } from './task_definition';

x-pack/platform/plugins/shared/alerting_v2/server/lib/rule_executor/task_definition.ts

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,23 @@
77

88
import { schema } from '@kbn/config-schema';
99

10-
import type { AlertingServerSetupDependencies } from '../../types';
11-
import type { TaskRunnerFactory } from '../services/task_run_scope_service/create_task_runner';
10+
import type { AlertingTaskDefinition } from '../services/task_run_scope_service/create_task_runner';
1211
import { RuleExecutorTaskRunner } from './task_runner';
1312

1413
export const ALERTING_RULE_EXECUTOR_TASK_TYPE = 'alerting_v2:rule_executor' as const;
1514

16-
export function registerRuleExecutorTaskDefinition({
17-
taskManager,
18-
taskRunnerFactory,
19-
}: {
20-
taskManager: AlertingServerSetupDependencies['taskManager'];
21-
taskRunnerFactory: TaskRunnerFactory;
22-
}) {
23-
const createTaskRunner = taskRunnerFactory({
24-
taskRunnerClass: RuleExecutorTaskRunner,
25-
taskType: ALERTING_RULE_EXECUTOR_TASK_TYPE,
26-
});
27-
28-
taskManager.registerTaskDefinitions({
29-
[ALERTING_RULE_EXECUTOR_TASK_TYPE]: {
30-
title: 'Alerting v2 rule executor (ES|QL)',
31-
timeout: '5m',
32-
paramsSchema: schema.object({
33-
ruleId: schema.string(),
34-
spaceId: schema.string(),
35-
}),
36-
createTaskRunner,
37-
},
38-
});
39-
}
15+
/**
16+
* Task definition for rule executor.
17+
* Bound to TaskDefinition token and automatically registered with Task Manager on setup.
18+
*/
19+
export const RuleExecutorTaskDefinition: AlertingTaskDefinition<RuleExecutorTaskRunner> = {
20+
taskType: ALERTING_RULE_EXECUTOR_TASK_TYPE,
21+
title: 'Alerting v2 rule executor (ES|QL)',
22+
timeout: '5m',
23+
paramsSchema: schema.object({
24+
ruleId: schema.string(),
25+
spaceId: schema.string(),
26+
}),
27+
taskRunnerClass: RuleExecutorTaskRunner,
28+
requiresFakeRequest: true,
29+
};

x-pack/platform/plugins/shared/alerting_v2/server/lib/services/task_run_scope_service/create_task_runner.ts

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* 2.0.
66
*/
77

8+
import type { ObjectType } from '@kbn/config-schema';
89
import type { CoreDiServiceStart } from '@kbn/core-di';
910
import { Global } from '@kbn/core-di-internal';
1011
import { Request } from '@kbn/core-di-server';
@@ -24,35 +25,77 @@ export interface AlertingTaskRunner {
2425
}): Promise<RunResult>;
2526
}
2627

28+
/**
29+
* Task definition interface for alerting tasks.
30+
* Similar to Route definitions, task definitions are bound to the TaskDefinition token
31+
* and automatically registered with Task Manager on setup.
32+
*/
33+
export interface AlertingTaskDefinition<TRunner extends AlertingTaskRunner = AlertingTaskRunner> {
34+
taskType: string;
35+
title: string;
36+
timeout: string;
37+
paramsSchema?: ObjectType;
38+
maxAttempts?: number;
39+
taskRunnerClass: TaskRunnerConstructor<TRunner>;
40+
/**
41+
* Whether this task requires a fakeRequest from Task Manager.
42+
* Tasks scheduled with API keys have a fakeRequest that enables request-scoped services.
43+
* Set to false for tasks that only use internal/singleton-scoped services.
44+
* @default true
45+
*/
46+
requiresFakeRequest?: boolean;
47+
}
48+
49+
export const TaskDefinition = Symbol.for(
50+
'alerting_v2.TaskDefinition'
51+
) as ServiceIdentifier<AlertingTaskDefinition>;
52+
2753
export type TaskRunnerFactory = <TRunner extends AlertingTaskRunner>(params: {
2854
taskRunnerClass: TaskRunnerConstructor<TRunner>;
2955
taskType: string;
56+
requiresFakeRequest?: boolean;
3057
}) => TaskRunCreatorFunction;
3158

3259
export const TaskRunnerFactoryToken = Symbol.for(
3360
'alerting_v2.TaskRunnerFactory'
3461
) as ServiceIdentifier<TaskRunnerFactory>;
3562

36-
// Factory for task runners that depend on Task Manager fakeRequest.
37-
// It forks the DI container and overrides Request scope with the fake request.
63+
/**
64+
* Factory for task runners that creates scoped DI containers for each task execution.
65+
*
66+
* For tasks with `requiresFakeRequest: true` (default):
67+
* - Forks the DI container and binds the fakeRequest to Request scope
68+
* - Enables request-scoped services (e.g., scoped ES clients)
69+
* - Throws if no fakeRequest is available (task must be scheduled with API key)
70+
*
71+
* For tasks with `requiresFakeRequest: false`:
72+
* - Forks the DI container for isolation
73+
* - Does not bind Request scope
74+
* - Task runner can only use internal/singleton-scoped services
75+
*/
3876
export function createTaskRunnerFactory({
3977
getInjection,
4078
}: {
4179
getInjection: () => CoreDiServiceStart;
4280
}): TaskRunnerFactory {
43-
return ({ taskRunnerClass, taskType }) => {
81+
return ({ taskRunnerClass, taskType, requiresFakeRequest = true }) => {
4482
return ({ taskInstance, abortController, fakeRequest }: RunContext) => ({
4583
run: async () => {
46-
if (!fakeRequest) {
84+
if (requiresFakeRequest && !fakeRequest) {
4785
throw new Error(
4886
`Cannot execute ${taskType} task without Task Manager fakeRequest. Ensure the task is scheduled with an API key (task id: ${taskInstance.id})`
4987
);
5088
}
5189

5290
const scope = getInjection().fork();
53-
scope.bind(Request).toConstantValue(fakeRequest);
54-
scope.bind(Global).toConstantValue(Request);
55-
scope.bind(taskRunnerClass).toSelf().inRequestScope();
91+
92+
if (fakeRequest) {
93+
scope.bind(Request).toConstantValue(fakeRequest);
94+
scope.bind(Global).toConstantValue(Request);
95+
scope.bind(taskRunnerClass).toSelf().inRequestScope();
96+
} else {
97+
scope.bind(taskRunnerClass).toSelf().inTransientScope();
98+
}
5699

57100
try {
58101
const runner = scope.get(taskRunnerClass);

x-pack/platform/plugins/shared/alerting_v2/server/lib/services/task_run_scope_service/create_task_runner_internal.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

x-pack/platform/plugins/shared/alerting_v2/server/setup/bind_on_setup.ts

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,12 @@
55
* 2.0.
66
*/
77

8+
import type { ContainerModuleLoadOptions } from 'inversify';
89
import { Logger, OnSetup, PluginSetup } from '@kbn/core-di';
910
import { CoreSetup } from '@kbn/core-di-server';
10-
import type { ContainerModuleLoadOptions } from 'inversify';
11-
import { registerDispatcherTaskDefinition } from '../lib/dispatcher/task_definition';
12-
import { registerRuleExecutorTaskDefinition } from '../lib/rule_executor/task_definition';
1311
import { registerFeaturePrivileges } from '../lib/security/privileges';
14-
import { TaskRunnerFactoryToken } from '../lib/services/task_run_scope_service/create_task_runner';
15-
import { TaskRunnerInternalFactoryToken } from '../lib/services/task_run_scope_service/create_task_runner_internal';
1612
import { registerSavedObjects } from '../saved_objects';
17-
import type { AlertingServerSetupDependencies } from '../types';
13+
import { TaskDefinition } from '../lib/services/task_run_scope_service/create_task_runner';
1814

1915
export function bindOnSetup({ bind }: ContainerModuleLoadOptions) {
2016
bind(OnSetup).toConstantValue((container) => {
@@ -27,18 +23,7 @@ export function bindOnSetup({ bind }: ContainerModuleLoadOptions) {
2723
logger,
2824
});
2925

30-
const taskManager = container.get(
31-
PluginSetup<AlertingServerSetupDependencies['taskManager']>('taskManager')
32-
);
33-
34-
registerRuleExecutorTaskDefinition({
35-
taskManager,
36-
taskRunnerFactory: container.get(TaskRunnerFactoryToken),
37-
});
38-
39-
registerDispatcherTaskDefinition({
40-
taskManager,
41-
taskRunnerInternalFactory: container.get(TaskRunnerInternalFactoryToken),
42-
});
26+
// Trigger task registration via onActivation callbacks
27+
container.getAll(TaskDefinition);
4328
});
4429
}

x-pack/platform/plugins/shared/alerting_v2/server/setup/bind_services.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ import {
3434
createTaskRunnerFactory,
3535
TaskRunnerFactoryToken,
3636
} from '../lib/services/task_run_scope_service/create_task_runner';
37-
import {
38-
createTaskRunnerInternalFactory,
39-
TaskRunnerInternalFactoryToken,
40-
} from '../lib/services/task_run_scope_service/create_task_runner_internal';
4137

4238
export function bindServices({ bind }: ContainerModuleLoadOptions) {
4339
bind(AlertActionsClient).toSelf().inRequestScope();
@@ -70,12 +66,6 @@ export function bindServices({ bind }: ContainerModuleLoadOptions) {
7066
})
7167
);
7268

73-
bind(TaskRunnerInternalFactoryToken).toFactory((context) =>
74-
createTaskRunnerInternalFactory({
75-
getInjection: () => context.get(CoreStart('injection')),
76-
})
77-
);
78-
7969
bind(RulesSavedObjectService).toSelf().inRequestScope();
8070

8171
bind(QueryServiceScopedToken)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { ContainerModuleLoadOptions } from 'inversify';
9+
import { PluginSetup } from '@kbn/core-di';
10+
import {
11+
TaskDefinition,
12+
TaskRunnerFactoryToken,
13+
} from '../lib/services/task_run_scope_service/create_task_runner';
14+
import { RuleExecutorTaskDefinition } from '../lib/rule_executor/task_definition';
15+
import { DispatcherTaskDefinition } from '../lib/dispatcher/task_definition';
16+
import type { AlertingServerSetupDependencies } from '../types';
17+
18+
export function bindTasks({ bind, onActivation }: ContainerModuleLoadOptions) {
19+
// Register task with Task Manager when the binding is activated
20+
onActivation(TaskDefinition, ({ get }, definition) => {
21+
const taskManager = get(
22+
PluginSetup<AlertingServerSetupDependencies['taskManager']>('taskManager')
23+
);
24+
const taskRunnerFactory = get(TaskRunnerFactoryToken);
25+
26+
const createTaskRunner = taskRunnerFactory({
27+
taskRunnerClass: definition.taskRunnerClass,
28+
taskType: definition.taskType,
29+
requiresFakeRequest: definition.requiresFakeRequest,
30+
});
31+
32+
taskManager.registerTaskDefinitions({
33+
[definition.taskType]: {
34+
title: definition.title,
35+
timeout: definition.timeout,
36+
createTaskRunner,
37+
...(definition.paramsSchema && { paramsSchema: definition.paramsSchema }),
38+
...(definition.maxAttempts && { maxAttempts: definition.maxAttempts }),
39+
},
40+
});
41+
42+
return definition;
43+
});
44+
45+
// Bind task definitions
46+
bind(TaskDefinition).toConstantValue(RuleExecutorTaskDefinition);
47+
bind(TaskDefinition).toConstantValue(DispatcherTaskDefinition);
48+
}

0 commit comments

Comments
 (0)