You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by or...@apache.org on 2023/12/21 12:12:52 UTC

(camel) branch main updated: CAMEL-20257: convert AbstractContext to the clock API

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 12d8bf0be4e CAMEL-20257: convert AbstractContext to the clock API
12d8bf0be4e is described below

commit 12d8bf0be4e3c0531de31b4f8e34f3d4f685e6de
Author: Otavio Rodolfo Piske <an...@gmail.com>
AuthorDate: Tue Dec 19 15:27:20 2023 -0300

    CAMEL-20257: convert AbstractContext to the clock API
    
    This also makes the clock API more generic and usable for other use cases besides tracking exchanges
---
 .../camel/component/jms/BrowsableQueueTest.java    |  2 +
 .../main/java/org/apache/camel/CamelContext.java   | 10 +++
 .../main/java/org/apache/camel/ContextEvents.java} | 28 ++------
 .../src/main/java/org/apache/camel/Exchange.java   |  1 +
 .../java/org/apache/camel/{ => clock}/Clock.java   |  8 +--
 .../java/org/apache/camel/clock/ContextClock.java  | 80 ++++++++++++++++++++++
 .../java/org/apache/camel/clock/EventClock.java}   | 35 +++++-----
 .../camel/impl/engine/AbstractCamelContext.java    | 26 ++++---
 .../apache/camel/support/AbstractExchangeTest.java |  2 +-
 .../org/apache/camel/support/DefaultExchange.java  |  2 +-
 .../camel/support/DefaultPooledExchange.java       |  2 +-
 .../org/apache/camel/support/MonotonicClock.java   |  8 +--
 .../org/apache/camel/support/ResetableClock.java   |  6 +-
 13 files changed, 145 insertions(+), 65 deletions(-)

