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

Add task thin executions by name and fix missing docs. #5994

Merged
merged 7 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ void index() throws Exception {
linkWithRel("tasks/executions/external").description("Returns Task execution by external id"),
linkWithRel("tasks/executions/current").description("Provides the current count of running tasks"),
linkWithRel("tasks/thinexecutions").description("Returns thin Task executions"),
linkWithRel("tasks/thinexecutions/name").description("Returns thin Task executions for a given task name"),
linkWithRel("tasks/info/executions").description("Provides the task executions info"),
linkWithRel("tasks/schedules").description("Provides schedule information of tasks"),
linkWithRel("tasks/schedules/instances").description("Provides schedule information of a specific task "),
linkWithRel("tasks/executions/name").description("Returns all task executions for a given Task name"),
linkWithRel("tasks/executions/execution").description("Provides details for a specific task execution"),
linkWithRel("tasks/platforms").description("Provides platform accounts for launching tasks. The results can be filtered to show the platforms that support scheduling by adding a request parameter of 'schedulesEnabled=true"),
linkWithRel("tasks/logs").description("Retrieve the task application log"),
linkWithRel("tasks/thinexecutions").description("Returns thin Task executions"),

linkWithRel("streams/definitions").description("Exposes the Streams resource"),
linkWithRel("streams/definitions/definition").description("Handle a specific Stream definition"),
Expand Down Expand Up @@ -221,14 +221,15 @@ void index() throws Exception {

fieldWithPath("_links.tasks/thinexecutions.href").description("Link to the tasks/thinexecutions"),

fieldWithPath("_links.tasks/thinexecutions/name.href").description("Link to the tasks/thinexecutions/name"),
fieldWithPath("_links.tasks/thinexecutions/name.templated").description("Link to the tasks/thinexecutions/name is templated"),

fieldWithPath("_links.tasks/info/executions.href").description("Link to the tasks/info/executions"),
fieldWithPath("_links.tasks/info/executions.templated").type(JsonFieldType.BOOLEAN).optional().description("Link tasks/info is templated"),

fieldWithPath("_links.tasks/logs.href").description("Link to the tasks/logs"),
fieldWithPath("_links.tasks/logs.templated").type(JsonFieldType.BOOLEAN).optional().description("Link tasks/logs is templated"),

fieldWithPath("_links.tasks/thinexecutions.href").description("Link to the tasks/thinexecutions"),

fieldWithPath("_links.tasks/schedules.href").description("Link to the tasks/executions/schedules"),
fieldWithPath("_links.tasks/schedules/instances.href").description("Link to the tasks/schedules/instances"),
fieldWithPath("_links.tasks/schedules/instances.templated").type(JsonFieldType.BOOLEAN).optional().description("Link tasks/schedules/instances is templated"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ void listTaskThinExecutions() throws Exception {
}

@Test
void listTaskExecutionsByName() throws Exception {
void listTaskThinExecutionsByName() throws Exception {
this.mockMvc.perform(
get("/tasks/executions")
get("/tasks/thinexecutions")
.queryParam("name", "taskB")
.queryParam("page", "0")
.queryParam("size", "10")
Expand All @@ -328,11 +328,33 @@ void listTaskExecutionsByName() throws Exception {
parameterWithName("name")
.description("The name associated with the task execution")),
responseFields(
subsectionWithPath("_embedded.taskExecutionResourceList")
.description("Contains a collection of Task Executions/"),
subsectionWithPath("_embedded.taskExecutionThinResourceList")
.description("Contains a collection of thin Task Executions/"),
subsectionWithPath("_links.self").description("Link to the task execution resource"),
subsectionWithPath("page").description("Pagination properties"))));
}
@Test
void listTaskExecutionsByName() throws Exception {
this.mockMvc.perform(
get("/tasks/executions")
.queryParam("name", "taskB")
.queryParam("page", "0")
.queryParam("size", "10")
)
.andExpect(status().isOk()).andDo(this.documentationHandler.document(
queryParameters(
parameterWithName("page")
.description("The zero-based page number (optional)"),
parameterWithName("size")
.description("The requested page size (optional)"),
parameterWithName("name")
.description("The name associated with the task execution")),
responseFields(
subsectionWithPath("_embedded.taskExecutionResourceList")
.description("Contains a collection of Task Executions/"),
subsectionWithPath("_links.self").description("Link to the task execution resource"),
subsectionWithPath("page").description("Pagination properties"))));
}

@Test
void stopTask() throws Exception {
Expand Down
79 changes: 79 additions & 0 deletions spring-cloud-dataflow-docs/src/main/asciidoc/api-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2067,6 +2067,85 @@ include::{snippets}/task-executions-documentation/list-task-executions-by-name/c
include::{snippets}/task-executions-documentation/list-task-executions-by-name/http-response.adoc[]


[[api-guide-resources-task-thin-executions-list]]
==== List All Task Thin Executions

The task executions endpoint lets you list all task executions with only top-level data.
The following topics provide more details:

* <<api-guide-resources-task-thin-executions-list-request-structure>>
* <<api-guide-resources-task-thin-executions-list-request-parameters>>
* <<api-guide-resources-task-thin-executions-list-example-request>>
* <<api-guide-resources-task-thin-executions-list-response-structure>>



[[api-guide-resources-task-thin-executions-list-request-structure]]
===== Request Structure

include::{snippets}/task-executions-documentation/list-task-thin-executions/http-request.adoc[]



[[api-guide-resources-task-thin-executions-list-request-parameters]]
===== Request Parameters

include::{snippets}/task-executions-documentation/list-task-thin-executions/request-parameters.adoc[]



[[api-guide-resources-task-thin-executions-list-example-request]]
===== Example Request

include::{snippets}/task-executions-documentation/list-task-thin-executions/curl-request.adoc[]



[[api-guide-resources-task-thin-executions-list-response-structure]]
===== Response Structure

include::{snippets}/task-executions-documentation/list-task-thin-executions/http-response.adoc[]



[[api-guide-resources-task-thin-executions-list-by-name]]
==== List All Task Thin Executions With a Specified Task Name

The task thin executions endpoint lets you list task executions with a specified task name.
The following topics provide more details:

* <<api-guide-resources-task-thin-executions-list-by-name-request-structure>>
* <<api-guide-resources-task-thin-executions-list-by-name-request-parameters>>
* <<api-guide-resources-task-thin-executions-list-by-name-example-request>>
* <<api-guide-resources-task-thin-executions-list-by-name-response-structure>>



[[api-guide-resources-task-thin-executions-list-by-name-request-structure]]
===== Request Structure

include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/http-request.adoc[]



[[api-guide-resources-task-thin-executions-list-by-name-request-parameters]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you verify that the request parameters are being generated properly. I'm seeing,

Unresolved directive in api-guide.adoc - include::/Users/grenfro/project/spring-cloud-dataflow/spring-cloud-dataflow-docs/../spring-cloud-dataflow-classic-docs/target/generated-snippets/task-executions-documentation/list-task-thin-executions-by-name/request-parameters.adoc[]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found the issue that caused this. Created #6008 to record it. I'll fix all of them.

===== Request Parameters

include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/request-parameters.adoc[]



[[api-guide-resources-task-thin-executions-list-by-name-example-request]]
===== Example Request

include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/curl-request.adoc[]



[[api-guide-resources-task-thin-executions-list-by-name-response-structure]]
===== Response Structure

include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/http-response.adoc[]

[[api-guide-resources-task-executions-detail]]
==== Task Execution Detail
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ spring:
- DELETE /tasks/executions/* => hasRole('ROLE_DESTROY')

- GET /tasks/thinexecutions => hasRole('ROLE_VIEW')
- GET /tasks/thinexecutions/* => hasRole('ROLE_VIEW')

# Task Schedules

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ public interface TaskOperations {
*/
PagedModel<TaskExecutionThinResource> thinExecutionList();

/**
* List task executions filtered by task name.
* @return the page of task executions for the given task name.
*/
PagedModel<TaskExecutionThinResource> thinExecutionListByTaskName(String taskName);

/**
* List task executions known to the system filtered by task name.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ public class TaskTemplate implements TaskOperations {

private static final String THIN_EXECUTIONS_RELATION = "tasks/thinexecutions";

private static final String THIN_EXECUTIONS_BY_NAME_RELATION = "tasks/thinexecutions/name";

private static final String EXECUTIONS_CURRENT_RELATION = "tasks/executions/current";

private static final String EXECUTION_RELATION = "tasks/executions/execution";
Expand All @@ -97,6 +99,8 @@ public class TaskTemplate implements TaskOperations {

private final Link thinExecutionsLink;

private final Link thinExecutionsByNameLink;

private final Link executionLink;

private final Link executionLaunchLink;
Expand Down Expand Up @@ -160,6 +164,12 @@ public class TaskTemplate implements TaskOperations {
} else {
this.thinExecutionsLink = null;
}
if(resources.getLink(THIN_EXECUTIONS_BY_NAME_RELATION).isPresent()) {
this.thinExecutionsByNameLink = resources.getLink(THIN_EXECUTIONS_BY_NAME_RELATION).get();
} else {
this.thinExecutionsByNameLink = null;
}

if(resources.getLink(EXECUTION_LAUNCH_RELATION).isPresent()) {
this.executionLaunchLink = resources.getLink(EXECUTION_LAUNCH_RELATION).get();
} else {
Expand Down Expand Up @@ -275,6 +285,15 @@ public PagedModel<TaskExecutionThinResource> thinExecutionList() {
}
}

@Override
public PagedModel<TaskExecutionThinResource> thinExecutionListByTaskName(String taskName) {
if(thinExecutionsByNameLink != null) {
return restTemplate.getForObject(thinExecutionsByNameLink.expand(taskName).getHref(), TaskExecutionThinResource.Page.class);
} else {
return restTemplate.getForObject(executionByNameLink.expand(taskName).getHref(), TaskExecutionThinResource.Page.class);
}
}

@Override
public TaskExecutionResource.Page executionListByTaskName(String taskName) {
return restTemplate.getForObject(executionByNameLink.expand(taskName).getHref(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,8 @@ public TaskExecutionController taskExecutionController(
}

@Bean
public TaskExecutionThinController taskExecutionThinController(DataflowTaskExplorer taskExplorer) {
return new TaskExecutionThinController(taskExplorer);
public TaskExecutionThinController taskExecutionThinController(DataflowTaskExplorer taskExplorer, TaskDefinitionRepository taskDefinitionRepository) {
return new TaskExecutionThinController(taskExplorer, taskDefinitionRepository);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public RootResource info() {
root.add(linkTo(methodOn(TasksInfoController.class).getInfo(null, null, null)).withRel("tasks/info/executions"));
root.add(linkTo(methodOn(TaskLogsController.class).getLog(null, null)).withRel("tasks/logs"));
root.add(linkTo(methodOn(TaskExecutionThinController.class).listTasks(null, null)).withRel("tasks/thinexecutions"));
root.add(linkTo(methodOn(TaskExecutionThinController.class).retrieveTasksByName(null,null, null)).withRel("tasks/thinexecutions/name"));

if (featuresProperties.isSchedulesEnabled()) {
root.add(entityLinks.linkToCollectionResource(ScheduleInfoResource.class).withRel("tasks/schedules"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,11 @@ public PagedModel<TaskExecutionResource> retrieveTasksByName(
Pageable pageable,
PagedResourcesAssembler<TaskJobExecutionRel> assembler
) {
long tasks = this.taskDefinitionRepository.countByTaskName(taskName);
if(tasks == 0) {
throw new NoSuchTaskDefinitionException(taskName);
}
validatePageable(pageable);
this.taskDefinitionRepository.findById(taskName)
.orElseThrow(() -> new NoSuchTaskDefinitionException(taskName));
Page<TaskExecution> taskExecutions = this.explorer.findTaskExecutionsByName(taskName, pageable);
Page<TaskJobExecutionRel> result = getPageableRelationships(taskExecutions, pageable);
return assembler.toModel(result, this.taskAssembler);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import org.springframework.cloud.dataflow.core.ThinTaskExecution;
import org.springframework.cloud.dataflow.rest.resource.TaskExecutionThinResource;
import org.springframework.cloud.dataflow.server.repository.NoSuchTaskDefinitionException;
import org.springframework.cloud.dataflow.server.repository.TaskDefinitionRepository;
import org.springframework.cloud.dataflow.server.task.DataflowTaskExplorer;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.data.domain.Page;
Expand All @@ -30,6 +32,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -46,10 +49,12 @@
public class TaskExecutionThinController {

private final DataflowTaskExplorer explorer;
private final TaskDefinitionRepository taskDefinitionRepository;
private final TaskExecutionThinResourceAssembler resourceAssembler;

public TaskExecutionThinController(DataflowTaskExplorer explorer) {
public TaskExecutionThinController(DataflowTaskExplorer explorer, TaskDefinitionRepository taskDefinitionRepository) {
this.explorer = explorer;
this.taskDefinitionRepository = taskDefinitionRepository;
this.resourceAssembler = new TaskExecutionThinResourceAssembler();
}

Expand All @@ -62,6 +67,23 @@ public PagedModel<TaskExecutionThinResource> listTasks(Pageable pageable, PagedR
return pagedAssembler.toModel(thinTaskExecutions, resourceAssembler);
}

@GetMapping(value = "", params = "name")
@ResponseStatus(HttpStatus.OK)
public PagedModel<TaskExecutionThinResource> retrieveTasksByName(
@RequestParam("name") String taskName,
Pageable pageable,
PagedResourcesAssembler<ThinTaskExecution> pagedAssembler
) {
long tasks = this.taskDefinitionRepository.countByTaskName(taskName);
if(tasks == 0) {
throw new NoSuchTaskDefinitionException(taskName);
}
Page<TaskExecution> page = this.explorer.findTaskExecutionsByName(taskName, pageable);
Page<ThinTaskExecution> thinTaskExecutions = new PageImpl<>(page.stream().map(ThinTaskExecution::new).toList(), pageable, page.getTotalElements());
explorer.populateCtrStatus(thinTaskExecutions.getContent());
return pagedAssembler.toModel(thinTaskExecutions, resourceAssembler);
}

static class TaskExecutionThinResourceAssembler extends RepresentationModelAssemblerSupport<ThinTaskExecution, TaskExecutionThinResource> {
public TaskExecutionThinResourceAssembler() {
super(TaskExecutionThinController.class, TaskExecutionThinResource.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ public interface TaskDefinitionRepository extends KeyValueRepository<TaskDefinit
*/
TaskDefinition findByTaskName(String name);

long countByTaskName(String taskName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -522,20 +522,19 @@ private List<String> getTaskArguments(long taskExecutionId) {

@Override
public void populateCtrStatus(Collection<ThinTaskExecution> thinTaskExecutions) {
Map<Long, ThinTaskExecution> taskExecutionMap = thinTaskExecutions.stream()
if(!thinTaskExecutions.isEmpty()) {
Map<Long, ThinTaskExecution> taskExecutionMap = thinTaskExecutions.stream()
.collect(Collectors.toMap(ThinTaskExecution::getExecutionId, Function.identity()));
String ids = taskExecutionMap.keySet()
.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
String sql = FIND_CTR_STATUS.replace(":taskExecutionIds", ids);
jdbcTemplate.query(sql, rs -> {
Long id = rs.getLong("TASK_EXECUTION_ID");
String ctrStatus = rs.getString("CTR_STATUS");
logger.debug("populateCtrStatus:{}={}", id, ctrStatus);
ThinTaskExecution execution = taskExecutionMap.get(id);
Assert.notNull(execution, "Expected TaskExecution for " + id + " from " + ids);
execution.setCtrTaskStatus(ctrStatus);
});
String ids = taskExecutionMap.keySet().stream().map(Object::toString).collect(Collectors.joining(","));
String sql = FIND_CTR_STATUS.replace(":taskExecutionIds", ids);
jdbcTemplate.query(sql, rs -> {
Long id = rs.getLong("TASK_EXECUTION_ID");
String ctrStatus = rs.getString("CTR_STATUS");
logger.debug("populateCtrStatus:{}={}", id, ctrStatus);
ThinTaskExecution execution = taskExecutionMap.get(id);
Assert.notNull(execution, "Expected TaskExecution for " + id + " from " + ids);
execution.setCtrTaskStatus(ctrStatus);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ spring:
- GET /tasks/info/* => hasRole('ROLE_VIEW')

- GET /tasks/thinexecutions => hasRole('ROLE_VIEW')
- GET /tasks/thinexecutions/* => hasRole('ROLE_VIEW')

# Task Schedules

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ public TaskExecutionController taskExecutionController(
}

@Bean
public TaskExecutionThinController taskExecutionThinController(DataflowTaskExplorer dataflowTaskExplorer) {
return new TaskExecutionThinController(dataflowTaskExplorer);
public TaskExecutionThinController taskExecutionThinController(DataflowTaskExplorer dataflowTaskExplorer, TaskDefinitionRepository taskDefinitionRepository) {
return new TaskExecutionThinController(dataflowTaskExplorer, taskDefinitionRepository);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,8 @@ public TaskExecutionController taskExecutionController(
}

@Bean
public TaskExecutionThinController taskExecutionThinController(DataflowTaskExplorer dataflowTaskExplorer) {
return new TaskExecutionThinController(dataflowTaskExplorer);
public TaskExecutionThinController taskExecutionThinController(DataflowTaskExplorer dataflowTaskExplorer, TaskDefinitionRepository taskDefinitionRepository) {
return new TaskExecutionThinController(dataflowTaskExplorer, taskDefinitionRepository);
}
@Bean
public TasksInfoController taskExecutionsInfoController(TaskExecutionService taskExecutionService) {
Expand Down
Loading
Loading