1616package com .stackify .api .common ;
1717
1818import java .io .IOException ;
19+ import java .util .Hashtable ;
20+ import java .util .Map ;
1921
2022import org .slf4j .Logger ;
2123import org .slf4j .LoggerFactory ;
@@ -44,27 +46,22 @@ public class AppIdentityService {
4446 * Five minutes (in milliseconds)
4547 */
4648 private static long FIVE_MINUTES_MILLIS = 300000 ;
47-
48- /**
49- * Timestamp of the last query
50- */
51- private long lastQuery = 0 ;
52-
49+
5350 /**
54- * The cached app identity
51+ * Map<ApplicationName, AppIdentityState> The cached app identity
5552 */
56- private Optional < AppIdentity > appIdentity = Optional . absent ();
57-
53+ private Map < String , AppIdentityState > applicationIdentityCache = new Hashtable < String , AppIdentityState > ();
54+
5855 /**
5956 * The API configuration
6057 */
61- private final ApiConfiguration apiConfig ;
58+ private final ApiConfiguration defaultApiConfig ;
6259
6360 /**
6461 * Jackson object mapper
6562 */
6663 private final ObjectMapper objectMapper ;
67-
64+
6865 /**
6966 * Constructor
7067 * @param apiConfig The API configuration
@@ -73,55 +70,128 @@ public class AppIdentityService {
7370 public AppIdentityService (final ApiConfiguration apiConfig , final ObjectMapper objectMapper ) {
7471 Preconditions .checkNotNull (apiConfig );
7572 Preconditions .checkNotNull (objectMapper );
76-
77- this .apiConfig = apiConfig ;
73+
74+ this .defaultApiConfig = apiConfig ;
7875 this .objectMapper = objectMapper ;
7976 }
80-
77+
78+ private boolean isCached (final String applicationName ) {
79+ Preconditions .checkNotNull (applicationName );
80+ return applicationIdentityCache .containsKey (applicationName );
81+ }
82+
8183 /**
8284 * Retrieves the application identity given the environment details
8385 * @return The application identity
8486 */
85- public Optional <AppIdentity > getAppIdentity () {
86- if (!appIdentity .isPresent ()) {
87- long currentTimeMillis = System .currentTimeMillis ();
88-
89- if (lastQuery + FIVE_MINUTES_MILLIS < currentTimeMillis ) {
90- try {
91- lastQuery = currentTimeMillis ;
92- appIdentity = Optional .fromNullable (identifyApp ());
93- LOGGER .debug ("Application identity: {}" , appIdentity .get ());
94- } catch (Throwable t ) {
95- LOGGER .info ("Unable to determine application identity" , t );
96- }
87+ private Optional <AppIdentity > getAppIdentity (ApiConfiguration apiConfig ) {
88+ final String applicationName = apiConfig .getApplication ();
89+
90+ if (applicationName == null )
91+ return Optional .absent ();
92+
93+ // new state with current timestamp
94+ final AppIdentityState state = new AppIdentityState ();
95+
96+ final long now = System .currentTimeMillis ();
97+
98+ if (state .lastModified () + FIVE_MINUTES_MILLIS < now ) {
99+ try {
100+ final AppIdentity identity = identifyApp (apiConfig );
101+ // Obtain AppIdentity for current app
102+ applicationIdentityCache .put (
103+ applicationName , state .updateAppIdentity (identity )
104+ );
105+
106+ LOGGER .debug ("Application identity: {}" , identity );
107+
108+ } catch (Throwable t ) {
109+ LOGGER .info ("Unable to determine application identity" , t );
97110 }
98111 }
99-
100- return appIdentity ;
112+
113+ return applicationIdentityCache . get ( apiConfig . getApplication ()). getAppIdentity () ;
101114 }
102-
115+
116+
117+
118+ public Optional <AppIdentity > getAppIdentity (final String applicationName ) {
119+ if (isCached (applicationName )) {
120+ return applicationIdentityCache .get (applicationName ).getAppIdentity ();
121+
122+ } else {
123+ // use existing apiConfig, with new application name
124+ final ApiConfiguration updatedApiConfig = defaultApiConfig .toBuilder ().application (applicationName ).build ();
125+ return getAppIdentity (updatedApiConfig );
126+ }
127+ }
128+
129+
130+ public Optional <AppIdentity > getAppIdentity () {
131+ return getAppIdentity (defaultApiConfig );
132+ }
133+
103134 /**
104135 * Retrieves the application identity given the environment details
105136 * @return The application identity
106137 * @throws IOException
107- * @throws HttpException
138+ * @throws HttpException
108139 */
109- private AppIdentity identifyApp () throws IOException , HttpException {
110-
140+ private AppIdentity identifyApp (ApiConfiguration apiConfig ) throws IOException , HttpException {
111141 // convert to json bytes
112-
113142 byte [] jsonBytes = objectMapper .writer ().writeValueAsBytes (apiConfig .getEnvDetail ());
114-
143+
115144 // post to stackify
116-
117- HttpClient httpClient = new HttpClient (apiConfig );
118- String responseString = httpClient .post ("/Metrics/IdentifyApp" , jsonBytes );
119-
145+ final HttpClient httpClient = new HttpClient (apiConfig );
146+ final String responseString = httpClient .post ("/Metrics/IdentifyApp" , jsonBytes );
147+
120148 // deserialize the response and return the app identity
121-
122149 ObjectReader jsonReader = objectMapper .reader (new TypeReference <AppIdentity >(){});
123- AppIdentity appIdentity = jsonReader .readValue (responseString );
124-
125- return appIdentity ;
150+ return jsonReader .readValue (responseString );
151+ }
152+
153+ /**
154+ * This class contains appIdentity and it's modification date
155+ */
156+ private class AppIdentityState {
157+
158+ private Optional <AppIdentity > mayBeAppIdentity = Optional .absent ();
159+ private long lastQueryTimeStamp ;
160+
161+ public AppIdentityState () {
162+ this .lastQueryTimeStamp = 0 ;
163+ this .mayBeAppIdentity = Optional .absent ();
164+ }
165+
166+ public AppIdentityState (final AppIdentity appIdentity ) {
167+ this .touch ();
168+ this .mayBeAppIdentity = Optional .fromNullable (appIdentity );
169+ }
170+
171+ public AppIdentityState (final AppIdentity appIdentity , long timestamp ) {
172+ this .lastQueryTimeStamp = timestamp ;
173+ this .mayBeAppIdentity = Optional .fromNullable (appIdentity );
174+ }
175+
176+ public final AppIdentityState updateAppIdentity (final AppIdentity appIdentity ) {
177+ mayBeAppIdentity = Optional .fromNullable (appIdentity );
178+ return this ;
179+ }
180+
181+ public final Optional <AppIdentity > getAppIdentity () {
182+ this .touch ();
183+ return mayBeAppIdentity ;
184+ }
185+
186+ public final long lastModified () {
187+ return lastQueryTimeStamp ;
188+ }
189+
190+ /**
191+ * Changes last modified date
192+ */
193+ public final void touch () {
194+ this .lastQueryTimeStamp = System .currentTimeMillis ();
195+ }
126196 }
127197}
0 commit comments