use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method doUpdateSchedule.
private void doUpdateSchedule(FullHttpRequest request, HttpResponder responder, String namespaceId, String appId, String appVersion, String scheduleName) throws Exception {
ScheduleId scheduleId = new ApplicationId(namespaceId, appId, appVersion).schedule(scheduleName);
ScheduleDetail scheduleDetail = readScheduleDetailBody(request, scheduleName);
programScheduleService.update(scheduleId, scheduleDetail);
responder.sendStatus(HttpResponseStatus.OK);
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method getProgramStatusSchedules.
/**
* Get schedules containing {@link ProgramStatusTrigger} filtered by triggering program, and optionally by
* triggering program statuses or schedule status
* @param triggerNamespaceId namespace of the triggering program in {@link ProgramStatusTrigger}
* @param triggerAppName application name of the triggering program in {@link ProgramStatusTrigger}
* @param triggerAppVersion application version of the triggering program in {@link ProgramStatusTrigger}
* @param triggerProgramType program type of the triggering program in {@link ProgramStatusTrigger}
* @param triggerProgramName program name of the triggering program in {@link ProgramStatusTrigger}
* @param triggerProgramStatuses comma separated {@link ProgramStatus} in {@link ProgramStatusTrigger}.
* Schedules with {@link ProgramStatusTrigger} triggered by none of the
* {@link ProgramStatus} in triggerProgramStatuses will be filtered out.
* If not specified, schedules will be returned regardless of triggering program status.
* @param scheduleStatus status of the schedule. Can only be one of "SCHEDULED" or "SUSPENDED".
* If specified, only schedules with matching status will be returned.
*/
@GET
@Path("schedules/trigger-type/program-status")
public void getProgramStatusSchedules(HttpRequest request, HttpResponder responder, @QueryParam("trigger-namespace-id") String triggerNamespaceId, @QueryParam("trigger-app-name") String triggerAppName, @QueryParam("trigger-app-version") @DefaultValue(ApplicationId.DEFAULT_VERSION) String triggerAppVersion, @QueryParam("trigger-program-type") String triggerProgramType, @QueryParam("trigger-program-name") String triggerProgramName, @QueryParam("trigger-program-statuses") String triggerProgramStatuses, @QueryParam("schedule-status") String scheduleStatus) throws Exception {
if (triggerNamespaceId == null) {
throw new BadRequestException("Must specify trigger-namespace-id as a query param");
}
if (triggerAppName == null) {
throw new BadRequestException("Must specify trigger-app-name as a query param");
}
if (triggerProgramType == null) {
throw new BadRequestException("Must specify trigger-program-type as a query param");
}
if (triggerProgramName == null) {
throw new BadRequestException("Must specify trigger-program-name as a query param");
}
ProgramType programType;
try {
programType = ProgramType.valueOfCategoryName(triggerProgramType);
} catch (IllegalArgumentException e) {
throw new BadRequestException(e.getMessage(), e);
}
ProgramScheduleStatus programScheduleStatus;
try {
programScheduleStatus = scheduleStatus == null ? null : ProgramScheduleStatus.valueOf(scheduleStatus);
} catch (IllegalArgumentException e) {
throw new BadRequestException(String.format("Invalid schedule status '%s'. Must be one of %s.", scheduleStatus, Joiner.on(',').join(ProgramScheduleStatus.values())), e);
}
ProgramId triggerProgramId = new NamespaceId(triggerNamespaceId).app(triggerAppName, triggerAppVersion).program(programType, triggerProgramName);
Set<co.cask.cdap.api.ProgramStatus> queryProgramStatuses = new HashSet<>();
if (triggerProgramStatuses != null) {
try {
for (String status : triggerProgramStatuses.split(",")) {
queryProgramStatuses.add(co.cask.cdap.api.ProgramStatus.valueOf(status));
}
} catch (Exception e) {
throw new BadRequestException(String.format("Unable to parse program statuses '%s'. Must be comma separated " + "valid ProgramStatus names such as COMPLETED, FAILED, KILLED.", triggerProgramStatuses), e);
}
} else {
// Query for schedules with all the statuses if no query status is specified
Collections.addAll(queryProgramStatuses, co.cask.cdap.api.ProgramStatus.values());
}
List<ScheduleDetail> details = programScheduleService.findTriggeredBy(triggerProgramId, queryProgramStatuses).stream().filter(record -> programScheduleStatus == null || record.getMeta().getStatus().equals(programScheduleStatus)).map(ProgramScheduleRecord::toScheduleDetail).collect(Collectors.toList());
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(details, Schedulers.SCHEDULE_DETAILS_TYPE));
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method doAddSchedule.
private void doAddSchedule(FullHttpRequest request, HttpResponder responder, String namespace, String appName, String appVersion, String scheduleName) throws Exception {
final ApplicationId applicationId = new ApplicationId(namespace, appName, appVersion);
ScheduleDetail scheduleFromRequest = readScheduleDetailBody(request, scheduleName);
if (scheduleFromRequest.getProgram() == null) {
throw new BadRequestException("No program was specified for the schedule");
}
if (scheduleFromRequest.getProgram().getProgramType() == null) {
throw new BadRequestException("No program type was specified for the schedule");
}
if (scheduleFromRequest.getProgram().getProgramName() == null) {
throw new BadRequestException("No program name was specified for the schedule");
}
if (scheduleFromRequest.getTrigger() == null) {
throw new BadRequestException("No trigger was specified for the schedule");
}
ProgramType programType = ProgramType.valueOfSchedulableType(scheduleFromRequest.getProgram().getProgramType());
String programName = scheduleFromRequest.getProgram().getProgramName();
ProgramId programId = applicationId.program(programType, programName);
if (!lifecycleService.programExists(programId)) {
throw new NotFoundException(programId);
}
String description = Objects.firstNonNull(scheduleFromRequest.getDescription(), "");
Map<String, String> properties = Objects.firstNonNull(scheduleFromRequest.getProperties(), EMPTY_PROPERTIES);
List<? extends Constraint> constraints = Objects.firstNonNull(scheduleFromRequest.getConstraints(), NO_CONSTRAINTS);
long timeoutMillis = Objects.firstNonNull(scheduleFromRequest.getTimeoutMillis(), Schedulers.JOB_QUEUE_TIMEOUT_MILLIS);
ProgramSchedule schedule = new ProgramSchedule(scheduleName, description, programId, properties, scheduleFromRequest.getTrigger(), constraints, timeoutMillis);
programScheduleService.add(schedule);
responder.sendStatus(HttpResponseStatus.OK);
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method readScheduleDetailBody.
private ScheduleDetail readScheduleDetailBody(FullHttpRequest request, String scheduleName) throws BadRequestException, IOException {
JsonElement json;
try (Reader reader = new InputStreamReader(new ByteBufInputStream(request.content()), Charsets.UTF_8)) {
// The schedule spec in the request body does not contain the program information
json = DECODE_GSON.fromJson(reader, JsonElement.class);
} catch (IOException e) {
throw new IOException("Error reading request body", e);
} catch (JsonSyntaxException e) {
throw new BadRequestException("Request body is invalid json: " + e.getMessage());
}
if (!json.isJsonObject()) {
throw new BadRequestException("Expected a json object in the request body but received " + GSON.toJson(json));
}
ScheduleDetail scheduleDetail;
try {
scheduleDetail = DECODE_GSON.fromJson(json, ScheduleDetail.class);
} catch (JsonSyntaxException e) {
throw new BadRequestException("Error parsing request body as a schedule specification: " + e.getMessage());
}
// If the schedule name is present in the request body, it should match the name in path params
if (scheduleDetail.getName() != null && !scheduleName.equals(scheduleDetail.getName())) {
throw new BadRequestException(String.format("Schedule name in the body of the request (%s) does not match the schedule name in the path parameter (%s)", scheduleDetail.getName(), scheduleName));
}
return scheduleDetail;
}
use of co.cask.cdap.proto.ScheduleDetail in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method doUpdateSchedule.
private void doUpdateSchedule(HttpRequest request, HttpResponder responder, String namespaceId, String appId, String appVersion, String scheduleName) throws BadRequestException, IOException, NotFoundException {
ScheduleId scheduleId = new ApplicationId(namespaceId, appId, appVersion).schedule(scheduleName);
final ProgramSchedule existingSchedule = programScheduler.getSchedule(scheduleId);
ScheduleDetail scheduleDetail = readScheduleDetailBody(request, scheduleName, true, new Function<JsonElement, ScheduleDetail>() {
@Override
public ScheduleDetail apply(@Nullable JsonElement input) {
ScheduleUpdateDetail updateDetail = GSON.fromJson(input, ScheduleUpdateDetail.class);
return toScheduleDetail(updateDetail, existingSchedule);
}
});
ProgramSchedule updatedSchedule = combineForUpdate(scheduleDetail, existingSchedule);
programScheduler.updateSchedule(updatedSchedule);
responder.sendStatus(HttpResponseStatus.OK);
}
Aggregations