diff --git a/components/camel-jms/src/test/java/org/apache/camel/component/jms/BrowsableQueueTest.java b/components/camel-jms/src/test/java/org/apache/camel/component/jms/BrowsableQueueTest.java
index 7382bb627ba..68c456a6927 100644
--- a/components/camel-jms/src/test/java/org/apache/camel/component/jms/BrowsableQueueTest.java
+++ b/components/camel-jms/src/test/java/org/apache/camel/component/jms/BrowsableQueueTest.java
@@ -29,11 +29,13 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.parallel.Isolated;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
+@Isolated("Needs greater isolation due to CAMEL-20269")
 public class BrowsableQueueTest extends AbstractJMSTest {
     @Order(2)
     @RegisterExtension
diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index cbf1548e1dd..1035141046d 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.camel.clock.EventClock;
 import org.apache.camel.spi.CamelContextNameStrategy;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.DataFormat;
@@ -165,6 +166,7 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
      *
      * @return the uptime in days/hours/minutes
      */
+    @Deprecated
     String getUptime();
 
     /**
@@ -172,13 +174,21 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
      *
      * @return the uptime in millis seconds
      */
+    @Deprecated
     long getUptimeMillis();
 
     /**
      * Gets the date and time Camel was started up.
      */
+    @Deprecated
     Date getStartDate();
 
+    /**
+     * Gets a clock instance that keeps track of time for relevant CamelContext events
+     * @return A clock instance
+     */
+    EventClock<ContextEvents> getClock();
+
     // Service Methods
     //-----------------------------------------------------------------------
 
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java b/core/camel-api/src/main/java/org/apache/camel/ContextEvents.java
similarity index 60%
copy from core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java
copy to core/camel-api/src/main/java/org/apache/camel/ContextEvents.java
index 4cbda16341c..2c0e7673227 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ContextEvents.java
@@ -14,29 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.support;
 
-import java.util.concurrent.TimeUnit;
-
-import org.apache.camel.Clock;
+package org.apache.camel;
 
 /**
- * A clock that is used for precise timing.
+ * Context events that can be traced by an {@link org.apache.camel.clock.EventClock}
  */
-public class MonotonicClock implements Clock {
-    private final long createdNano;
-
-    MonotonicClock() {
-        this.createdNano = System.nanoTime();
-    }
-
-    @Override
-    public long elapsed() {
-        return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - createdNano);
-    }
-
-    @Override
-    public long getCreated() {
-        return System.currentTimeMillis() - elapsed();
-    }
+public enum ContextEvents {
+    /**
+     * Start event
+     */
+    START
 }
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 9f7aac0f0bc..9e7abd83ad0 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
@@ -18,6 +18,7 @@ package org.apache.camel;
 
 import java.util.Map;
 
+import org.apache.camel.clock.Clock;
 import org.apache.camel.spi.UnitOfWork;
 import org.apache.camel.spi.annotations.ConstantProvider;
 
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/Clock.java
similarity index 90%
rename from core/camel-api/src/main/java/org/apache/camel/Clock.java
rename to core/camel-api/src/main/java/org/apache/camel/clock/Clock.java
index 66e18399965..3cee3bd99f2 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Clock.java
+++ b/core/camel-api/src/main/java/org/apache/camel/clock/Clock.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel;
+package org.apache.camel.clock;
 
 import java.time.Instant;
 import java.time.ZoneId;
@@ -22,19 +22,19 @@ import java.time.ZonedDateTime;
 import java.util.Date;
 
 /**
- * A clock used to track the lifetime of an exchange
+ * A clock abstraction used to track pass of time
  */
 public interface Clock {
 
     /**
-     * The elapsed time since the creation of the exchange
+     * The elapsed time since the creation of the clock
      *
      * @return The elapsed time, in milliseconds, since the creation of the exchange
      */
     long elapsed();
 
     /**
-     * The point in time the exchange was created
+     * The point in time the clock was created
      *
      * @return The point in time, in milliseconds, the exchange was created.
      * @see    System#currentTimeMillis()
diff --git a/core/camel-api/src/main/java/org/apache/camel/clock/ContextClock.java b/core/camel-api/src/main/java/org/apache/camel/clock/ContextClock.java
new file mode 100644
index 00000000000..2bc575a0abf
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/clock/ContextClock.java
@@ -0,0 +1,80 @@
+/*
+ * 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.clock;
+
+import java.util.Date;
+import java.util.EnumMap;
+
+import org.apache.camel.ContextEvents;
+
+/**
+ * An event clock that tracks the pass of time for different types of context-related events (see {@link ContextEvents})
+ */
+public final class ContextClock implements EventClock<ContextEvents> {
+    private EnumMap<ContextEvents, Clock> events = new EnumMap<>(ContextEvents.class);
+
+    @Override
+    public long elapsed() {
+        return 0;
+    }
+
+    @Override
+    public long getCreated() {
+        return 0;
+    }
+
+    @Override
+    public void add(ContextEvents event, Clock clock) {
+        events.put(event, clock);
+    }
+
+    @Override
+    public Clock get(ContextEvents event) {
+        return events.get(event);
+    }
+
+    /**
+     * Get the elapsed time for the event
+     * @param event the event to get the elapsed time
+     * @param defaultValue the default value to provide if the event is not being tracked
+     * @return The elapsed time or the default value if the event is not being tracked
+     */
+    public long elapsed(ContextEvents event, long defaultValue) {
+        Clock clock = events.get(event);
+        if (clock == null) {
+            return defaultValue;
+        }
+
+        return clock.elapsed();
+    }
+
+    /**
+     * Get the time for the event as a Date object
+     * @param event the event to get the elapsed time
+     * @param defaultValue the default value to provide if the event is not being tracked
+     * @return The Date object representing the creation date or the default value if the event is not being tracked
+     */
+    public Date asDate(ContextEvents event, Date defaultValue) {
+        Clock clock = events.get(event);
+        if (clock == null) {
+            return defaultValue;
+        }
+
+        return clock.asDate();
+    }
+}
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java b/core/camel-api/src/main/java/org/apache/camel/clock/EventClock.java
similarity index 58%
copy from core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java
copy to core/camel-api/src/main/java/org/apache/camel/clock/EventClock.java
index 4cbda16341c..924640a5814 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/MonotonicClock.java
+++ b/core/camel-api/src/main/java/org/apache/camel/clock/EventClock.java
@@ -14,29 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.support;
 
-import java.util.concurrent.TimeUnit;
-
-import org.apache.camel.Clock;
+package org.apache.camel.clock;
 
 /**
- * A clock that is used for precise timing.
+ * A specialized clock that tracks the pass of time for one or more types of events
+ * @param <T> The event type as an Enum
  */
-public class MonotonicClock implements Clock {
-    private final long createdNano;
-
-    MonotonicClock() {
-        this.createdNano = System.nanoTime();
-    }
+public interface EventClock<T extends Enum<T>> extends Clock {
 
-    @Override
-    public long elapsed() {
-        return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - createdNano);
-    }
+    /**
+     * Add the event to be tracked
+     * @param event the event to track
+     * @param clock the clock associated with the event
+     */
+    void add(T event, Clock clock);
 
-    @Override
-    public long getCreated() {
-        return System.currentTimeMillis() - elapsed();
-    }
+    /**
+     * Get the clock for the event
+     * @param event the event to get the clock for
+     * @return the clock instance or null if not set
+     */
+    Clock get(T event);
 }
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 49629404a41..49b5d5bb0d5 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -44,6 +44,7 @@ import org.apache.camel.CamelContextAware;
 import org.apache.camel.CatalogCamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.ContextEvents;
 import org.apache.camel.Endpoint;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.FailedToStartComponentException;
@@ -71,6 +72,9 @@ import org.apache.camel.TypeConverter;
 import org.apache.camel.VetoCamelContextStartException;
 import org.apache.camel.api.management.JmxSystemPropertyKeys;
 import org.apache.camel.catalog.RuntimeCamelCatalog;
+import org.apache.camel.clock.Clock;
+import org.apache.camel.clock.ContextClock;
+import org.apache.camel.clock.EventClock;
 import org.apache.camel.console.DevConsoleRegistry;
 import org.apache.camel.console.DevConsoleResolver;
 import org.apache.camel.health.HealthCheckRegistry;
@@ -171,6 +175,7 @@ import org.apache.camel.support.NormalizedUri;
 import org.apache.camel.support.OrderedComparator;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.support.ProcessorEndpoint;
+import org.apache.camel.support.ResetableClock;
 import org.apache.camel.support.ResolverHelper;
 import org.apache.camel.support.jsse.SSLContextParameters;
 import org.apache.camel.support.service.BaseService;
@@ -266,7 +271,7 @@ public abstract class AbstractCamelContext extends BaseService
     private Debugger debugger;
     private long buildTaken;
     private long initTaken;
-    private long startDate;
+    private final ContextClock clock = new ContextClock();
     private SSLContextParameters sslContextParameters;
     private StartupSummaryLevel startupSummaryLevel = StartupSummaryLevel.Default;
 
@@ -1877,18 +1882,12 @@ public abstract class AbstractCamelContext extends BaseService
 
     @Override
     public long getUptimeMillis() {
-        if (startDate == 0) {
-            return 0;
-        }
-        return System.currentTimeMillis() - startDate;
+        return clock.elapsed(ContextEvents.START, 0);
     }
 
     @Override
     public Date getStartDate() {
-        if (startDate == 0) {
-            return null;
-        }
-        return new Date(startDate);
+        return clock.asDate(ContextEvents.START, null);
     }
 
     @Override
@@ -1896,6 +1895,11 @@ public abstract class AbstractCamelContext extends BaseService
         return VersionHolder.VERSION;
     }
 
+    @Override
+    public EventClock<ContextEvents> getClock() {
+        return clock;
+    }
+
     @Override
     protected void doSuspend() throws Exception {
         EventHelper.notifyCamelContextSuspending(this);
@@ -2431,7 +2435,7 @@ public abstract class AbstractCamelContext extends BaseService
         LOG.info("Apache Camel {} ({}) is starting", getVersion(), camelContextExtension.getName());
 
         vetoed = null;
-        startDate = System.currentTimeMillis();
+        clock.add(ContextEvents.START, new ResetableClock());
         stopWatch.restart();
 
         // Start the route controller
@@ -2955,7 +2959,7 @@ public abstract class AbstractCamelContext extends BaseService
         startupStepRecorder.stop();
 
         // and clear start date
-        startDate = 0;
+        clock.add(ContextEvents.START, null);
 
         // Call all registered trackers with this context
         // Note, this may use a partially constructed object
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 8be0bc8b500..6e9179a909c 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,8 +17,8 @@
 package org.apache.camel.support;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.Clock;
 import org.apache.camel.Exchange;
+import org.apache.camel.clock.Clock;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeAware;
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 0ed154f3817..5eae5f92755 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,11 +20,11 @@ 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;
 import org.apache.camel.ExchangePropertyKey;
+import org.apache.camel.clock.Clock;
 
 /**
  * The default and only implementation of {@link Exchange}.
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 a92fccb94e6..75fa2d70e42 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,12 +19,12 @@ 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;
 import org.apache.camel.Message;
 import org.apache.camel.PooledExchange;
+import org.apache.camel.clock.Clock;
 
 /**
  * The default and only implementation of {@link PooledExchange}.
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
index 4cbda16341c..7e7ab0573be 100644
--- 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
@@ -18,15 +18,15 @@ package org.apache.camel.support;
 
 import java.util.concurrent.TimeUnit;
 
-import org.apache.camel.Clock;
+import org.apache.camel.clock.Clock;
 
 /**
- * A clock that is used for precise timing.
+ * A clock that increases monotonically (i.e.: does not go back in time)
  */
-public class MonotonicClock implements Clock {
+public final class MonotonicClock implements Clock {
     private final long createdNano;
 
-    MonotonicClock() {
+    public MonotonicClock() {
         this.createdNano = System.nanoTime();
     }
 
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
index dfacfa694ef..00091ac8353 100644
--- 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
@@ -18,7 +18,7 @@ package org.apache.camel.support;
 
 import java.util.concurrent.TimeUnit;
 
-import org.apache.camel.Clock;
+import org.apache.camel.clock.Clock;
 
 /**
  * A clock that can be reset.
@@ -27,12 +27,12 @@ public final class ResetableClock implements Clock {
     private long created;
     private long createdNano;
 
-    ResetableClock(Clock clock) {
+    public ResetableClock(Clock clock) {
         this.created = clock.getCreated();
         this.createdNano = System.nanoTime();
     }
 
-    ResetableClock() {
+    public ResetableClock() {
         this.created = System.currentTimeMillis();
         this.createdNano = System.nanoTime();
     }