{"action":"created","comment":{"url":"https://api.github.com/repos/caskdata/cdap/pulls/comments/24943097","id":24943097,"diff_hunk":"@@ -90,280 +94,150 @@ protected final void stopScheduler() {\n \n   @Override\n   public void schedule(Id.Program programId, SchedulableProgramType programType, Schedule schedule) {\n-    delegate.schedule(programId, programType, schedule);\n+    if (schedule instanceof TimeSchedule) {\n+      timeScheduler.schedule(programId, programType, schedule);\n+    } else if (schedule instanceof StreamSizeSchedule) {\n+      streamSizeScheduler.schedule(programId, programType, schedule);\n+    }\n+    throw new IllegalStateException(\"Unhandled type of schedule: \" + schedule.getClass());\n   }\n \n   @Override\n   public void schedule(Id.Program programId, SchedulableProgramType programType, Iterable<Schedule> schedules) {\n-    delegate.schedule(programId, programType, schedules);\n+    Set<Schedule> timeSchedules = Sets.newHashSet();\n+    Set<Schedule> streamSizeSchedules = Sets.newHashSet();\n+    for (Schedule schedule : schedules) {\n+      if (schedule instanceof TimeSchedule) {\n+        timeSchedules.add(schedule);\n+      } else if (schedule instanceof StreamSizeSchedule) {\n+        streamSizeSchedules.add(schedule);\n+      } else {\n+        throw new IllegalStateException(\"Unhandled type of schedule: \" + schedule.getClass());\n+      }\n+    }\n+    if (!timeSchedules.isEmpty()) {\n+      timeScheduler.schedule(programId, programType, timeSchedules);\n+    }\n+    if (!streamSizeSchedules.isEmpty()) {\n+      streamSizeScheduler.schedule(programId, programType, streamSizeSchedules);\n+    }\n   }\n \n   @Override\n   public List<ScheduledRuntime> nextScheduledRuntime(Id.Program program, SchedulableProgramType programType) {\n-   return delegate.nextScheduledRuntime(program, programType);\n+   return timeScheduler.nextScheduledRuntime(program, programType);\n   }\n \n   @Override\n   public List<String> getScheduleIds(Id.Program program, SchedulableProgramType programType) {\n-    return delegate.getScheduleIds(program, programType);\n+    return ImmutableList.<String>builder()\n+      .addAll(timeScheduler.getScheduleIds(program, programType))\n+      .addAll(streamSizeScheduler.getScheduleIds(program, programType))\n+      .build();\n   }\n \n   @Override\n   public void suspendSchedule(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-    delegate.suspendSchedule(program, programType, scheduleName);\n+    ScheduleType type = getScheduleType(program, programType, scheduleName);\n+    if (type == null) {\n+      return;\n+    }\n+    switch (type) {\n+      case TIME:\n+        timeScheduler.suspendSchedule(program, programType, scheduleName);\n+        break;\n+      case STREAM:\n+        streamSizeScheduler.suspendSchedule(program, programType, scheduleName);\n+        break;\n+    }\n   }\n \n   @Override\n   public void resumeSchedule(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-    delegate.resumeSchedule(program, programType, scheduleName);\n+    ScheduleType type = getScheduleType(program, programType, scheduleName);\n+    if (type == null) {\n+      return;\n+    }\n+    switch (type) {\n+      case TIME:\n+        timeScheduler.resumeSchedule(program, programType, scheduleName);\n+        break;\n+      case STREAM:\n+        streamSizeScheduler.resumeSchedule(program, programType, scheduleName);\n+        break;\n+    }\n   }\n \n   @Override\n   public void deleteSchedule(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-    delegate.deleteSchedule(program, programType, scheduleName);\n+    ScheduleType type = getScheduleType(program, programType, scheduleName);\n+    if (type == null) {\n+      return;\n+    }\n+    switch (type) {\n+      case TIME:\n+        timeScheduler.deleteSchedule(program, programType, scheduleName);\n+        break;\n+      case STREAM:\n+        streamSizeScheduler.deleteSchedule(program, programType, scheduleName);\n+        break;\n+    }\n   }\n \n   @Override\n   public void deleteSchedules(Id.Program program, SchedulableProgramType programType) {\n-    delegate.deleteSchedules(program, programType);\n+    timeScheduler.deleteSchedules(program, programType);\n+    streamSizeScheduler.deleteSchedules(program, programType);\n   }\n \n   @Override\n   public ScheduleState scheduleState (Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-    return delegate.scheduleState(program, programType, scheduleName);\n-  }\n-\n-  /**\n-   * class that wraps Quartz scheduler. Needed to delegate start stop operations to classes that extend\n-   * DefaultSchedulerService.\n-   */\n-  static final class WrappedScheduler implements co.cask.cdap.internal.app.runtime.schedule.Scheduler {\n-    private Scheduler scheduler;\n-    private final StoreFactory storeFactory;\n-    private final Supplier<Scheduler> schedulerSupplier;\n-    private final ProgramRuntimeService programRuntimeService;\n-    private final PreferencesStore preferencesStore;\n-\n-    WrappedScheduler(Supplier<Scheduler> schedulerSupplier, StoreFactory storeFactory,\n-                     ProgramRuntimeService programRuntimeService, PreferencesStore preferencesStore) {\n-      this.schedulerSupplier = schedulerSupplier;\n-      this.storeFactory = storeFactory;\n-      this.programRuntimeService = programRuntimeService;\n-      this.scheduler = null;\n-      this.preferencesStore = preferencesStore;\n-    }\n-\n-    void start() throws SchedulerException {\n-      scheduler = schedulerSupplier.get();\n-      scheduler.setJobFactory(createJobFactory(storeFactory.create()));\n-      scheduler.start();\n-    }\n-\n-    void stop() throws SchedulerException {\n-      if (scheduler != null) {\n-        scheduler.shutdown();\n-      }\n-    }\n-\n-    @Override\n-    public void schedule(Id.Program programId, SchedulableProgramType programType, Schedule schedule) {\n-      schedule(programId, programType, ImmutableList.of(schedule));\n-    }\n-\n-    // TODO remove this annotation once the Schedule class becomes abstract\n-    @Override\n-    public void schedule(Id.Program programId, SchedulableProgramType programType, Iterable<Schedule> schedules) {\n-      checkInitialized();\n-      Preconditions.checkNotNull(schedules);\n-\n-      String jobKey = getJobKey(programId, programType).getName();\n-      JobDetail job = JobBuilder.newJob(DefaultSchedulerService.ScheduledJob.class)\n-        .withIdentity(jobKey)\n-        .storeDurably(true)\n-        .build();\n-      try {\n-        scheduler.addJob(job, true);\n-      } catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n-      for (Schedule schedule : schedules) {\n-        Preconditions.checkArgument(schedule instanceof TimeSchedule);\n-        TimeSchedule timeSchedule = (TimeSchedule) schedule;\n-        String scheduleName = timeSchedule.getName();\n-        String cronEntry = timeSchedule.getCronEntry();\n-        String triggerKey = getScheduleId(programId, programType, scheduleName);\n-\n-        LOG.debug(\"Scheduling job {} with cron {}\", scheduleName, cronEntry);\n-\n-        Trigger trigger = TriggerBuilder.newTrigger()\n-          .withIdentity(triggerKey)\n-          .forJob(job)\n-          .withSchedule(CronScheduleBuilder\n-                          .cronSchedule(getQuartzCronExpression(cronEntry)))\n-          .build();\n-        try {\n-          scheduler.scheduleJob(trigger);\n-        } catch (SchedulerException e) {\n-          throw Throwables.propagate(e);\n-        }\n-      }\n-    }\n-\n-    @Override\n-    public List<ScheduledRuntime> nextScheduledRuntime(Id.Program program, SchedulableProgramType programType) {\n-      checkInitialized();\n-\n-      List<ScheduledRuntime> scheduledRuntimes = Lists.newArrayList();\n-      try {\n-        for (Trigger trigger : scheduler.getTriggersOfJob(getJobKey(program, programType))) {\n-          ScheduledRuntime runtime = new ScheduledRuntime(trigger.getKey().toString(),\n-                                                          trigger.getNextFireTime().getTime());\n-          scheduledRuntimes.add(runtime);\n-        }\n-      } catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n-      return scheduledRuntimes;\n-    }\n-\n-    @Override\n-    public List<String> getScheduleIds(Id.Program program, SchedulableProgramType programType) {\n-      checkInitialized();\n-\n-      List<String> scheduleIds = Lists.newArrayList();\n-      try {\n-        for (Trigger trigger : scheduler.getTriggersOfJob(getJobKey(program, programType))) {\n-          scheduleIds.add(trigger.getKey().getName());\n-        }\n-      }   catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n-      return scheduleIds;\n-    }\n-\n-\n-    @Override\n-    public void suspendSchedule(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-      checkInitialized();\n-      try {\n-        scheduler.pauseTrigger(new TriggerKey(getScheduleId(program, programType, scheduleName)));\n-      } catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n-    }\n-\n-    @Override\n-    public void resumeSchedule(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-      checkInitialized();\n-      try {\n-        scheduler.resumeTrigger(new TriggerKey(getScheduleId(program, programType, scheduleName)));\n-      } catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n-    }\n-\n-    @Override\n-    public void deleteSchedule(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-      checkInitialized();\n-      try {\n-        Trigger trigger = scheduler.getTrigger(new TriggerKey(getScheduleId(program, programType, scheduleName)));\n-        Preconditions.checkNotNull(trigger);\n-\n-        scheduler.unscheduleJob(trigger.getKey());\n-\n-        JobKey jobKey = trigger.getJobKey();\n-        if (scheduler.getTriggersOfJob(jobKey).isEmpty()) {\n-          scheduler.deleteJob(jobKey);\n-        }\n-      } catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n-    }\n-\n-    @Override\n-    public void deleteSchedules(Id.Program program, SchedulableProgramType programType) {\n-      checkInitialized();\n-      try {\n-        scheduler.deleteJob(getJobKey(program, programType));\n-      } catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n+    ScheduleType type = getScheduleType(program, programType, scheduleName);\n+    if (type == null) {\n+      throw new UnsupportedOperationException(\"Schedule could not be found in application specification\");\n     }\n-\n-    @Override\n-    public ScheduleState scheduleState(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-      checkInitialized();\n-      try {\n-        Trigger.TriggerState state = scheduler.getTriggerState(new TriggerKey(getScheduleId(program, programType,\n-                                                                                            scheduleName)));\n-        // Map trigger state to schedule state.\n-        // This method is only interested in returning if the scheduler is\n-        // Paused, Scheduled or NotFound.\n-        switch (state) {\n-          case NONE:\n-            return ScheduleState.NOT_FOUND;\n-          case PAUSED:\n-            return ScheduleState.SUSPENDED;\n-          default:\n-            return ScheduleState.SCHEDULED;\n-        }\n-      } catch (SchedulerException e) {\n-        throw Throwables.propagate(e);\n-      }\n+    switch (type) {\n+      case STREAM:\n+        return streamSizeScheduler.scheduleState(program, programType, scheduleName);\n+      case TIME:\n+        return timeScheduler.scheduleState(program, programType, scheduleName);\n     }\n+    throw new IllegalStateException(\"Unhandled type of schedule: \" + type);\n+  }\n \n-    private void checkInitialized() {\n-      Preconditions.checkNotNull(scheduler, \"Scheduler not yet initialized\");\n+  private Store getStore() {\n+    if (store == null) {\n+      store = storeFactory.create();\n     }\n+    return store;\n+  }\n \n-    private String getScheduleId(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n-      return String.format(\"%s:%s\", getJobKey(program, programType).getName(), scheduleName);\n+  private ScheduleType getScheduleType(Id.Program program, SchedulableProgramType programType, String scheduleName) {\n+    ApplicationSpecification appSpec = getStore().getApplication(program.getApplication());\n+    if (appSpec == null) {\n+      return null;","path":"cdap-app-fabric/src/main/java/co/cask/cdap/internal/app/runtime/schedule/AbstractSchedulerService.java","position":409,"original_position":408,"commit_id":"182d3bdc3e8649e57cc68d66159c796bfc593c54","original_commit_id":"7902c804e1a06f103c137c115c44f890592dfb07","user":{"login":"anew","id":483004,"avatar_url":"https://avatars.githubusercontent.com/u/483004?v=3","gravatar_id":"","url":"https://api.github.com/users/anew","html_url":"https://github.com/anew","followers_url":"https://api.github.com/users/anew/followers","following_url":"https://api.github.com/users/anew/following{/other_user}","gists_url":"https://api.github.com/users/anew/gists{/gist_id}","starred_url":"https://api.github.com/users/anew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anew/subscriptions","organizations_url":"https://api.github.com/users/anew/orgs","repos_url":"https://api.github.com/users/anew/repos","events_url":"https://api.github.com/users/anew/events{/privacy}","received_events_url":"https://api.github.com/users/anew/received_events","type":"User","site_admin":false},"body":"I am a little worried about the null returns. Sometimes we throw an IllegalStateException, sometimes we return null - and then the caller just ignores the call? What kind of error handling is this? Is it expected that we simply ignore the call if the app, the program or the schedule is not known But throw an exception if the scheduler type is not known?","created_at":"2015-02-18T21:34:41Z","updated_at":"2015-02-18T21:34:41Z","html_url":"https://github.com/caskdata/cdap/pull/1339#discussion_r24943097","pull_request_url":"https://api.github.com/repos/caskdata/cdap/pulls/1339","_links":{"self":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/comments/24943097"},"html":{"href":"https://github.com/caskdata/cdap/pull/1339#discussion_r24943097"},"pull_request":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/1339"}}},"pull_request":{"url":"https://api.github.com/repos/caskdata/cdap/pulls/1339","id":29512989,"html_url":"https://github.com/caskdata/cdap/pull/1339","diff_url":"https://github.com/caskdata/cdap/pull/1339.diff","patch_url":"https://github.com/caskdata/cdap/pull/1339.patch","issue_url":"https://api.github.com/repos/caskdata/cdap/issues/1339","number":1339,"state":"open","locked":false,"title":"Create a new StreamSizeScheduler","user":{"login":"jguery","id":3600810,"avatar_url":"https://avatars.githubusercontent.com/u/3600810?v=3","gravatar_id":"","url":"https://api.github.com/users/jguery","html_url":"https://github.com/jguery","followers_url":"https://api.github.com/users/jguery/followers","following_url":"https://api.github.com/users/jguery/following{/other_user}","gists_url":"https://api.github.com/users/jguery/gists{/gist_id}","starred_url":"https://api.github.com/users/jguery/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jguery/subscriptions","organizations_url":"https://api.github.com/users/jguery/orgs","repos_url":"https://api.github.com/users/jguery/repos","events_url":"https://api.github.com/users/jguery/events{/privacy}","received_events_url":"https://api.github.com/users/jguery/received_events","type":"User","site_admin":false},"body":"- Create a shell of a StreamSizeScheduler. It integrates in the ``AbstractSchedulerService``. \r\n- The ``TimeScheduler`` is moved, from inside the ``AbstractSchedulerService`` class to its own class.\r\n- The ``AbstractSchedulerService`` uses the metastore to check the type of a schedule, to route the operations to the right scheduler (either TimeScheduler or StreamSizeScheduler).\r\n- The ``SchedulerServiceTest`` is modified so that the schedules that are... scheduled, do appear in the metastore.\r\n\r\nBuild: http://builds.cask.co/browse/CDAP-DUT819","created_at":"2015-02-18T10:01:40Z","updated_at":"2015-02-18T21:34:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"544e07cc07f3d63ae030da53d0c04b6d0af30e8f","assignee":null,"milestone":{"url":"https://api.github.com/repos/caskdata/cdap/milestones/3","labels_url":"https://api.github.com/repos/caskdata/cdap/milestones/3/labels","id":944584,"number":3,"title":"2.8.0","description":null,"creator":{"login":"jwang47","id":1084704,"avatar_url":"https://avatars.githubusercontent.com/u/1084704?v=3","gravatar_id":"","url":"https://api.github.com/users/jwang47","html_url":"https://github.com/jwang47","followers_url":"https://api.github.com/users/jwang47/followers","following_url":"https://api.github.com/users/jwang47/following{/other_user}","gists_url":"https://api.github.com/users/jwang47/gists{/gist_id}","starred_url":"https://api.github.com/users/jwang47/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jwang47/subscriptions","organizations_url":"https://api.github.com/users/jwang47/orgs","repos_url":"https://api.github.com/users/jwang47/repos","events_url":"https://api.github.com/users/jwang47/events{/privacy}","received_events_url":"https://api.github.com/users/jwang47/received_events","type":"User","site_admin":false},"open_issues":16,"closed_issues":41,"state":"open","created_at":"2015-01-21T01:15:14Z","updated_at":"2015-02-18T20:34:46Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/caskdata/cdap/pulls/1339/commits","review_comments_url":"https://api.github.com/repos/caskdata/cdap/pulls/1339/comments","review_comment_url":"https://api.github.com/repos/caskdata/cdap/pulls/comments/{number}","comments_url":"https://api.github.com/repos/caskdata/cdap/issues/1339/comments","statuses_url":"https://api.github.com/repos/caskdata/cdap/statuses/182d3bdc3e8649e57cc68d66159c796bfc593c54","head":{"label":"caskdata:feature/split-schedulers","ref":"feature/split-schedulers","sha":"182d3bdc3e8649e57cc68d66159c796bfc593c54","user":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"repo":{"id":22542759,"name":"cdap","full_name":"caskdata/cdap","owner":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/caskdata/cdap","description":"Cask Data Application Platform (CDAP)","fork":false,"url":"https://api.github.com/repos/caskdata/cdap","forks_url":"https://api.github.com/repos/caskdata/cdap/forks","keys_url":"https://api.github.com/repos/caskdata/cdap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/caskdata/cdap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/caskdata/cdap/teams","hooks_url":"https://api.github.com/repos/caskdata/cdap/hooks","issue_events_url":"https://api.github.com/repos/caskdata/cdap/issues/events{/number}","events_url":"https://api.github.com/repos/caskdata/cdap/events","assignees_url":"https://api.github.com/repos/caskdata/cdap/assignees{/user}","branches_url":"https://api.github.com/repos/caskdata/cdap/branches{/branch}","tags_url":"https://api.github.com/repos/caskdata/cdap/tags","blobs_url":"https://api.github.com/repos/caskdata/cdap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/caskdata/cdap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/caskdata/cdap/git/refs{/sha}","trees_url":"https://api.github.com/repos/caskdata/cdap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/caskdata/cdap/statuses/{sha}","languages_url":"https://api.github.com/repos/caskdata/cdap/languages","stargazers_url":"https://api.github.com/repos/caskdata/cdap/stargazers","contributors_url":"https://api.github.com/repos/caskdata/cdap/contributors","subscribers_url":"https://api.github.com/repos/caskdata/cdap/subscribers","subscription_url":"https://api.github.com/repos/caskdata/cdap/subscription","commits_url":"https://api.github.com/repos/caskdata/cdap/commits{/sha}","git_commits_url":"https://api.github.com/repos/caskdata/cdap/git/commits{/sha}","comments_url":"https://api.github.com/repos/caskdata/cdap/comments{/number}","issue_comment_url":"https://api.github.com/repos/caskdata/cdap/issues/comments/{number}","contents_url":"https://api.github.com/repos/caskdata/cdap/contents/{+path}","compare_url":"https://api.github.com/repos/caskdata/cdap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/caskdata/cdap/merges","archive_url":"https://api.github.com/repos/caskdata/cdap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/caskdata/cdap/downloads","issues_url":"https://api.github.com/repos/caskdata/cdap/issues{/number}","pulls_url":"https://api.github.com/repos/caskdata/cdap/pulls{/number}","milestones_url":"https://api.github.com/repos/caskdata/cdap/milestones{/number}","notifications_url":"https://api.github.com/repos/caskdata/cdap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/caskdata/cdap/labels{/name}","releases_url":"https://api.github.com/repos/caskdata/cdap/releases{/id}","created_at":"2014-08-02T09:00:10Z","updated_at":"2015-02-18T20:43:52Z","pushed_at":"2015-02-18T21:07:53Z","git_url":"git://github.com/caskdata/cdap.git","ssh_url":"git@github.com:caskdata/cdap.git","clone_url":"https://github.com/caskdata/cdap.git","svn_url":"https://github.com/caskdata/cdap","homepage":"http://cdap.io","size":780427,"stargazers_count":27,"watchers_count":27,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":9,"mirror_url":null,"open_issues_count":23,"forks":9,"open_issues":23,"watchers":27,"default_branch":"develop"}},"base":{"label":"caskdata:develop","ref":"develop","sha":"44317f057de27b856bf6e526fa0ad64606608f3f","user":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"repo":{"id":22542759,"name":"cdap","full_name":"caskdata/cdap","owner":{"login":"caskdata","id":8123023,"avatar_url":"https://avatars.githubusercontent.com/u/8123023?v=3","gravatar_id":"","url":"https://api.github.com/users/caskdata","html_url":"https://github.com/caskdata","followers_url":"https://api.github.com/users/caskdata/followers","following_url":"https://api.github.com/users/caskdata/following{/other_user}","gists_url":"https://api.github.com/users/caskdata/gists{/gist_id}","starred_url":"https://api.github.com/users/caskdata/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caskdata/subscriptions","organizations_url":"https://api.github.com/users/caskdata/orgs","repos_url":"https://api.github.com/users/caskdata/repos","events_url":"https://api.github.com/users/caskdata/events{/privacy}","received_events_url":"https://api.github.com/users/caskdata/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/caskdata/cdap","description":"Cask Data Application Platform (CDAP)","fork":false,"url":"https://api.github.com/repos/caskdata/cdap","forks_url":"https://api.github.com/repos/caskdata/cdap/forks","keys_url":"https://api.github.com/repos/caskdata/cdap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/caskdata/cdap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/caskdata/cdap/teams","hooks_url":"https://api.github.com/repos/caskdata/cdap/hooks","issue_events_url":"https://api.github.com/repos/caskdata/cdap/issues/events{/number}","events_url":"https://api.github.com/repos/caskdata/cdap/events","assignees_url":"https://api.github.com/repos/caskdata/cdap/assignees{/user}","branches_url":"https://api.github.com/repos/caskdata/cdap/branches{/branch}","tags_url":"https://api.github.com/repos/caskdata/cdap/tags","blobs_url":"https://api.github.com/repos/caskdata/cdap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/caskdata/cdap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/caskdata/cdap/git/refs{/sha}","trees_url":"https://api.github.com/repos/caskdata/cdap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/caskdata/cdap/statuses/{sha}","languages_url":"https://api.github.com/repos/caskdata/cdap/languages","stargazers_url":"https://api.github.com/repos/caskdata/cdap/stargazers","contributors_url":"https://api.github.com/repos/caskdata/cdap/contributors","subscribers_url":"https://api.github.com/repos/caskdata/cdap/subscribers","subscription_url":"https://api.github.com/repos/caskdata/cdap/subscription","commits_url":"https://api.github.com/repos/caskdata/cdap/commits{/sha}","git_commits_url":"https://api.github.com/repos/caskdata/cdap/git/commits{/sha}","comments_url":"https://api.github.com/repos/caskdata/cdap/comments{/number}","issue_comment_url":"https://api.github.com/repos/caskdata/cdap/issues/comments/{number}","contents_url":"https://api.github.com/repos/caskdata/cdap/contents/{+path}","compare_url":"https://api.github.com/repos/caskdata/cdap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/caskdata/cdap/merges","archive_url":"https://api.github.com/repos/caskdata/cdap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/caskdata/cdap/downloads","issues_url":"https://api.github.com/repos/caskdata/cdap/issues{/number}","pulls_url":"https://api.github.com/repos/caskdata/cdap/pulls{/number}","milestones_url":"https://api.github.com/repos/caskdata/cdap/milestones{/number}","notifications_url":"https://api.github.com/repos/caskdata/cdap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/caskdata/cdap/labels{/name}","releases_url":"https://api.github.com/repos/caskdata/cdap/releases{/id}","created_at":"2014-08-02T09:00:10Z","updated_at":"2015-02-18T20:43:52Z","pushed_at":"2015-02-18T21:07:53Z","git_url":"git://github.com/caskdata/cdap.git","ssh_url":"git@github.com:caskdata/cdap.git","clone_url":"https://github.com/caskdata/cdap.git","svn_url":"https://github.com/caskdata/cdap","homepage":"http://cdap.io","size":780427,"stargazers_count":27,"watchers_count":27,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":9,"mirror_url":null,"open_issues_count":23,"forks":9,"open_issues":23,"watchers":27,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/1339"},"html":{"href":"https://github.com/caskdata/cdap/pull/1339"},"issue":{"href":"https://api.github.com/repos/caskdata/cdap/issues/1339"},"comments":{"href":"https://api.github.com/repos/caskdata/cdap/issues/1339/comments"},"review_comments":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/1339/comments"},"review_comment":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/caskdata/cdap/pulls/1339/commits"},"statuses":{"href":"https://api.github.com/repos/caskdata/cdap/statuses/182d3bdc3e8649e57cc68d66159c796bfc593c54"}}}}