public String getJobType() { return job.getJobType(); }
@Override public List<JobInfo> findLatestJobsDistinct() { Set<String> typeSet = new HashSet<>(); return jobs.values() .stream() .sorted(STARTED_TIME_DESC_COMPARATOR) .filter(j -> nonNull(j.getJobType())) .filter(j -> typeSet.add(j.getJobType())) .collect(toList()); }
@Override public List<JobInfo> findByType(String jobType) { return jobs.values().stream() .filter(jobInfo -> jobInfo.getJobType().equals(jobType)) .collect(toList()); }
@Override public List<JobInfo> findLatestBy(String type, int maxCount) { return jobs.values() .stream() .sorted(STARTED_TIME_DESC_COMPARATOR) .filter(jobInfo -> jobInfo.getJobType().equalsIgnoreCase(type)) .limit(maxCount) .collect(toList()); }
@RequestMapping(value = "${edison.application.management.base-path:/internal}/jobs", method = GET, produces = "application/json") @ResponseBody public List<JobRepresentation> getJobsAsJson(@RequestParam(name = "type", required = false) String type, @RequestParam(name = "count", defaultValue = "10") int count, @RequestParam(name = "distinct", defaultValue = "true", required = false) boolean distinct, @RequestParam(name = "humanReadable", defaultValue = "false", required = false) boolean humanReadable, HttpServletRequest request) { return getJobInfos(type, count, distinct) .stream() .map((j) -> representationOf(j, getJobMeta(j.getJobType()), humanReadable, baseUriOf(request), applicationProperties.getManagement().getBasePath())) .collect(toList()); }
@RequestMapping(value = "${edison.application.management.base-path:/internal}/jobs", method = GET, produces = "text/html") public ModelAndView getJobsAsHtml(@RequestParam(value = "type", required = false) String type, @RequestParam(value = "count", defaultValue = "100") int count, @RequestParam(value = "distinct", defaultValue = "true", required = false) boolean distinct, HttpServletRequest request) { final List<JobRepresentation> jobRepresentations = getJobInfos(type, count, distinct).stream() .map((j) -> representationOf(j, getJobMeta(j.getJobType()), true, baseUriOf(request), applicationProperties.getManagement().getBasePath())) .collect(toList()); final ModelAndView modelAndView = new ModelAndView("jobs"); modelAndView.addObject("jobs", jobRepresentations); if (type != null) { modelAndView.addObject("typeFilter", type); } modelAndView.addObject("baseUri", baseUriOf(request)); return modelAndView; }
public List<Link> getLinks() { final String jobUri = String.format("%s%s/jobs/%s", baseUri, edisonManagementBasePath, job.getJobId()); return asList( link("self", jobUri, "Self"), link("http://github.com/otto-de/edison/link-relations/job/definition", String.format("%s%s/jobdefinitions/%s", baseUri, edisonManagementBasePath, job.getJobType()), "Job Definition"), link("collection", jobUri.substring(0, jobUri.lastIndexOf("/")), "All Jobs"), link("collection/" + getJobType(), jobUri.substring(0, jobUri.lastIndexOf("/")) + "?type=" + getJobType(), "All " + getJobType() + " Jobs") ); }
@RequestMapping(value = "${edison.application.management.base-path:/internal}/jobs/{id}", method = GET, produces = "application/json") @ResponseBody public JobRepresentation getJob(final HttpServletRequest request, final HttpServletResponse response, @PathVariable("id") final String jobId, @RequestParam(name = "humanReadable", defaultValue = "false", required = false) boolean humanReadable ) throws IOException { setCorsHeaders(response); final Optional<JobInfo> optionalJob = jobService.findJob(jobId); if (optionalJob.isPresent()) { final JobInfo jobInfo = optionalJob.get(); return representationOf(optionalJob.get(), getJobMeta(jobInfo.getJobType()), humanReadable, baseUriOf(request), applicationProperties.getManagement().getBasePath()); } else { response.sendError(SC_NOT_FOUND, "Job not found"); return null; } }
@RequestMapping(value = "${edison.application.management.base-path:/internal}/jobs/{id}", method = GET, produces = "text/html") public ModelAndView getJobAsHtml(final HttpServletRequest request, final HttpServletResponse response, @PathVariable("id") final String jobId) throws IOException { setCorsHeaders(response); final Optional<JobInfo> optionalJob = jobService.findJob(jobId); if (optionalJob.isPresent()) { final JobInfo jobInfo = optionalJob.get(); final JobMeta jobMeta = getJobMeta(jobInfo.getJobType()); final ModelAndView modelAndView = new ModelAndView("job"); modelAndView .addObject("job", representationOf(jobInfo, jobMeta, true, baseUriOf(request), applicationProperties.getManagement().getBasePath())) .addObject("baseUri", baseUriOf(request)); return modelAndView; } else { response.sendError(SC_NOT_FOUND, "Job not found"); return null; } }
private JobInfo someRunningJob(final JobInfo.JobStatus jobStatus, int startedSecondsAgo) { OffsetDateTime now = now(); JobInfo someJob = mock(JobInfo.class); when(someJob.getJobType()).thenReturn("someJobType"); when(someJob.getJobId()).thenReturn("someJobId"); when(someJob.getStarted()).thenReturn(now.minusSeconds(startedSecondsAgo)); when(someJob.getStopped()).thenReturn(empty()); when(someJob.getStatus()).thenReturn(jobStatus); return someJob; } }
private JobInfo someStoppedJob(final JobInfo.JobStatus jobStatus, int startedSecondsAgo) { OffsetDateTime now = now(); JobInfo someJob = mock(JobInfo.class); when(someJob.getJobType()).thenReturn("someJobType"); when(someJob.getJobId()).thenReturn("someId"); when(someJob.getStarted()).thenReturn(now.minusSeconds(startedSecondsAgo)); when(someJob.getStopped()).thenReturn(of(now.minusSeconds(startedSecondsAgo-1))); when(someJob.getStatus()).thenReturn(jobStatus); return someJob; }
/** * Starts a job asynchronously in the background. * * @param jobType the type of the job * @return the URI under which you can retrieve the status about the triggered job instance */ public Optional<String> startAsyncJob(String jobType) { try { final JobRunnable jobRunnable = findJobRunnable(jobType); final JobInfo jobInfo = createJobInfo(jobType); jobMetaService.aquireRunLock(jobInfo.getJobId(), jobInfo.getJobType()); jobRepository.createOrUpdate(jobInfo); return Optional.of(startAsync(metered(jobRunnable), jobInfo.getJobId())); } catch (JobBlockedException e) { LOG.info(e.getMessage()); return Optional.empty(); } }
@Test public void shouldRunJob() { // given: String jobType = "bar"; when(jobRunnable.getJobDefinition()).thenReturn(someJobDefinition(jobType)); // when: Optional<String> optionalJobId = jobService.startAsyncJob(jobType); // then: final JobInfo expectedJobInfo = JobInfo.newJobInfo(optionalJobId.get(), jobType, clock, systemInfo.hostname); verify(executorService).execute(any(Runnable.class)); verify(jobRepository).createOrUpdate(expectedJobInfo); verify(jobRunnable).execute(); verify(jobMetaService).aquireRunLock(expectedJobInfo.getJobId(), expectedJobInfo.getJobType()); }
private void stopJob(final String jobId, final JobStatus status) { jobRepository.findOne(jobId).ifPresent((JobInfo jobInfo) -> { jobMetaService.releaseRunLock(jobInfo.getJobType()); final OffsetDateTime now = now(clock); final Builder builder = jobInfo.copy() .setStopped(now) .setLastUpdated(now); if (status != null) { builder.setStatus(status); } jobRepository.createOrUpdate(builder.build()); }); }
@Override protected final Document encode(final JobInfo job) { final Document document = new Document() .append(JobStructure.ID.key(), job.getJobId()) .append(JobStructure.JOB_TYPE.key(), job.getJobType()) .append(JobStructure.STARTED.key(), Date.from(job.getStarted().toInstant())) .append(JobStructure.LAST_UPDATED.key(), Date.from(job.getLastUpdated().toInstant())) .append(JobStructure.MESSAGES.key(), job.getMessages().stream() .map(MongoJobRepository::encodeJobMessage) .collect(toList())) .append(JobStructure.STATUS.key(), job.getStatus().name()) .append(JobStructure.HOSTNAME.key(), job.getHostname()); if (job.isStopped()) { document.append(JobStructure.STOPPED.key(), Date.from(job.getStopped().get().toInstant())); } return document; }
@Override protected final Document encode(final JobInfo job) { final Document document = new Document() .append(JobStructure.ID.key(), job.getJobId()) .append(JobStructure.JOB_TYPE.key(), job.getJobType()) .append(JobStructure.STARTED.key(), DateTimeConverters.toDate(job.getStarted())) .append(JobStructure.LAST_UPDATED.key(), DateTimeConverters.toDate(job.getLastUpdated())) .append(JobStructure.MESSAGES.key(), job.getMessages().stream() .map(MongoJobRepository::encodeJobMessage) .collect(toList())) .append(JobStructure.STATUS.key(), job.getStatus().name()) .append(JobStructure.HOSTNAME.key(), job.getHostname()); if (job.isStopped()) { document.append(JobStructure.STOPPED.key(), DateTimeConverters.toDate(job.getStopped().get())); } return document; }