use of org.apache.sling.event.jobs.Job in project sling by apache.
the class JobManagerImpl method findJobs.
/**
* @see org.apache.sling.event.jobs.JobManager#findJobs(org.apache.sling.event.jobs.JobManager.QueryType, java.lang.String, long, java.util.Map[])
*/
@Override
public Collection<Job> findJobs(final QueryType type, final String topic, final long limit, final Map<String, Object>... templates) {
final boolean isHistoryQuery = type == QueryType.HISTORY || type == QueryType.SUCCEEDED || type == QueryType.CANCELLED || type == QueryType.DROPPED || type == QueryType.ERROR || type == QueryType.GIVEN_UP || type == QueryType.STOPPED;
final List<Job> result = new ArrayList<>();
final ResourceResolver resolver = this.configuration.createResourceResolver();
final StringBuilder buf = new StringBuilder(64);
try {
buf.append("/jcr:root");
buf.append(this.configuration.getJobsBasePathWithSlash());
buf.append("/element(*,");
buf.append(ResourceHelper.RESOURCE_TYPE_JOB);
buf.append(")[@");
buf.append(ISO9075.encode(ResourceHelper.PROPERTY_JOB_TOPIC));
if (topic != null) {
buf.append(" = '");
buf.append(topic);
buf.append("'");
}
// restricting on the type - history or unfinished
if (isHistoryQuery) {
buf.append(" and @");
buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE));
if (type == QueryType.SUCCEEDED || type == QueryType.DROPPED || type == QueryType.ERROR || type == QueryType.GIVEN_UP || type == QueryType.STOPPED) {
buf.append(" = '");
buf.append(type.name());
buf.append("'");
} else if (type == QueryType.CANCELLED) {
buf.append(" and (@");
buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE));
buf.append(" = '");
buf.append(QueryType.DROPPED.name());
buf.append("' or @");
buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE));
buf.append(" = '");
buf.append(QueryType.ERROR.name());
buf.append("' or @");
buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE));
buf.append(" = '");
buf.append(QueryType.GIVEN_UP.name());
buf.append("' or @");
buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE));
buf.append(" = '");
buf.append(QueryType.STOPPED.name());
buf.append("')");
}
} else {
buf.append(" and not(@");
buf.append(ISO9075.encode(JobImpl.PROPERTY_FINISHED_STATE));
buf.append(")");
if (type == QueryType.ACTIVE) {
buf.append(" and @");
buf.append(ISO9075.encode(Job.PROPERTY_JOB_STARTED_TIME));
} else if (type == QueryType.QUEUED) {
buf.append(" and not(@");
buf.append(ISO9075.encode(Job.PROPERTY_JOB_STARTED_TIME));
buf.append(")");
}
}
if (templates != null && templates.length > 0) {
int index = 0;
for (final Map<String, Object> template : templates) {
// skip empty templates
if (template.size() == 0) {
continue;
}
if (index == 0) {
buf.append(" and (");
} else {
buf.append(" or ");
}
buf.append('(');
final Iterator<Map.Entry<String, Object>> i = template.entrySet().iterator();
boolean first = true;
while (i.hasNext()) {
final Map.Entry<String, Object> current = i.next();
final String key = ISO9075.encode(current.getKey());
final char firstChar = key.length() > 0 ? key.charAt(0) : 0;
final String propName;
final Operation op;
if (firstChar == '=') {
propName = key.substring(1);
op = Operation.EQUALS;
} else if (firstChar == '<') {
final char secondChar = key.length() > 1 ? key.charAt(1) : 0;
if (secondChar == '=') {
op = Operation.LESS_OR_EQUALS;
propName = key.substring(2);
} else {
op = Operation.LESS;
propName = key.substring(1);
}
} else if (firstChar == '>') {
final char secondChar = key.length() > 1 ? key.charAt(1) : 0;
if (secondChar == '=') {
op = Operation.GREATER_OR_EQUALS;
propName = key.substring(2);
} else {
op = Operation.GREATER;
propName = key.substring(1);
}
} else {
propName = key;
op = Operation.EQUALS;
}
if (first) {
first = false;
buf.append('@');
} else {
buf.append(" and @");
}
buf.append(propName);
buf.append(' ');
switch(op) {
case EQUALS:
buf.append('=');
break;
case LESS:
buf.append('<');
break;
case LESS_OR_EQUALS:
buf.append("<=");
break;
case GREATER:
buf.append('>');
break;
case GREATER_OR_EQUALS:
buf.append(">=");
break;
}
buf.append(" '");
buf.append(current.getValue());
buf.append("'");
}
buf.append(')');
index++;
}
if (index > 0) {
buf.append(')');
}
}
buf.append("] order by @");
if (isHistoryQuery) {
buf.append(JobImpl.PROPERTY_FINISHED_DATE);
buf.append(" descending");
} else {
buf.append(Job.PROPERTY_JOB_CREATED);
buf.append(" ascending");
}
final Iterator<Resource> iter = resolver.findResources(buf.toString(), "xpath");
long count = 0;
while (iter.hasNext() && (limit < 1 || count < limit)) {
final Resource jobResource = iter.next();
// sanity check for the path
if (this.configuration.isJob(jobResource.getPath())) {
final JobImpl job = Utility.readJob(logger, jobResource);
if (job != null) {
count++;
result.add(job);
}
}
}
} catch (final QuerySyntaxException qse) {
logger.warn("Query syntax wrong " + buf.toString(), qse);
} finally {
resolver.close();
}
return result;
}
use of org.apache.sling.event.jobs.Job in project sling by apache.
the class JobManagerImpl method addJob.
/**
* Internal method to add a job
*/
public Job addJob(final String topic, final Map<String, Object> properties, final List<String> errors) {
final String errorMessage = Utility.checkJob(topic, properties);
if (errorMessage != null) {
logger.warn("{}", errorMessage);
if (errors != null) {
errors.add(errorMessage);
}
this.configuration.getAuditLogger().debug("ADD FAILED topic={}, properties={} : {}", new Object[] { topic, properties, errorMessage });
return null;
}
final List<String> errorList = new ArrayList<>();
Job result = this.addJobInternal(topic, properties, errorList);
if (errors != null) {
errors.addAll(errorList);
}
if (result == null) {
this.configuration.getAuditLogger().debug("ADD FAILED topic={}, properties={} : {}", new Object[] { topic, properties, errorList });
} else {
this.configuration.getAuditLogger().debug("ADD OK topic={}, properties={} : {}", new Object[] { topic, properties, result.getId() });
}
return result;
}
use of org.apache.sling.event.jobs.Job in project sling by apache.
the class TopicMatchingTest method testDeepMatching.
/**
* Test deep pattern matching /**
*/
@Test(timeout = DEFAULT_TEST_TIMEOUT)
public void testDeepMatching() throws Exception {
final Barrier barrier = new Barrier(2);
this.registerJobExecutor("sling/**", new JobExecutor() {
@Override
public JobExecutionResult process(final Job job, final JobExecutionContext context) {
return context.result().succeeded();
}
});
this.registerEventHandler(NotificationConstants.TOPIC_JOB_FINISHED, new EventHandler() {
@Override
public void handleEvent(final Event event) {
barrier.block();
}
});
this.getJobManager().addJob(TOPIC, null);
barrier.block();
}
use of org.apache.sling.event.jobs.Job in project sling by apache.
the class TopicMatchingTest method testSimpleMatching.
/**
* Test simple pattern matching /*
*/
@Test(timeout = DEFAULT_TEST_TIMEOUT)
public void testSimpleMatching() throws Exception {
final Barrier barrier = new Barrier(2);
this.registerJobExecutor("sling/test/*", new JobExecutor() {
@Override
public JobExecutionResult process(final Job job, final JobExecutionContext context) {
return context.result().succeeded();
}
});
this.registerEventHandler(NotificationConstants.TOPIC_JOB_FINISHED, new EventHandler() {
@Override
public void handleEvent(final Event event) {
barrier.block();
}
});
this.getJobManager().addJob(TOPIC, null);
barrier.block();
}
use of org.apache.sling.event.jobs.Job in project sling by apache.
the class UnorderedQueueTest method testUnorderedQueue.
@Test(timeout = DEFAULT_TEST_TIMEOUT)
public void testUnorderedQueue() throws Exception {
final JobManager jobManager = this.getJobManager();
final Barrier cb = new Barrier(2);
this.registerJobConsumer(TOPIC + "/start", new JobConsumer() {
@Override
public JobResult process(final Job job) {
cb.block();
return JobResult.OK;
}
});
// register new consumer and event handle
final AtomicInteger count = new AtomicInteger(0);
final AtomicInteger parallelCount = new AtomicInteger(0);
final Set<Integer> maxParticipants = new HashSet<Integer>();
this.registerJobConsumer(TOPIC + "/*", new JobConsumer() {
@Override
public JobResult process(final Job job) {
final int max = parallelCount.incrementAndGet();
if (max > MAX_PAR) {
parallelCount.decrementAndGet();
return JobResult.FAILED;
}
synchronized (maxParticipants) {
maxParticipants.add(max);
}
sleep(job.getProperty("sleep", 30));
parallelCount.decrementAndGet();
return JobResult.OK;
}
});
this.registerEventHandler(NotificationConstants.TOPIC_JOB_FINISHED, new EventHandler() {
@Override
public void handleEvent(final Event event) {
count.incrementAndGet();
}
});
// we first sent one event to get the queue started
jobManager.addJob(TOPIC + "/start", null);
assertTrue("No event received in the given time.", cb.block(5));
cb.reset();
// get the queue
final Queue q = jobManager.getQueue(QUEUE_NAME);
assertNotNull("Queue '" + QUEUE_NAME + "' should exist!", q);
// suspend it
q.suspend();
// we start "some" jobs:
for (int i = 0; i < NUM_JOBS; i++) {
final String subTopic = TOPIC + "/sub" + (i % 10);
final Map<String, Object> props = new HashMap<String, Object>();
if (i < 10) {
props.put("sleep", 300);
} else {
props.put("sleep", 30);
}
jobManager.addJob(subTopic, props);
}
// start the queue
q.resume();
while (count.get() < NUM_JOBS + 1) {
assertEquals("Failed count", 0, q.getStatistics().getNumberOfFailedJobs());
assertEquals("Cancelled count", 0, q.getStatistics().getNumberOfCancelledJobs());
sleep(300);
}
// we started one event before the test, so add one
assertEquals("Finished count", NUM_JOBS + 1, count.get());
assertEquals("Finished count", NUM_JOBS + 1, jobManager.getStatistics().getNumberOfFinishedJobs());
assertEquals("Finished count", NUM_JOBS + 1, q.getStatistics().getNumberOfFinishedJobs());
assertEquals("Failed count", 0, q.getStatistics().getNumberOfFailedJobs());
assertEquals("Cancelled count", 0, q.getStatistics().getNumberOfCancelledJobs());
for (int i = 1; i <= MAX_PAR; i++) {
assertTrue("# Participants " + String.valueOf(i) + " not in " + maxParticipants, maxParticipants.contains(i));
}
}
Aggregations