Skip to content
This repository was archived by the owner on May 14, 2025. It is now read-only.

Commit b4980ef

Browse files
authored
Enhance docs for the Task Launcher (#5084)
* Add readme for task launcher * Update instructions for launching CTR for streams
1 parent 8dba0c3 commit b4980ef

File tree

2 files changed

+165
-37
lines changed

2 files changed

+165
-37
lines changed

spring-cloud-dataflow-docs/src/main/asciidoc/tasks.adoc

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,15 +1059,15 @@ Then `DDD` and `EEE` would run in parallel.
10591059
[[spring-cloud-dataflow-launch-tasks-from-stream]]
10601060
== Launching Tasks from a Stream
10611061

1062-
You can launch a task from a stream by using the https://github.com/spring-cloud-stream-app-starters/tasklauncher-dataflow/blob/master/spring-cloud-starter-stream-sink-task-launcher-dataflow/README.adoc[`task-launcher-dataflow`] sink.
1062+
You can launch a task from a stream by using the https://github.com/spring-cloud/spring-cloud-dataflow/tree/main/spring-cloud-dataflow-tasklauncher/README.adoc[`task-launcher-dataflow`] sink which is provided as a part of the Spring Cloud Data Flow project.
10631063
The sink connects to a Data Flow server and uses its REST API to launch any defined task.
1064-
The sink accepts a https://github.com/spring-cloud-stream-app-starters/tasklauncher-dataflow/blob/master/spring-cloud-starter-stream-sink-task-launcher-dataflow/README.adoc#payload[JSON payload] representing a `task launch request`, which provides the name of the task to launch and may include command line arguments and deployment properties.
1064+
The sink accepts a https://github.com/spring-cloud/spring-cloud-dataflow/tree/main/spring-cloud-dataflow-tasklauncher/README.adoc#payload[JSON payload] representing a `task launch request`, which provides the name of the task to launch and may include command line arguments and deployment properties.
10651065

1066-
The https://github.com/spring-cloud-stream-app-starters/core/blob/master/common/app-starters-task-launch-request-common/README.adoc[`app-starters-task-launch-request-common`] component, in conjunction with Spring Cloud Stream https://docs.spring.io/spring-cloud-stream/docs/current-snapshot/reference/htmlsingle/#_functional_composition[functional composition], can transform the output of any source or processor to a task launch request.
1066+
The https://github.com/spring-cloud/stream-applications/tree/main/functions/function/task-launch-request-function/README.adoc[`task-launch-request-function`] component, in conjunction with Spring Cloud Stream https://docs.spring.io/spring-cloud-stream/docs/current-snapshot/reference/htmlsingle/#_functional_composition[functional composition], can transform the output of any source or processor to a task launch request.
10671067

1068-
Adding a dependency to `app-starters-task-launch-request-common` auto-configures a `java.util.function.Function` implementation, registered through https://cloud.spring.io/spring-cloud-function/[Spring Cloud Function] as a `taskLaunchRequest`.
1068+
Adding a dependency to `task-launch-request-function` auto-configures a `java.util.function.Function` implementation, registered through https://cloud.spring.io/spring-cloud-function/[Spring Cloud Function] as a `taskLaunchRequest`.
10691069

1070-
For example, you can start with the https://github.com/spring-cloud-stream-app-starters/time/tree/master/spring-cloud-starter-stream-source-time[time] source, add the following dependency, build it, and register it as a custom source. We call it `time-tlr` in this example:
1070+
For example, you can start with the https://github.com/spring-cloud/stream-applications/tree/main/applications/source/time-source[time] source, add the following dependency, build it, and register it as a custom source.
10711071

10721072
====
10731073
[source,xml]
@@ -1079,14 +1079,16 @@ For example, you can start with the https://github.com/spring-cloud-stream-app-s
10791079
----
10801080
====
10811081

1082-
TIP: https://start-scs.cfapps.io/[Spring Cloud Stream Initializr] provides a great starting point for creating stream applications.
1082+
To build the application follow the instructions https://github.com/spring-cloud/stream-applications#building-stream-applications[here].
10831083

1084-
Next, <<applications.adoc#applications, register>> the `task-launcher-dataflow` sink and create a task (we use the provided timestamp task):
1084+
This will create an `apps` directory that contains `time-source-rabbit` and `time-source-kafka` directories in the `<stream app project>/applications/source/time-source` directory. In each of these you will see a target directory that contains a `time-source-<binder>-<version>.jar`. Now register the `time-source` jar (use the appropriate binder jar) with SCDF as a time source named `timestamp-tlr`.
1085+
1086+
Next, register the `task-launcher-dataflow` sink with SCDF and create a task definition `timestamp-task`. Once this is complete create the stream definition as shown below:
10851087

10861088
====
10871089
[source,bash]
10881090
----
1089-
stream create --name task-every-minute --definition "time-tlr --trigger.fixed-delay=60 --spring.cloud.stream.function.definition=taskLaunchRequest --task.launch.request.task-name=timestamp-task | task-launcher-dataflow" --deploy
1091+
stream create --name task-every-minute --definition 'timestamp-tlr --fixed-delay=60000 --task.launch.request.task-name=timestamp-task --spring.cloud.function.definition=\"timeSupplier|taskLaunchRequestFunction\"| tasklauncher-sink' --deploy
10901092
----
10911093
====
10921094

@@ -1097,7 +1099,7 @@ The following stream definition illustrates the use of command line arguments. I
10971099
====
10981100
[source,bash]
10991101
----
1100-
stream create --name task-every-second --definition "time-tlr --spring.cloud.stream.function.definition=taskLaunchRequest --task.launch.request.task-name=timestamp-task --task.launch.request.args=foo=bar --task.launch.request.arg-expressions=time=payload | task-launcher-dataflow" --deploy
1102+
stream create --name task-every-second --definition 'timestamp-tlr --task.launch.request.task-name=timestamp-task --spring.cloud.function.definition=\"timeSupplier|taskLaunchRequestFunction\" --task.launch.request.args=foo=bar --task.launch.request.arg-expressions=time=payload | tasklauncher-sink' --deploy
11011103
----
11021104
====
11031105

@@ -1109,14 +1111,14 @@ You can then see the list of task executions by using the shell command `task ex
11091111
[source,bash,options="nowrap"]
11101112
----
11111113
dataflow:>task execution list
1112-
╔════════════════════╤══╤════════════════════════════╤════════════════════════════╤═════════╗
1113-
Task Name │ID│ Start Time │ End Time │Exit Code║
1114-
╠════════════════════╪══╪════════════════════════════╪════════════════════════════╪═════════╣
1115-
║timestamp-task_26176│4 │Tue May 02 12:13:49 EDT 2017│Tue May 02 12:13:49 EDT 2017│0 ║
1116-
║timestamp-task_32996│3 │Tue May 02 12:12:49 EDT 2017│Tue May 02 12:12:49 EDT 2017│0 ║
1117-
║timestamp-task_58971│2 │Tue May 02 12:11:50 EDT 2017│Tue May 02 12:11:50 EDT 2017│0 ║
1118-
║timestamp-task_13467│1 │Tue May 02 12:10:50 EDT 2017│Tue May 02 12:10:50 EDT 2017│0 ║
1119-
╚════════════════════╧══╧════════════════════════════╧════════════════════════════╧═════════╝
1114+
╔══════════════╤═══╤════════════════════════════╤════════════════════════════╤═════════╗
1115+
║ Task Name │ID │ Start Time │ End Time │Exit Code║
1116+
╠══════════════╪═══╪════════════════════════════╪════════════════════════════╪═════════╣
1117+
║timestamp-task│581│Thu Sep 08 11:38:33 EDT 2022│Thu Sep 08 11:38:33 EDT 2022│0 ║
1118+
║timestamp-task│580│Thu Sep 08 11:38:31 EDT 2022│Thu Sep 08 11:38:31 EDT 2022│0 ║
1119+
║timestamp-task│579│Thu Sep 08 11:38:29 EDT 2022│Thu Sep 08 11:38:29 EDT 2022│0 ║
1120+
║timestamp-task│578│Thu Sep 08 11:38:26 EDT 2022│Thu Sep 08 11:38:26 EDT 2022│0 ║
1121+
╚══════════════╧═══╧════════════════════════════╧════════════════════════════╧═════════╝
11201122
----
11211123
====
11221124

@@ -1128,43 +1130,30 @@ This pattern may be applied to any source to launch a task in response to any ev
11281130
A composed task can be launched with the `task-launcher-dataflow` sink, as discussed <<spring-cloud-dataflow-launch-tasks-from-stream, here>>.
11291131
Since we use the `ComposedTaskRunner` directly, we need to set up the task definitions for the composed task runner itself, along with the composed tasks, prior to the creation of the composed task launching stream.
11301132
Suppose we wanted to create the following composed task definition: `AAA && BBB`.
1131-
The first step would be to create the task definitions, as shown in the following example:
1133+
The first step would be to create the task definition, as shown in the following example:
11321134

11331135
====
11341136
[source]
11351137
----
1136-
task create composed-task-runner --definition "composed-task-runner"
1137-
task create AAA --definition "timestamp"
1138-
task create BBB --definition "timestamp"
1138+
task create --name composed-task-sample --definition "AAA: timestamp && BBB: timestamp"
11391139
----
11401140
====
11411141

1142-
NOTE: Releases of `ComposedTaskRunner` can be found
1143-
https://github.com/spring-cloud-task-app-starters/composed-task-runner/releases[here].
1144-
1145-
Now that the task definitions we need for composed task definition are ready, we need to create a stream that launches `ComposedTaskRunner`.
1146-
So, in this case, we create a stream with:
1142+
Now that the task definition we need for composed task definition is ready, we need to create a stream that launches `composed-task-sample`.
1143+
We create a stream with:
11471144

1148-
* The `time` source customized to emit task launch requests, as shown <<spring-cloud-dataflow-launch-tasks-from-stream, earlier>>.
1149-
* The `task-launcher-dataflow` sink that launches the `ComposedTaskRunner`
1145+
* The `timestamp-tlr` source customized to emit task launch requests, as shown <<spring-cloud-dataflow-launch-tasks-from-stream, earlier>>.
1146+
* The `task-launcher` sink that launches the `composed-task-sample`
11501147

11511148
The stream should resemble the following:
11521149

11531150
====
11541151
[source]
11551152
----
1156-
stream create ctr-stream --definition "time --fixed-delay=30 --task.launch.request.task-name=composed-task-launcher --task.launch.request.args=--graph=AAA&&BBB,--increment-instance-enabled=true | task-launcher-dataflow"
1153+
stream create --name ctr-stream --definition "timestamp-tlr --fixed-delay=30000 --spring.cloud.function.definition=\"timeSupplier|taskLaunchRequestFunction\" --task.launch.request.task-name=composed-task-sample | tasklauncher-sink" --deploy
11571154
----
11581155
====
11591156

1160-
For now, we focus on the configuration that is required to launch the `ComposedTaskRunner`:
1161-
1162-
* `graph`: This is the graph that is to be executed by the `ComposedTaskRunner`.
1163-
In this case it is `AAA&&BBB`.
1164-
* `increment-instance-enabled`: This lets each execution of `ComposedTaskRunner` be unique.
1165-
`ComposedTaskRunner` is built by using https://projects.spring.io/spring-batch/[Spring Batch].
1166-
Thus, we want a new Job Instance for each launch of the `ComposedTaskRunner`.
1167-
To do this, we set `increment-instance-enabled` to be `true`.
11681157

11691158
[[sharing-spring-cloud-dataflows-datastore-with-tasks]]
11701159
== Sharing Spring Cloud Data Flow's Datastore with Tasks
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
//tag::ref-doc[]
2+
= Spring Cloud Data Flow Task Launcher Sink
3+
4+
This application launches a registered task definition using the Data Flow Server https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#api-guide-resources-task-executions-launching[REST API].
5+
6+
== Input
7+
8+
Launch request args including:
9+
10+
* the task name (required and created as a task with the target Data Flow Server)
11+
* deployment properties (key value pairs, optional).
12+
* program arguments for the task (a list, optional).
13+
14+
=== Headers:
15+
16+
* `Content-Type: application/json`
17+
18+
=== Payload:
19+
20+
A JSON document:
21+
22+
[source,json]
23+
----
24+
{
25+
"name":"foo",
26+
"deploymentProps": {"key1":"val1","key2":"val2"},
27+
"args":["--debug", "--foo", "bar"]
28+
}
29+
----
30+
31+
minimally,
32+
33+
[source,json]
34+
----
35+
{"name":"foo"}
36+
----
37+
38+
== Output
39+
40+
N/A (launches task on the SCDF server's task platform).
41+
42+
=== Options
43+
44+
The **$$Spring Cloud Data Flow Task Launcher$$** $$sink$$ supports the following configuration properties:
45+
46+
//tag::configuration-properties[]
47+
$$platform-name$$:: $$The Spring Cloud Data Flow platform to use for launching tasks.$$ *($$String$$, default: `$$default$$`)*
48+
$$spring.cloud.dataflow.client.authentication.access-token$$:: $$OAuth2 Access Token.$$ *($$String$$, default: `$$<none>$$`)*
49+
$$spring.cloud.dataflow.client.authentication.basic.password$$:: $$The login password.$$ *($$String$$, default: `$$<none>$$`)*
50+
$$spring.cloud.dataflow.client.authentication.basic.username$$:: $$The login username.$$ *($$String$$, default: `$$<none>$$`)*
51+
$$spring.cloud.dataflow.client.authentication.client-id$$:: $$OAuth2 Client Id.$$ *($$String$$, default: `$$<none>$$`)*
52+
$$spring.cloud.dataflow.client.authentication.client-secret$$:: $$OAuth2 Client Secret.$$ *($$String$$, default: `$$<none>$$`)*
53+
$$spring.cloud.dataflow.client.authentication.scope$$:: $$OAuth2 Scopes.$$ *($$Set<String>$$, default: `$$<none>$$`)*
54+
$$spring.cloud.dataflow.client.authentication.token-uri$$:: $$OAuth2 Token Uri.$$ *($$String$$, default: `$$<none>$$`)*
55+
$$spring.cloud.dataflow.client.enable-dsl$$:: $$Enable Data Flow DSL access.$$ *($$Boolean$$, default: `$$false$$`)*
56+
$$spring.cloud.dataflow.client.server-uri$$:: $$The Data Flow server URI.$$ *($$String$$, default: `$$http://localhost:9393$$`)*
57+
$$spring.cloud.dataflow.client.skip-ssl-validation$$:: $$Skip Ssl validation.$$ *($$Boolean$$, default: `$$false$$`)*
58+
$$trigger.initial-delay$$:: $$The initial delay in milliseconds.$$ *($$Integer$$, default: `$$1000$$`)*
59+
$$trigger.max-period$$:: $$The maximum polling period in milliseconds. Will be set to period if period > maxPeriod.$$ *($$Integer$$, default: `$$30000$$`)*
60+
$$trigger.period$$:: $$The polling period in milliseconds.$$ *($$Integer$$, default: `$$1000$$`)*
61+
//end::configuration-properties[]
62+
63+
== Using the TaskLauncher
64+
The Dataflow tasklauncher is a sink that consumes `TaskLaunchRequest` messages, as described above, and launches a task using the configured Spring Cloud Data Flow server (given by `--spring.cloud.dataflow.client.server-uri`).
65+
The task launcher periodically polls its input source for launch requests but will pause polling when the platform has reached it's concurrent task execution limit, given by `spring.cloud.dataflow.task.platform.<platform-type>.accounts[<account-name>].maximum-concurrent-tasks`.
66+
This prevents the SCDF deployer's deployment platform from exhausting its resources under heavy task load.
67+
The poller is scheduled using a `DynamicPeriodicTrigger`. By default the initial polling rate is 1 second, but may be configured to any duration. When polling is paused, or if there are no launch requests present, the trigger period will increase, applying exponential backoff, up to a configured maximum (30 seconds by default).
68+
69+
The SCDF server may be configured to launch tasks on multiple platforms.
70+
Each task launcher instance is configured for a single platform, given by the `platformName` property (`default` if not specified).
71+
This limitation is enforced because if the server has multiple task platforms configured, it may be the case that some of its task platforms are at the limit and some are not.
72+
In this situation, we can only consume the next launch request if we know for which task platform it is targeted.
73+
For this reason, if the SCDF server is configured for multiple task platforms (or a single non-default platform), we assume that all launch requests are targeted for that platform.
74+
The task launcher will set the required deployment property `spring.cloud.dataflow.task.platformName` if the request does not provide it.
75+
76+
NOTE: If the request includes the deployment property `spring.cloud.dataflow.task.platformName`, and the value is not the same as the tasklauncher's `platformName`, the task launcher will throw an exception.
77+
78+
To launch tasks on multiple platforms, you must configure a task launcher instance per platform and use a https://github.com/spring-cloud-stream-app-starters/router/tree/master/spring-cloud-starter-stream-sink-router[router sink], or https://docs.spring.io/spring-cloud-stream/docs/current/reference/htmlsingle/#partitioning[partitioning strategy], to route requests to the correct instance.
79+
80+
NOTE: When the poller is paused it puts pressure
81+
on the message broker so some tuning will be necessary in extreme cases to balance resource utilization.
82+
83+
=== Client Authentication
84+
85+
If the SCDF server requires authentication, the client must pass credentials with authorization to launch a task.
86+
The Data Flow client supports both basic and OAuth2 authentication.
87+
88+
For basic authentication set the username and password:
89+
90+
```
91+
--spring.cloud.dataflow.client.authentication.basic.username=<username> --spring.cloud.dataflow.client.authentication.basic.password=<password>
92+
```
93+
94+
For OAuth2 authentication, set the `client-id`, `client-secret`, and `token-uri` at a minimum. These values correspond to values set in the SCDF server's OAuth2 configuration.
95+
For more details, see https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#configuration-local-security[the Security section in the Data Flow reference].
96+
97+
```
98+
--spring.cloud.dataflow.client.authentication.client-id=<client-id> --spring.cloud.dataflow.client.authentication.client-secret=<client-secret> spring.cloud.dataflow.client.authentication.token-uri: <token-uri>
99+
```
100+
101+
102+
== Build
103+
104+
[source,bash]
105+
----
106+
$ ./mvnw clean install
107+
----
108+
109+
=== Examples
110+
111+
Register a task app and create a task, the
112+
https://github.com/spring-cloud/spring-cloud-task/tree/2.4.x/spring-cloud-task-samples/timestamp[timestamp sample]
113+
provides a simple demonstration.
114+
115+
[source,bash]
116+
----
117+
dataflow:>app register --name timestamp --type task --uri ...
118+
dataflow:>task create timestamp --definition timestamp
119+
dataflow:>stream create http --server.port=9000 | task-launcher-dataflow-sink --deploy
120+
----
121+
122+
Send a launch request,
123+
124+
[source,bash]
125+
----
126+
$curl http://localhost:9000 -H"Content-Type:application/json" -d '{"name":"timestamp"}'
127+
----
128+
129+
[source,bash]
130+
----
131+
dataflow:>task execution list
132+
╔═════════╤══╤════════════════════════════╤════════════════════════════╤═════════╗
133+
║Task Name│ID│ Start Time │ End Time │Exit Code║
134+
╠═════════╪══╪════════════════════════════╪════════════════════════════╪═════════╣
135+
║timestamp│1 │Fri Aug 10 08:48:05 EDT 2018│Fri Aug 10 08:48:05 EDT 2018│0 ║
136+
╚═════════╧══╧════════════════════════════╧════════════════════════════╧═════════╝
137+
----
138+
139+
//end::ref-doc[]

0 commit comments

Comments
 (0)