azkaban-aplcache

SessionCache documentation enhanced; config keys moved to

3/13/2018 1:49:42 AM

Details

diff --git a/az-core/src/main/java/azkaban/Constants.java b/az-core/src/main/java/azkaban/Constants.java
index 820b041..9497ffe 100644
--- a/az-core/src/main/java/azkaban/Constants.java
+++ b/az-core/src/main/java/azkaban/Constants.java
@@ -205,6 +205,8 @@ public class Constants {
     public static final String EXECUTOR_SELECTOR_COMPARATOR_PREFIX =
         "azkaban.executorselector.comparator.";
     public static final String QUEUEPROCESSING_ENABLED = "azkaban.queueprocessing.enabled";
+
+    public static final String SESSION_TIME_TO_LIVE = "session.time.to.live";
   }
 
   public static class FlowProperties {
diff --git a/az-core/src/main/java/azkaban/utils/Props.java b/az-core/src/main/java/azkaban/utils/Props.java
index 9ee0869..1b6c433 100644
--- a/az-core/src/main/java/azkaban/utils/Props.java
+++ b/az-core/src/main/java/azkaban/utils/Props.java
@@ -39,7 +39,7 @@ import java.util.TreeMap;
 import org.apache.log4j.Logger;
 
 /**
- * Hashmap implementation of a hierarchitical properties with helpful converter functions and
+ * Hashmap implementation of a hierarchical properties with helpful converter functions and
  * Exception throwing. This class is not threadsafe.
  */
 public class Props {
diff --git a/az-core/src/main/java/azkaban/utils/PropsUtils.java b/az-core/src/main/java/azkaban/utils/PropsUtils.java
index 6784f40..5caa30b 100644
--- a/az-core/src/main/java/azkaban/utils/PropsUtils.java
+++ b/az-core/src/main/java/azkaban/utils/PropsUtils.java
@@ -142,7 +142,7 @@ public class PropsUtils {
     return false;
   }
 
-  public static boolean isVarialbeReplacementPattern(final String str) {
+  public static boolean isVariableReplacementPattern(final String str) {
     final Matcher matcher = VARIABLE_REPLACEMENT_PATTERN.matcher(str);
     return matcher.matches();
   }
diff --git a/azkaban-common/src/main/java/azkaban/project/FlowLoaderUtils.java b/azkaban-common/src/main/java/azkaban/project/FlowLoaderUtils.java
index 1fa4ac3..eee2df3 100644
--- a/azkaban-common/src/main/java/azkaban/project/FlowLoaderUtils.java
+++ b/azkaban-common/src/main/java/azkaban/project/FlowLoaderUtils.java
@@ -263,14 +263,14 @@ public class FlowLoaderUtils {
     for (final String jobName : jobPropsMap.keySet()) {
       final Props jobProps = jobPropsMap.get(jobName);
       final String xms = jobProps.getString(XMS, null);
-      if (xms != null && !PropsUtils.isVarialbeReplacementPattern(xms)
+      if (xms != null && !PropsUtils.isVariableReplacementPattern(xms)
           && Utils.parseMemString(xms) > sizeMaxXms) {
         errors.add(String.format(
             "%s: Xms value has exceeded the allowed limit (max Xms = %s)",
             jobName, maxXms));
       }
       final String xmx = jobProps.getString(XMX, null);
-      if (xmx != null && !PropsUtils.isVarialbeReplacementPattern(xmx)
+      if (xmx != null && !PropsUtils.isVariableReplacementPattern(xmx)
           && Utils.parseMemString(xmx) > sizeMaxXmx) {
         errors.add(String.format(
             "%s: Xmx value has exceeded the allowed limit (max Xmx = %s)",
diff --git a/azkaban-common/src/main/java/azkaban/server/session/SessionCache.java b/azkaban-common/src/main/java/azkaban/server/session/SessionCache.java
index 505a59d..49303ca 100644
--- a/azkaban-common/src/main/java/azkaban/server/session/SessionCache.java
+++ b/azkaban-common/src/main/java/azkaban/server/session/SessionCache.java
@@ -16,6 +16,7 @@
 
 package azkaban.server.session;
 
+import azkaban.Constants.ConfigurationKeys;
 import azkaban.utils.Props;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
@@ -25,28 +26,32 @@ import java.util.concurrent.TimeUnit;
 /**
  * Cache for web session.
  *
- * The following global azkaban properties can be used: max.num.sessions - used to determine the
- * number of live sessions that azkaban will handle. Default is 10000 session.time.to.live -Number
- * of seconds before session expires. Default set to 10 hours.
+ * The following global Azkaban properties are used:
+ * <ul>
+ *   <li>{@code max.num.sessions} - number of live sessions that Azkaban handles, default is 10000
+ *   <li>{@code session.time.to.live} - number of milliseconds before the session expires,
+ *   default 36000000 ms, i.e. 10 hours.
+ * </ul>
  */
 public class SessionCache {
 
   private static final int MAX_NUM_SESSIONS = 10000;
-  private static final long SESSION_TIME_TO_LIVE = 10 * 60 * 60 * 1000L;
+  private static final long DEFAULT_SESSION_TIME_TO_LIVE = 10 * 60 * 60 * 1000L; // 10 hours
 
-  // private CacheManager manager = CacheManager.create();
   private final Cache<String, Session> cache;
 
+  private final long effectiveSessionTimeToLive;
+
   /**
    * Constructor taking global props.
    */
   @Inject
   public SessionCache(final Props props) {
+    this.effectiveSessionTimeToLive = props.getLong(ConfigurationKeys.SESSION_TIME_TO_LIVE,
+        DEFAULT_SESSION_TIME_TO_LIVE);
     this.cache = CacheBuilder.newBuilder()
         .maximumSize(props.getInt("max.num.sessions", MAX_NUM_SESSIONS))
-        .expireAfterAccess(
-            props.getLong("session.time.to.live", SESSION_TIME_TO_LIVE),
-            TimeUnit.MILLISECONDS)
+        .expireAfterAccess(effectiveSessionTimeToLive, TimeUnit.MILLISECONDS)
         .build();
   }
 
@@ -58,6 +63,10 @@ public class SessionCache {
     return elem;
   }
 
+  public long getEffectiveSessionTimeToLive() {
+    return effectiveSessionTimeToLive;
+  }
+
   /**
    * Adds a session to the cache. Accessible through the session ID.
    */
diff --git a/azkaban-common/src/test/java/azkaban/server/session/SessionCacheTest.java b/azkaban-common/src/test/java/azkaban/server/session/SessionCacheTest.java
new file mode 100644
index 0000000..f205be3
--- /dev/null
+++ b/azkaban-common/src/test/java/azkaban/server/session/SessionCacheTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 LinkedIn Corp.
+ *
+ * Licensed 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 azkaban.server.session;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import azkaban.user.User;
+import azkaban.utils.Props;
+import azkaban.utils.PropsUtils;
+import org.junit.Test;
+
+public final class SessionCacheTest {
+
+  final String propsString = "{ \"session.time.to.live\": \"100\" }";
+
+  SessionCache freshSessionCache() throws Exception {
+    final Props props = PropsUtils.fromJSONString(propsString);
+    return new SessionCache(props);
+  }
+
+  @Test
+  public void SessionCacheHit() throws Exception {
+    final SessionCache sessionCache = freshSessionCache();
+    final Session session = new Session("TEST_SESSION_ID", new User("TEST_USER_HIT"),
+        "123.12.12.123");
+    sessionCache.addSession(session);
+    assertThat(sessionCache.getSession("TEST_SESSION_ID")).isEqualTo(session);
+  }
+
+  @Test
+  public void SessionCacheMiss() throws Exception {
+    final SessionCache sessionCache = freshSessionCache();
+    final Session session = new Session("TEST_SESSION_ID", new User("TEST_USER_MISS"),
+        "123.12.12.123");
+    sessionCache.addSession(session);
+    Thread.sleep(200L);
+    assertThat(sessionCache.getSession("TEST_SESSION_ID")).isNull();
+  }
+
+}