org.apache.camel.impl.engine.DefaultInflightRepository Maven / Gradle / Ivy
/*
* 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.impl.engine;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.camel.Exchange;
import org.apache.camel.ExtendedExchange;
import org.apache.camel.MessageHistory;
import org.apache.camel.spi.InflightRepository;
import org.apache.camel.support.ExchangeHelper;
import org.apache.camel.support.service.ServiceSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default {@link org.apache.camel.spi.InflightRepository}.
*/
public class DefaultInflightRepository extends ServiceSupport implements InflightRepository {
private static final Logger LOG = LoggerFactory.getLogger(DefaultInflightRepository.class);
private final AtomicInteger size = new AtomicInteger();
private final ConcurrentMap inflight = new ConcurrentHashMap<>();
private final ConcurrentMap routeCount = new ConcurrentHashMap<>();
private boolean inflightExchangeEnabled;
@Override
public void add(Exchange exchange) {
size.incrementAndGet();
if (inflightExchangeEnabled) {
inflight.put(exchange.getExchangeId(), exchange);
}
}
@Override
public void remove(Exchange exchange) {
size.decrementAndGet();
if (inflightExchangeEnabled) {
inflight.remove(exchange.getExchangeId());
}
}
@Override
public void add(Exchange exchange, String routeId) {
AtomicInteger existing = routeCount.get(routeId);
if (existing != null) {
existing.incrementAndGet();
}
}
@Override
public void remove(Exchange exchange, String routeId) {
AtomicInteger existing = routeCount.get(routeId);
if (existing != null) {
existing.decrementAndGet();
}
}
@Override
public int size() {
return size.get();
}
@Override
public void addRoute(String routeId) {
routeCount.putIfAbsent(routeId, new AtomicInteger());
}
@Override
public void removeRoute(String routeId) {
routeCount.remove(routeId);
}
@Override
public int size(String routeId) {
AtomicInteger existing = routeCount.get(routeId);
return existing != null ? existing.get() : 0;
}
@Override
public boolean isInflightBrowseEnabled() {
return inflightExchangeEnabled;
}
@Override
public void setInflightBrowseEnabled(boolean inflightBrowseEnabled) {
this.inflightExchangeEnabled = inflightBrowseEnabled;
}
@Override
public Collection browse() {
return browse(null, -1, false);
}
@Override
public Collection browse(String fromRouteId) {
return browse(fromRouteId, -1, false);
}
@Override
public Collection browse(int limit, boolean sortByLongestDuration) {
return browse(null, limit, sortByLongestDuration);
}
@Override
public Collection browse(String fromRouteId, int limit, boolean sortByLongestDuration) {
if (!inflightExchangeEnabled) {
return Collections.emptyList();
}
Stream values;
if (fromRouteId == null) {
// all values
values = inflight.values().stream();
} else {
// only if route match
values = inflight.values().stream()
.filter(e -> fromRouteId.equals(e.getFromRouteId()));
}
if (sortByLongestDuration) {
// sort by duration and grab the first
values = values.sorted((e1, e2) -> {
long d1 = getExchangeDuration(e1);
long d2 = getExchangeDuration(e2);
// need the biggest number first
return -1 * Long.compare(d1, d2);
});
} else {
// else sort by exchange id
values = values.sorted(Comparator.comparing(Exchange::getExchangeId));
}
if (limit > 0) {
values = values.limit(limit);
}
List answer = values.map(InflightExchangeEntry::new).collect(Collectors.toList());
return Collections.unmodifiableCollection(answer);
}
@Override
public InflightExchange oldest(String fromRouteId) {
if (!inflightExchangeEnabled) {
return null;
}
Stream values;
if (fromRouteId == null) {
// all values
values = inflight.values().stream();
} else {
// only if route match
values = inflight.values().stream()
.filter(e -> fromRouteId.equals(e.getFromRouteId()));
}
// sort by duration and grab the first
Exchange first = values.sorted((e1, e2) -> {
long d1 = getExchangeDuration(e1);
long d2 = getExchangeDuration(e2);
// need the biggest number first
return -1 * Long.compare(d1, d2);
}).findFirst().orElse(null);
if (first != null) {
return new InflightExchangeEntry(first);
} else {
return null;
}
}
@Override
protected void doStop() throws Exception {
int count = size();
if (count > 0) {
LOG.warn("Shutting down while there are still {} inflight exchanges.", count);
} else {
LOG.debug("Shutting down with no inflight exchanges.");
}
routeCount.clear();
}
private static long getExchangeDuration(Exchange exchange) {
return System.currentTimeMillis() - exchange.getCreated();
}
private static final class InflightExchangeEntry implements InflightExchange {
private final Exchange exchange;
private InflightExchangeEntry(Exchange exchange) {
this.exchange = exchange;
}
@Override
public Exchange getExchange() {
return exchange;
}
@Override
public long getDuration() {
return DefaultInflightRepository.getExchangeDuration(exchange);
}
@Override
@SuppressWarnings("unchecked")
public long getElapsed() {
// this can only be calculate if message history is enabled
LinkedList list = exchange.getProperty(Exchange.MESSAGE_HISTORY, LinkedList.class);
if (list == null || list.isEmpty()) {
return 0;
}
// get latest entry
MessageHistory history = list.getLast();
if (history != null) {
long elapsed = history.getElapsed();
if (elapsed == 0 && history.getTime() > 0) {
// still in progress, so lets compute it via the start time
elapsed = System.currentTimeMillis() - history.getTime();
}
return elapsed;
} else {
return 0;
}
}
@Override
@SuppressWarnings("unchecked")
public String getNodeId() {
return exchange.adapt(ExtendedExchange.class).getHistoryNodeId();
}
@Override
public String getFromRouteId() {
return exchange.getFromRouteId();
}
@Override
@SuppressWarnings("unchecked")
public String getAtRouteId() {
return ExchangeHelper.getAtRouteId(exchange);
}
@Override
public String toString() {
return "InflightExchangeEntry[exchangeId=" + exchange.getExchangeId() + "]";
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy