Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.beanstalk;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import com.surftools.BeanstalkClient.BeanstalkException;
import com.surftools.BeanstalkClient.Client;
import com.surftools.BeanstalkClient.Job;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Processor;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.component.beanstalk.processors.BuryCommand;
import org.apache.camel.component.beanstalk.processors.Command;
import org.apache.camel.component.beanstalk.processors.DeleteCommand;
import org.apache.camel.component.beanstalk.processors.ReleaseCommand;
import org.apache.camel.impl.ScheduledPollConsumer;
import org.apache.camel.spi.Synchronization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* PollingConsumer to read Beanstalk jobs.
*
* The consumer may delete the job immediately or based on successful {@link Exchange}
* completion. The behavior is configurable by consumer.awaitJob
* flag (by default true)
*
* This consumer will add a {@link Synchronization} object to every {@link Exchange}
* object it creates in order to react on successful exchange completion or failure.
*
* In the case of successful completion, Beanstalk's delete method is
* called upon the job. In the case of failure the default reaction is to call
* bury.
*
* The reaction on failures is configurable: possible variants are "bury", "release" or "delete"
*/
public class BeanstalkConsumer extends ScheduledPollConsumer {
private static final Logger LOG = LoggerFactory.getLogger(BeanstalkConsumer.class);
private static final String[] STATS_KEY_STR = new String[]{"tube", "state"};
private static final String[] STATS_KEY_INT = new String[]{"age", "time-left", "timeouts", "releases", "buries", "kicks"};
private BeanstalkCommand onFailure;
private boolean useBlockIO;
private boolean awaitJob;
private Client client;
private ExecutorService executor;
private Synchronization sync;
private final Runnable initTask = new Runnable() {
@Override
public void run() {
client = getEndpoint().getConnection().newReadingClient(useBlockIO);
}
};
private final Callable pollTask = new Callable() {
final Integer noWait = 0;
@Override
public Exchange call() throws Exception {
if (client == null) {
throw new RuntimeCamelException("Beanstalk client not initialized");
}
try {
final Job job = client.reserve(noWait);
if (job == null) {
return null;
}
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Received job ID %d (data length %d)", job.getJobId(), job.getData().length));
}
final Exchange exchange = getEndpoint().createExchange(ExchangePattern.InOnly);
exchange.getIn().setHeader(Headers.JOB_ID, job.getJobId());
exchange.getIn().setBody(job.getData(), byte[].class);
Map jobStats = client.statsJob(job.getJobId());
if (jobStats != null && !jobStats.isEmpty()) {
for (String key : STATS_KEY_STR) {
if (jobStats.containsKey(key)) {
exchange.getIn().setHeader(Headers.PREFIX + key, jobStats.get(key).trim());
}
}
if (jobStats.containsKey("pri")) {
exchange.getIn().setHeader(Headers.PRIORITY, Long.parseLong(jobStats.get("pri").trim()));
}
for (String key : STATS_KEY_INT) {
if (jobStats.containsKey(key)) {
exchange.getIn().setHeader(Headers.PREFIX + key, Integer.parseInt(jobStats.get(key).trim()));
}
}
}
if (!awaitJob) {
client.delete(job.getJobId());
} else {
exchange.addOnCompletion(sync);
}
return exchange;
} catch (BeanstalkException e) {
getExceptionHandler().handleException("Beanstalk client error", e);
resetClient();
return null;
}
}
};
public BeanstalkConsumer(final BeanstalkEndpoint endpoint, final Processor processor) {
super(endpoint, processor);
}
@Override
protected int poll() throws Exception {
int messagesPolled = 0;
while (isPollAllowed()) {
final Exchange exchange = executor.submit(pollTask).get();
if (exchange == null) {
break;
}
++messagesPolled;
getProcessor().process(exchange);
}
return messagesPolled;
}
public BeanstalkCommand getOnFailure() {
return onFailure;
}
public void setOnFailure(BeanstalkCommand onFailure) {
this.onFailure = onFailure;
}
public boolean isUseBlockIO() {
return useBlockIO;
}
public void setUseBlockIO(boolean useBlockIO) {
this.useBlockIO = useBlockIO;
}
public boolean isAwaitJob() {
return awaitJob;
}
public void setAwaitJob(boolean awaitJob) {
this.awaitJob = awaitJob;
}
@Override
public BeanstalkEndpoint getEndpoint() {
return (BeanstalkEndpoint) super.getEndpoint();
}
@Override
protected void doStart() throws Exception {
executor = getEndpoint().getCamelContext().getExecutorServiceManager().newSingleThreadExecutor(this, "Beanstalk-Consumer");
executor.execute(initTask);
sync = new Sync();
super.doStart();
}
@Override
protected void doStop() throws Exception {
super.doStop();
if (executor != null) {
getEndpoint().getCamelContext().getExecutorServiceManager().shutdown(executor);
}
}
protected void resetClient() {
if (client != null) {
client.close();
}
initTask.run();
}
class Sync implements Synchronization {
protected final Command successCommand;
protected final Command failureCommand;
Sync() {
successCommand = new DeleteCommand(getEndpoint());
if (BeanstalkComponent.COMMAND_BURY.equals(onFailure.name())) {
failureCommand = new BuryCommand(getEndpoint());
} else if (BeanstalkComponent.COMMAND_RELEASE.equals(onFailure.name())) {
failureCommand = new ReleaseCommand(getEndpoint());
} else if (BeanstalkComponent.COMMAND_DELETE.equals(onFailure.name())) {
failureCommand = new DeleteCommand(getEndpoint());
} else {
throw new IllegalArgumentException(String.format("Unknown failure command: %s", onFailure));
}
}
@Override
public void onComplete(final Exchange exchange) {
try {
executor.submit(new RunCommand(successCommand, exchange)).get();
} catch (Exception e) {
LOG.error(String.format("Could not run completion of exchange %s", exchange), e);
}
}
@Override
public void onFailure(final Exchange exchange) {
try {
executor.submit(new RunCommand(failureCommand, exchange)).get();
} catch (Exception e) {
LOG.error(String.format("%s could not run failure of exchange %s", failureCommand.getClass().getName(), exchange), e);
}
}
class RunCommand implements Runnable {
private final Command command;
private final Exchange exchange;
RunCommand(final Command command, final Exchange exchange) {
this.command = command;
this.exchange = exchange;
}
@Override
public void run() {
try {
try {
command.act(client, exchange);
} catch (BeanstalkException e) {
LOG.warn(String.format("Post-processing %s of exchange %s failed, retrying.", command.getClass().getName(), exchange), e);
resetClient();
command.act(client, exchange);
}
} catch (final Exception e) {
LOG.error(String.format("%s could not post-process exchange %s", command.getClass().getName(), exchange), e);
exchange.setException(e);
}
}
}
}
}