This is an automated email from the ASF dual-hosted git repository. orpiske pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new c65a2e6509f CAMEL-20225: move time-related information to a separate abstraction c65a2e6509f is described below commit c65a2e6509f4a264cac031e2de013e62c0610fa9 Author: Otavio Rodolfo Piske <angusyo...@gmail.com> AuthorDate: Tue Dec 12 11:15:51 2023 -0300 CAMEL-20225: move time-related information to a separate abstraction --- .../camel/component/cloudevents/CloudEvent.java | 2 +- .../language/csimple/joor/OriginalSimpleTest.java | 3 +- .../knative/ce/AbstractCloudEventProcessor.java | 2 +- .../src/main/java/org/apache/camel/Clock.java | 38 +++++++++++++++ .../src/main/java/org/apache/camel/Exchange.java | 3 ++ .../src/main/java/org/apache/camel/Message.java | 2 +- .../main/java/org/apache/camel/PooledExchange.java | 1 + .../camel/impl/engine/CamelInternalProcessor.java | 4 +- .../impl/engine/DefaultInflightRepository.java | 2 +- .../camel/impl/engine/PooledExchangeFactory.java | 7 ++- .../engine/PooledProcessorExchangeFactory.java | 12 ++--- .../camel/impl/event/ExchangeCompletedEvent.java | 17 ++----- .../component/mock/MockEndpointTimeClauseTest.java | 2 +- .../event/EventNotifierExchangeCompletedTest.java | 2 +- .../apache/camel/language/simple/SimpleTest.java | 3 +- .../processor/ExchangeCreatedTimestampTest.java | 2 +- .../apache/camel/support/AbstractExchangeTest.java | 7 +++ .../management/mbean/ManagedBacklogDebugger.java | 2 +- .../org/apache/camel/support/AbstractExchange.java | 8 +-- .../org/apache/camel/support/DefaultExchange.java | 21 ++++++++ .../camel/support/DefaultPooledExchange.java | 34 +++++++++++-- .../org/apache/camel/support/LanguageHelper.java | 2 +- .../org/apache/camel/support/MessageHelper.java | 8 ++- .../org/apache/camel/support/MonotonicClock.java | 38 +++++++++++++++ .../org/apache/camel/support/ResetableClock.java | 57 ++++++++++++++++++++++ .../ROOT/pages/camel-4x-upgrade-guide-4_4.adoc | 2 + 26 files changed, 228 insertions(+), 53 deletions(-) diff --git a/components/camel-cloudevents/src/main/java/org/apache/camel/component/cloudevents/CloudEvent.java b/components/camel-cloudevents/src/main/java/org/apache/camel/component/cloudevents/CloudEvent.java index ba3fc3d430a..9f3d6451e59 100644 --- a/components/camel-cloudevents/src/main/java/org/apache/camel/component/cloudevents/CloudEvent.java +++ b/components/camel-cloudevents/src/main/java/org/apache/camel/component/cloudevents/CloudEvent.java @@ -77,7 +77,7 @@ public interface CloudEvent { */ default String getEventTime(Exchange exchange) { final ZonedDateTime created - = ZonedDateTime.ofInstant(Instant.ofEpochMilli(exchange.getCreated()), ZoneId.systemDefault()); + = ZonedDateTime.ofInstant(Instant.ofEpochMilli(exchange.getClock().getCreated()), ZoneId.systemDefault()); return DateTimeFormatter.ISO_INSTANT.format(created); } diff --git a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java index 5abd0240c51..e6de82b4906 100644 --- a/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java +++ b/components/camel-csimple-joor/src/test/java/org/apache/camel/language/csimple/joor/OriginalSimpleTest.java @@ -658,7 +658,8 @@ public class OriginalSimpleTest extends LanguageTestSupport { @Test public void testDateExchangeCreated() { - Object out = evaluateExpression("${date:exchangeCreated:hh:mm:ss a}", "" + exchange.getCreated()); + Object out = evaluateExpression("${date:exchangeCreated:hh:mm:ss a}", + String.valueOf(exchange.getClock().getCreated())); assertNotNull(out); } diff --git a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java index 63813d236c0..3165c2d8911 100644 --- a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java +++ b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/ce/AbstractCloudEventProcessor.java @@ -123,7 +123,7 @@ abstract class AbstractCloudEventProcessor implements CloudEventProcessor { setCloudEventHeader(headers, CloudEvent.CAMEL_CLOUD_EVENT_VERSION, ce::version); setCloudEventHeader(headers, CloudEvent.CAMEL_CLOUD_EVENT_TIME, () -> { final ZonedDateTime created - = ZonedDateTime.ofInstant(Instant.ofEpochMilli(exchange.getCreated()), ZoneId.systemDefault()); + = ZonedDateTime.ofInstant(Instant.ofEpochMilli(exchange.getClock().getCreated()), ZoneId.systemDefault()); return DateTimeFormatter.ISO_INSTANT.format(created); }); diff --git a/core/camel-api/src/main/java/org/apache/camel/Clock.java b/core/camel-api/src/main/java/org/apache/camel/Clock.java new file mode 100644 index 00000000000..f19ecd35a07 --- /dev/null +++ b/core/camel-api/src/main/java/org/apache/camel/Clock.java @@ -0,0 +1,38 @@ +/* + * 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; + +/** + * A clock used to track the lifetime of an exchange + */ +public interface Clock { + /** + * The elapsed time since the creation of the exchange + * + * @return The elapsed time, in milliseconds, since the creation of the exchange + */ + long elapsed(); + + /** + * The point in time the exchange was created + * + * @return The point in time, in milliseconds, the exchange was created. + * @see System#currentTimeMillis() + */ + long getCreated(); +} diff --git a/core/camel-api/src/main/java/org/apache/camel/Exchange.java b/core/camel-api/src/main/java/org/apache/camel/Exchange.java index 0db1ae54850..f8390711f73 100644 --- a/core/camel-api/src/main/java/org/apache/camel/Exchange.java +++ b/core/camel-api/src/main/java/org/apache/camel/Exchange.java @@ -662,6 +662,7 @@ public interface Exchange { * * @see Message#getMessageTimestamp() */ + @Deprecated long getCreated(); /** @@ -672,4 +673,6 @@ public interface Exchange { */ ExchangeExtension getExchangeExtension(); + Clock getClock(); + } diff --git a/core/camel-api/src/main/java/org/apache/camel/Message.java b/core/camel-api/src/main/java/org/apache/camel/Message.java index b4d4da50eb9..02ab5e15d31 100644 --- a/core/camel-api/src/main/java/org/apache/camel/Message.java +++ b/core/camel-api/src/main/java/org/apache/camel/Message.java @@ -64,7 +64,7 @@ public interface Message { * components when the consumer is able to extract the timestamp from the source event. * * @return the timestamp, or <tt>0</tt> if the message has no source timestamp. - * @see Exchange#getCreated() + * @see Exchange#getClock() */ long getMessageTimestamp(); diff --git a/core/camel-api/src/main/java/org/apache/camel/PooledExchange.java b/core/camel-api/src/main/java/org/apache/camel/PooledExchange.java index a1b85aa73ec..ae1c075baba 100644 --- a/core/camel-api/src/main/java/org/apache/camel/PooledExchange.java +++ b/core/camel-api/src/main/java/org/apache/camel/PooledExchange.java @@ -52,6 +52,7 @@ public interface PooledExchange extends Exchange { * <p/> * <b>Important:</b> This API is NOT intended for Camel end users, but used internally by Camel itself. */ + @Deprecated void reset(long created); /** diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java index 48c3b610da9..9a581058ba2 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java @@ -648,7 +648,7 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In if (first) { // use route as pseudo source when first String source = LoggerHelper.getLineNumberLoggerName(routeDefinition); - long created = exchange.getCreated(); + final long created = exchange.getClock().getCreated(); DefaultBacklogTracerEventMessage pseudoFirst = new DefaultBacklogTracerEventMessage( true, false, backlogTracer.incrementTraceCounter(), created, source, routeId, null, exchangeId, rest, template, messageAsXml, messageAsJSon); @@ -675,7 +675,7 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In String routeId = routeDefinition != null ? routeDefinition.getRouteId() : null; String exchangeId = exchange.getExchangeId(); boolean includeExchangeProperties = backlogTracer.isIncludeExchangeProperties(); - long created = exchange.getCreated(); + long created = exchange.getClock().getCreated(); String messageAsXml = MessageHelper.dumpAsXml(exchange.getIn(), includeExchangeProperties, true, 4, true, backlogTracer.isBodyIncludeStreams(), backlogTracer.isBodyIncludeFiles(), backlogTracer.getBodyMaxChars()); diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInflightRepository.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInflightRepository.java index dce5ccc589f..44483efcb7e 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInflightRepository.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInflightRepository.java @@ -207,7 +207,7 @@ public class DefaultInflightRepository extends ServiceSupport implements Infligh } private static long getExchangeDuration(Exchange exchange) { - return System.currentTimeMillis() - exchange.getCreated(); + return exchange.getClock().elapsed(); } private static final class InflightExchangeEntry implements InflightExchange { diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledExchangeFactory.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledExchangeFactory.java index 7468e4f9c58..f072adbf0fd 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledExchangeFactory.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledExchangeFactory.java @@ -22,6 +22,7 @@ import org.apache.camel.Exchange; import org.apache.camel.PooledExchange; import org.apache.camel.spi.ExchangeFactory; import org.apache.camel.support.DefaultPooledExchange; +import org.apache.camel.support.ResetableClock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,8 +67,7 @@ public final class PooledExchangeFactory extends PrototypeExchangeFactory { } // reset exchange for reuse - PooledExchange ee = (PooledExchange) exchange; - ee.reset(System.currentTimeMillis()); + ((ResetableClock) exchange.getClock()).reset(); return exchange; } @@ -88,8 +88,7 @@ public final class PooledExchangeFactory extends PrototypeExchangeFactory { } // reset exchange for reuse - PooledExchange ee = (PooledExchange) exchange; - ee.reset(System.currentTimeMillis()); + ((ResetableClock) exchange.getClock()).reset(); return exchange; } diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledProcessorExchangeFactory.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledProcessorExchangeFactory.java index 634d2db3cd7..2f5b96f8c3d 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledProcessorExchangeFactory.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/PooledProcessorExchangeFactory.java @@ -25,6 +25,7 @@ import org.apache.camel.Processor; import org.apache.camel.spi.ProcessorExchangeFactory; import org.apache.camel.support.DefaultPooledExchange; import org.apache.camel.support.ExchangeHelper; +import org.apache.camel.support.ResetableClock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,9 +73,7 @@ public class PooledProcessorExchangeFactory extends PrototypeProcessorExchangeFa } // reset exchange for reuse - PooledExchange ee = (PooledExchange) answer; - ee.reset(System.currentTimeMillis()); - + ((ResetableClock) exchange.getClock()).reset(); ExchangeHelper.copyResults(answer, exchange); return answer; } @@ -98,8 +97,7 @@ public class PooledProcessorExchangeFactory extends PrototypeProcessorExchangeFa } // reset exchange for reuse - PooledExchange ee = (PooledExchange) answer; - ee.reset(System.currentTimeMillis()); + ((ResetableClock) exchange.getClock()).reset(); ExchangeHelper.copyResults(answer, exchange); // do not reuse message id on copy @@ -129,9 +127,7 @@ public class PooledProcessorExchangeFactory extends PrototypeProcessorExchangeFa } // reset exchange for reuse - PooledExchange ee = (PooledExchange) answer; - ee.reset(System.currentTimeMillis()); - + ((ResetableClock) answer.getClock()).reset(); return answer; } diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/event/ExchangeCompletedEvent.java b/core/camel-base/src/main/java/org/apache/camel/impl/event/ExchangeCompletedEvent.java index 4c7dcd1ea32..91ab9cf3470 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/event/ExchangeCompletedEvent.java +++ b/core/camel-base/src/main/java/org/apache/camel/impl/event/ExchangeCompletedEvent.java @@ -26,21 +26,14 @@ public class ExchangeCompletedEvent extends AbstractExchangeEvent implements Cam public ExchangeCompletedEvent(Exchange source) { super(source); - long created = getExchange().getCreated(); - if (created > 0) { - this.timeTaken = System.currentTimeMillis() - created; - } else { - this.timeTaken = -1; - } + + this.timeTaken = getExchange().getClock().elapsed(); } @Override public String toString() { - if (timeTaken > -1) { - return getExchange().getExchangeId() + " exchange completed" - + " took: " + TimeUtils.printDuration(timeTaken, true); - } else { - return getExchange().getExchangeId() + " exchange completed"; - } + return getExchange().getExchangeId() + " exchange completed" + + " took: " + TimeUtils.printDuration(timeTaken, true); + } } diff --git a/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTimeClauseTest.java b/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTimeClauseTest.java index 6be1d2b3c79..bb1cb10226e 100644 --- a/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTimeClauseTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTimeClauseTest.java @@ -36,7 +36,7 @@ public class MockEndpointTimeClauseTest extends ContextTestSupport { @Test public void testReceivedTimestamp() throws Exception { MockEndpoint mock = getMockEndpoint("mock:result"); - mock.message(0).predicate(e -> e.getCreated() > 0); + mock.message(0).predicate(e -> e.getClock().getCreated() > 0); mock.message(0).exchangeProperty(Exchange.RECEIVED_TIMESTAMP).isNotNull(); mock.message(0).exchangeProperty(Exchange.RECEIVED_TIMESTAMP).isInstanceOf(Date.class); diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/event/EventNotifierExchangeCompletedTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/event/EventNotifierExchangeCompletedTest.java index e43d1adf263..3cfe101fe43 100644 --- a/core/camel-core/src/test/java/org/apache/camel/impl/event/EventNotifierExchangeCompletedTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/impl/event/EventNotifierExchangeCompletedTest.java @@ -70,7 +70,7 @@ public class EventNotifierExchangeCompletedTest extends ContextTestSupport { assertEquals("direct://start", event.getExchange().getFromEndpoint().getEndpointUri()); // grab the created timestamp - long created = event.getExchange().getCreated(); + long created = event.getExchange().getClock().getCreated(); assertTrue(created > 0); // calculate elapsed time diff --git a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java index 4e54af27e31..f6d5e1a8586 100644 --- a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java @@ -650,7 +650,8 @@ public class SimpleTest extends LanguageTestSupport { @Test public void testDateExchangeCreated() throws Exception { - Object out = evaluateExpression("${date:exchangeCreated:hh:mm:ss a}", ("" + exchange.getCreated()).getClass()); + Object out + = evaluateExpression("${date:exchangeCreated:hh:mm:ss a}", ("" + exchange.getClock().getCreated()).getClass()); assertNotNull(out); } diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ExchangeCreatedTimestampTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/ExchangeCreatedTimestampTest.java index b671336b19f..b352479fb31 100644 --- a/core/camel-core/src/test/java/org/apache/camel/processor/ExchangeCreatedTimestampTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/processor/ExchangeCreatedTimestampTest.java @@ -34,7 +34,7 @@ public class ExchangeCreatedTimestampTest extends ContextTestSupport { assertMockEndpointsSatisfied(); - long created = mock.getReceivedExchanges().get(0).getCreated(); + long created = mock.getReceivedExchanges().get(0).getClock().getCreated(); assertTrue(created > 0); } diff --git a/core/camel-core/src/test/java/org/apache/camel/support/AbstractExchangeTest.java b/core/camel-core/src/test/java/org/apache/camel/support/AbstractExchangeTest.java index 2710b25b52f..8be0bc8b500 100644 --- a/core/camel-core/src/test/java/org/apache/camel/support/AbstractExchangeTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/support/AbstractExchangeTest.java @@ -17,6 +17,7 @@ package org.apache.camel.support; import org.apache.camel.CamelContext; +import org.apache.camel.Clock; import org.apache.camel.Exchange; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.spi.DataType; @@ -32,6 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertSame; public class AbstractExchangeTest { static class CustomAbstractExchange extends AbstractExchange { + private final Clock clock = new MonotonicClock(); CustomAbstractExchange(CustomAbstractExchange abstractExchange) { super(abstractExchange); @@ -45,6 +47,11 @@ public class AbstractExchangeTest { AbstractExchange newCopy() { return new CustomAbstractExchange(this); } + + @Override + public Clock getClock() { + return clock; + } } @Test diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java index a89d53da607..b07f6ee39ee 100644 --- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java +++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java @@ -394,7 +394,7 @@ public class ManagedBacklogDebugger implements ManagedBacklogDebuggerMBean { + "]"; } - long elapsed = TimeUtils.elapsedMillisSince(suspendedExchange.getCreated()); + long elapsed = TimeUtils.elapsedMillisSince(suspendedExchange.getClock().getCreated()); messageHistoryBuilder .append(" <messageHistoryEntry") diff --git a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java index 42ff7b76398..df3ed17dcc3 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java @@ -53,7 +53,6 @@ abstract class AbstractExchange implements Exchange { protected final CamelContext context; protected Map<String, Object> properties; // create properties on-demand as we use internal properties mostly - protected long created; protected Message in; protected Message out; protected Exception exception; @@ -81,7 +80,6 @@ abstract class AbstractExchange implements Exchange { public AbstractExchange(CamelContext context, ExchangePattern pattern) { this.context = context; this.pattern = pattern; - this.created = System.currentTimeMillis(); internalProperties = new EnumMap<>(ExchangePropertyKey.class); privateExtension = new ExtendedExchangeExtension(this); @@ -90,7 +88,6 @@ abstract class AbstractExchange implements Exchange { public AbstractExchange(Exchange parent) { this.context = parent.getContext(); this.pattern = parent.getPattern(); - this.created = parent.getCreated(); internalProperties = new EnumMap<>(ExchangePropertyKey.class); @@ -103,7 +100,6 @@ abstract class AbstractExchange implements Exchange { AbstractExchange(AbstractExchange parent) { this.context = parent.getContext(); this.pattern = parent.getPattern(); - this.created = parent.getCreated(); this.internalProperties = new EnumMap<>(parent.internalProperties); @@ -140,7 +136,6 @@ abstract class AbstractExchange implements Exchange { public AbstractExchange(Endpoint fromEndpoint) { this.context = fromEndpoint.getCamelContext(); this.pattern = fromEndpoint.getExchangePattern(); - this.created = System.currentTimeMillis(); internalProperties = new EnumMap<>(ExchangePropertyKey.class); privateExtension = new ExtendedExchangeExtension(this); @@ -150,7 +145,6 @@ abstract class AbstractExchange implements Exchange { public AbstractExchange(Endpoint fromEndpoint, ExchangePattern pattern) { this.context = fromEndpoint.getCamelContext(); this.pattern = pattern; - this.created = System.currentTimeMillis(); internalProperties = new EnumMap<>(ExchangePropertyKey.class); privateExtension = new ExtendedExchangeExtension(this); @@ -159,7 +153,7 @@ abstract class AbstractExchange implements Exchange { @Override public long getCreated() { - return created; + return getClock().getCreated(); } abstract AbstractExchange newCopy(); diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java index 91cb6c882b0..51bc0669bdb 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchange.java @@ -20,6 +20,7 @@ import java.util.EnumMap; import java.util.Map; import org.apache.camel.CamelContext; +import org.apache.camel.Clock; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; @@ -29,38 +30,58 @@ import org.apache.camel.ExchangePropertyKey; * The default and only implementation of {@link Exchange}. */ public final class DefaultExchange extends AbstractExchange { + private final Clock timeInfo; DefaultExchange(CamelContext context, EnumMap<ExchangePropertyKey, Object> internalProperties, Map<String, Object> properties) { super(context, internalProperties, properties); + + this.timeInfo = new MonotonicClock(); } public DefaultExchange(CamelContext context) { super(context); + + this.timeInfo = new MonotonicClock(); } public DefaultExchange(CamelContext context, ExchangePattern pattern) { super(context, pattern); + + this.timeInfo = new MonotonicClock(); } public DefaultExchange(Exchange parent) { super(parent); + + this.timeInfo = parent.getClock(); } DefaultExchange(AbstractExchange parent) { super(parent); + + this.timeInfo = parent.getClock(); } public DefaultExchange(Endpoint fromEndpoint) { super(fromEndpoint); + + this.timeInfo = new MonotonicClock(); } public DefaultExchange(Endpoint fromEndpoint, ExchangePattern pattern) { super(fromEndpoint, pattern); + + this.timeInfo = new MonotonicClock(); } @Override AbstractExchange newCopy() { return new DefaultExchange(this); } + + @Override + public Clock getClock() { + return timeInfo; + } } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java index 19c757c1309..286875aed55 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultPooledExchange.java @@ -19,6 +19,7 @@ package org.apache.camel.support; import java.util.concurrent.ConcurrentHashMap; import org.apache.camel.CamelContext; +import org.apache.camel.Clock; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; @@ -29,7 +30,7 @@ import org.apache.camel.PooledExchange; * The default and only implementation of {@link PooledExchange}. */ public final class DefaultPooledExchange extends AbstractExchange implements PooledExchange { - + private final ResetableClock clock; private OnDoneTask onDone; private Class<?> originalInClassType; private Message originalOut; @@ -40,30 +41,46 @@ public final class DefaultPooledExchange extends AbstractExchange implements Poo super(context); this.originalPattern = getPattern(); this.properties = new ConcurrentHashMap<>(8); + + this.clock = new ResetableClock(); } public DefaultPooledExchange(CamelContext context, ExchangePattern pattern) { super(context, pattern); this.originalPattern = pattern; this.properties = new ConcurrentHashMap<>(8); + + this.clock = new ResetableClock(); } public DefaultPooledExchange(Exchange parent) { super(parent); this.originalPattern = parent.getPattern(); this.properties = new ConcurrentHashMap<>(8); + + Clock parentClock = parent.getClock(); + + if (parentClock instanceof ResetableClock rs) { + this.clock = rs; + } else { + this.clock = new ResetableClock(parent.getClock()); + } } public DefaultPooledExchange(Endpoint fromEndpoint) { super(fromEndpoint); this.originalPattern = getPattern(); this.properties = new ConcurrentHashMap<>(8); + + this.clock = new ResetableClock(); } public DefaultPooledExchange(Endpoint fromEndpoint, ExchangePattern pattern) { super(fromEndpoint, pattern); this.originalPattern = pattern; this.properties = new ConcurrentHashMap<>(8); + + this.clock = new ResetableClock(); } @Override @@ -86,8 +103,10 @@ public final class DefaultPooledExchange extends AbstractExchange implements Poo } public void done() { - if (created > 0) { - this.created = 0; // by setting to 0 we also flag that this exchange is done and needs to be reset to use again + if (clock.getCreated() > 0) { + // by unsetting (setting to 0) we also flag that this exchange is done and needs to be reset to use again + clock.unset(); + this.properties.clear(); internalProperties.clear(); if (this.safeCopyProperties != null) { @@ -117,12 +136,14 @@ public final class DefaultPooledExchange extends AbstractExchange implements Poo if (onDone != null) { onDone.onDone(this); } + } } @Override + @Deprecated public void reset(long created) { - this.created = created; + clock.reset(); } @Override @@ -169,4 +190,9 @@ public final class DefaultPooledExchange extends AbstractExchange implements Poo } } + @Override + public Clock getClock() { + return clock; + } + } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/LanguageHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/LanguageHelper.java index c31913beecd..65c19334c8e 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/LanguageHelper.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/LanguageHelper.java @@ -263,7 +263,7 @@ public final class LanguageHelper { * @return A Date instance */ public static Date dateFromExchangeCreated(Exchange exchange) { - long num = exchange.getCreated(); + long num = exchange.getClock().getCreated(); return new Date(num); } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/MessageHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/MessageHelper.java index 7760d70ca8a..4382bb347d4 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/MessageHelper.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/MessageHelper.java @@ -716,7 +716,7 @@ public final class MessageHelper { label = "from[" + URISupport.sanitizeUri(StringHelper.limitLength(exchange.getFromEndpoint().getEndpointUri(), 100)) + "]"; } - long elapsed = System.currentTimeMillis() - exchange.getCreated(); + final long elapsed = exchange.getClock().elapsed(); List<MessageHistory> list = exchange.getProperty(ExchangePropertyKey.MESSAGE_HISTORY, List.class); boolean enabled = list != null; @@ -768,9 +768,8 @@ public final class MessageHelper { // fast label = URISupport.sanitizeUri(StringHelper.limitLength(label, 100)); // we do not have elapsed time - elapsed = 0; sb.append("\t...\n"); - sb.append(String.format(goMessageHistoryOutput, loc, routeId + "/" + id, label, elapsed)); + sb.append(String.format(goMessageHistoryOutput, loc, routeId + "/" + id, label, 0)); sb.append("\n"); } } else { @@ -790,9 +789,8 @@ public final class MessageHelper { // characters in the sanitizeUri method and will be reasonably // fast label = URISupport.sanitizeUri(StringHelper.limitLength(history.getNode().getLabel(), 100)); - elapsed = history.getElapsed(); - sb.append(String.format(goMessageHistoryOutput, loc, routeId + "/" + id, label, elapsed)); + sb.append(String.format(goMessageHistoryOutput, loc, routeId + "/" + id, label, history.getElapsed())); sb.append("\n"); } } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java b/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java new file mode 100644 index 00000000000..3a3ca3f482b --- /dev/null +++ b/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java @@ -0,0 +1,38 @@ +/* + * 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.support; + +import org.apache.camel.Clock; + +public class MonotonicClock implements Clock { + private final long created; + + MonotonicClock() { + this.created = System.currentTimeMillis(); + } + + @Override + public long elapsed() { + return System.currentTimeMillis() - created; + } + + @Override + public long getCreated() { + return created; + } +} diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ResetableClock.java b/core/camel-support/src/main/java/org/apache/camel/support/ResetableClock.java new file mode 100644 index 00000000000..cabf9c776fc --- /dev/null +++ b/core/camel-support/src/main/java/org/apache/camel/support/ResetableClock.java @@ -0,0 +1,57 @@ +/* + * 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.support; + +import org.apache.camel.Clock; + +public final class ResetableClock implements Clock { + private long created; + + ResetableClock(Clock clock) { + this.created = clock.getCreated(); + } + + ResetableClock() { + this.created = System.currentTimeMillis(); + } + + @Override + public long elapsed() { + return System.currentTimeMillis() - created; + } + + @Override + public long getCreated() { + return created; + } + + /** + * Reset the clock to the current point in time + */ + public void reset() { + this.created = System.currentTimeMillis(); + } + + /** + * Unset the clock (set to zero). This is part of the pooling exchange support, so that the exchange can be marked + * as done and reused + */ + void unset() { + this.created = 0; + } +} diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc index e9d33a5b449..8b79b865cd3 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc @@ -11,6 +11,8 @@ from both 4.0 to 4.1 and 4.1 to 4.2. Removed the deprecated constructor from the internal class `org.apache.camel.util.StopWatch`. Users of this class are advised to use the default constructor if necessary. +The method `getCreated` is now deprecated. Access to the time-related information from the exchange should be done via `getClock`. + === camel-azure-cosmosdb The useDefaultIdentity parameter has been removed in favor of the credentialType parameter. Now user should select between SHARED_ACCOUNT_KEY and AZURE_IDENTITY.