Search in sources :

Example 1 with ScheduleUpdateDetail

use of co.cask.cdap.proto.ScheduleUpdateDetail in project cdap by caskdata.

the class ProgramLifecycleHttpHandler method toScheduleDetail.

private ScheduleDetail toScheduleDetail(ScheduleUpdateDetail updateDetail, ProgramSchedule existing) {
    ScheduleUpdateDetail.Schedule scheduleUpdate = updateDetail.getSchedule();
    if (scheduleUpdate == null) {
        return new ScheduleDetail(null, null, null, updateDetail.getProperties(), null, null, null);
    }
    Trigger trigger = null;
    if (scheduleUpdate.getCronExpression() != null && (scheduleUpdate.getStreamName() != null || scheduleUpdate.getDataTriggerMB() != null)) {
        throw new IllegalArgumentException(String.format("Cannot define time trigger with cron expression and define stream size trigger with" + " stream name and data trigger configuration in the same schedule update details %s. " + "Schedule update detail must contain only one trigger.", updateDetail));
    }
    NamespaceId namespaceId = existing.getProgramId().getNamespaceId();
    if (scheduleUpdate.getCronExpression() != null) {
        trigger = new TimeTrigger(updateDetail.getSchedule().getCronExpression());
    } else if (existing.getTrigger() instanceof StreamSizeTrigger) {
        // if the existing trigger is StreamSizeTrigger, use the field in the existing trigger if the corresponding field
        // in schedule update detail is null
        StreamSizeTrigger existingTrigger = (StreamSizeTrigger) existing.getTrigger();
        String streamName = Objects.firstNonNull(scheduleUpdate.getStreamName(), existingTrigger.getStreamId().getStream());
        int dataTriggerMB = Objects.firstNonNull(scheduleUpdate.getDataTriggerMB(), existingTrigger.getTriggerMB());
        trigger = new StreamSizeTrigger(namespaceId.stream(streamName), dataTriggerMB);
    } else if (scheduleUpdate.getStreamName() != null && scheduleUpdate.getDataTriggerMB() != null) {
        trigger = new StreamSizeTrigger(namespaceId.stream(scheduleUpdate.getStreamName()), scheduleUpdate.getDataTriggerMB());
    } else if (scheduleUpdate.getStreamName() != null || scheduleUpdate.getDataTriggerMB() != null) {
        throw new IllegalArgumentException(String.format("Only one of stream name and data trigger MB is defined in schedule update details %s. " + "Must provide both stream name and data trigger MB to update the existing schedule with " + "trigger of type %s to a schedule with stream size trigger.", updateDetail, existing.getTrigger().getClass()));
    }
    List<Constraint> constraints = toConstraints(scheduleUpdate.getRunConstraints());
    return new ScheduleDetail(null, scheduleUpdate.getDescription(), null, updateDetail.getProperties(), trigger, constraints, null);
}
Also used : StreamSizeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.StreamSizeTrigger) TimeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.TimeTrigger) Trigger(co.cask.cdap.internal.schedule.trigger.Trigger) TimeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.TimeTrigger) Constraint(co.cask.cdap.internal.schedule.constraint.Constraint) ProtoConstraint(co.cask.cdap.proto.ProtoConstraint) StreamSizeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.StreamSizeTrigger) ScheduleDetail(co.cask.cdap.proto.ScheduleDetail) NamespaceId(co.cask.cdap.proto.id.NamespaceId) ScheduleUpdateDetail(co.cask.cdap.proto.ScheduleUpdateDetail)

Example 2 with ScheduleUpdateDetail

use of co.cask.cdap.proto.ScheduleUpdateDetail in project cdap by caskdata.

the class ProgramLifecycleHttpHandlerTest method testUpdateSchedule.

private void testUpdateSchedule(ApplicationId appV2Id) throws Exception {
    // intentionally keep two ScheduleUpdateDetail's to test backward compatibility
    ScheduleUpdateDetail scheduleUpdateDetail = new ScheduleUpdateDetail("updatedDescription", new RunConstraints(5), "0 4 * * *", null, null, ImmutableMap.of("twoKey", "twoValue", "someKey", "newValue"));
    ScheduleUpdateDetail invalidUpdateDetail = new ScheduleUpdateDetail("updatedDescription", null, null, "streamName", null, ImmutableMap.<String, String>of());
    ScheduleDetail validScheduleDetail = new ScheduleDetail(AppWithSchedule.SCHEDULE, "updatedDescription", null, ImmutableMap.<String, String>of(), new StreamSizeTrigger(new NamespaceId(TEST_NAMESPACE1).stream(AppWithSchedule.STREAM), 10), ImmutableList.<Constraint>of(new ConcurrencyConstraint(5)), null);
    // trying to update schedule for a non-existing app should fail
    HttpResponse response = updateSchedule(TEST_NAMESPACE1, "nonExistingApp", null, AppWithSchedule.SCHEDULE, scheduleUpdateDetail);
    Assert.assertEquals(HttpResponseStatus.NOT_FOUND.getCode(), response.getStatusLine().getStatusCode());
    // trying to update a non-existing schedule should fail
    response = updateSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, "NonExistingSchedule", scheduleUpdateDetail);
    Assert.assertEquals(HttpResponseStatus.NOT_FOUND.getCode(), response.getStatusLine().getStatusCode());
    // trying to update a time schedule with stream schedule detail containing null dataTriggerMB should fail
    response = updateSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, AppWithSchedule.SCHEDULE, invalidUpdateDetail);
    Assert.assertEquals(HttpResponseStatus.BAD_REQUEST.getCode(), response.getStatusLine().getStatusCode());
    // trying to update a time schedule with stream schedule detail containing both
    // stream name and dataTriggerMB should succeed
    response = updateSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, AppWithSchedule.SCHEDULE, validScheduleDetail);
    Assert.assertEquals(HttpResponseStatus.OK.getCode(), response.getStatusLine().getStatusCode());
    // should be able to update an existing stream size schedule with a valid new time schedule
    response = updateSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, AppWithSchedule.SCHEDULE, scheduleUpdateDetail);
    Assert.assertEquals(HttpResponseStatus.OK.getCode(), response.getStatusLine().getStatusCode());
    // verify that the schedule information for updated
    ScheduleDetail schedule = getSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, AppWithSchedule.SCHEDULE);
    Assert.assertEquals("updatedDescription", schedule.getDescription());
    Assert.assertEquals("0 4 * * *", ((TimeTrigger) schedule.getTrigger()).getCronExpression());
    Assert.assertEquals(new ProtoConstraint.ConcurrencyConstraint(5), schedule.getConstraints().get(0));
    // the properties should have been replaced
    Assert.assertEquals(2, schedule.getProperties().size());
    Assert.assertEquals("newValue", schedule.getProperties().get("someKey"));
    Assert.assertEquals("twoValue", schedule.getProperties().get("twoKey"));
    // the old property should not exist
    Assert.assertNull(schedule.getProperties().get("oneKey"));
    // the above update should not have affected the schedule for the other version of the app
    schedule = getSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, appV2Id.getVersion(), AppWithSchedule.SCHEDULE);
    Assert.assertNotEquals("updatedDescription", schedule.getDescription());
    Assert.assertEquals("0/15 * * * * ?", ((TimeTrigger) schedule.getTrigger()).getCronExpression());
    // try to update the schedule again but this time with property as null. It should retain the old properties
    ScheduleDetail scheduleDetail = new ScheduleDetail(AppWithSchedule.SCHEDULE, "updatedDescription", null, null, new TimeTrigger("0 4 * * *"), null, null);
    response = updateSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, AppWithSchedule.SCHEDULE, scheduleDetail);
    Assert.assertEquals(HttpResponseStatus.OK.getCode(), response.getStatusLine().getStatusCode());
    schedule = getSchedule(TEST_NAMESPACE1, AppWithSchedule.NAME, null, AppWithSchedule.SCHEDULE);
    Assert.assertEquals(2, schedule.getProperties().size());
    Assert.assertEquals("newValue", schedule.getProperties().get("someKey"));
    Assert.assertEquals("twoValue", schedule.getProperties().get("twoKey"));
    Assert.assertEquals(new ProtoConstraint.ConcurrencyConstraint(5), schedule.getConstraints().get(0));
}
Also used : ConcurrencyConstraint(co.cask.cdap.internal.app.runtime.schedule.constraint.ConcurrencyConstraint) ProtoConstraint(co.cask.cdap.proto.ProtoConstraint) TimeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.TimeTrigger) StreamSizeTrigger(co.cask.cdap.internal.app.runtime.schedule.trigger.StreamSizeTrigger) HttpResponse(org.apache.http.HttpResponse) ScheduleDetail(co.cask.cdap.proto.ScheduleDetail) NamespaceId(co.cask.cdap.proto.id.NamespaceId) RunConstraints(co.cask.cdap.api.schedule.RunConstraints) ScheduleUpdateDetail(co.cask.cdap.proto.ScheduleUpdateDetail)

Example 3 with ScheduleUpdateDetail

use of co.cask.cdap.proto.ScheduleUpdateDetail 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);
}
Also used : ProgramSchedule(co.cask.cdap.internal.app.runtime.schedule.ProgramSchedule) JsonElement(com.google.gson.JsonElement) ScheduleDetail(co.cask.cdap.proto.ScheduleDetail) ScheduleId(co.cask.cdap.proto.id.ScheduleId) ApplicationId(co.cask.cdap.proto.id.ApplicationId) ScheduleUpdateDetail(co.cask.cdap.proto.ScheduleUpdateDetail)

Aggregations

ScheduleDetail (co.cask.cdap.proto.ScheduleDetail)3 ScheduleUpdateDetail (co.cask.cdap.proto.ScheduleUpdateDetail)3 StreamSizeTrigger (co.cask.cdap.internal.app.runtime.schedule.trigger.StreamSizeTrigger)2 TimeTrigger (co.cask.cdap.internal.app.runtime.schedule.trigger.TimeTrigger)2 ProtoConstraint (co.cask.cdap.proto.ProtoConstraint)2 NamespaceId (co.cask.cdap.proto.id.NamespaceId)2 RunConstraints (co.cask.cdap.api.schedule.RunConstraints)1 ProgramSchedule (co.cask.cdap.internal.app.runtime.schedule.ProgramSchedule)1 ConcurrencyConstraint (co.cask.cdap.internal.app.runtime.schedule.constraint.ConcurrencyConstraint)1 Constraint (co.cask.cdap.internal.schedule.constraint.Constraint)1 Trigger (co.cask.cdap.internal.schedule.trigger.Trigger)1 ApplicationId (co.cask.cdap.proto.id.ApplicationId)1 ScheduleId (co.cask.cdap.proto.id.ScheduleId)1 JsonElement (com.google.gson.JsonElement)1 HttpResponse (org.apache.http.HttpResponse)1