From d0c212b01d0b9d902226da4aaca12d6f175f05a6 Mon Sep 17 00:00:00 2001 From: Paul Caruana Date: Thu, 18 Apr 2024 19:45:18 +0200 Subject: [PATCH 1/4] Letting Memory Cache takes care of the locks cause of concurrent requests --- .../Client/Authentication/TokenHandler.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Conductor/Client/Authentication/TokenHandler.cs b/Conductor/Client/Authentication/TokenHandler.cs index 7fa978c3..b6327eaa 100644 --- a/Conductor/Client/Authentication/TokenHandler.cs +++ b/Conductor/Client/Authentication/TokenHandler.cs @@ -21,12 +21,13 @@ public TokenHandler() public string GetToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) { - string token = (string)_memoryCache.Get(authenticationSettings); - if (token != null) - { - return token; - } - return RefreshToken(authenticationSettings, tokenClient); + string token = _memoryCache.GetOrCreate(authenticationSettings, entry => { + + entry.AbsoluteExpiration = GetTokenExpiration(); + return GetTokenFromServer(authenticationSettings, tokenClient); + + }); + return token; } public string RefreshToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) @@ -34,11 +35,15 @@ public string RefreshToken(OrkesAuthenticationSettings authenticationSettings, T lock (_lockObject) { string token = GetTokenFromServer(authenticationSettings, tokenClient); - var expirationTime = System.DateTimeOffset.Now.AddMinutes(30); + var expirationTime = GetTokenExpiration(); _memoryCache.Set(authenticationSettings, token, expirationTime); return token; } } + private DateTimeOffset GetTokenExpiration() + { + return System.DateTimeOffset.Now.AddMinutes(30); + } private string GetTokenFromServer(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) { From 20e00653b27292250e9dbe49c8b779820922e2b7 Mon Sep 17 00:00:00 2001 From: Paul Caruana Date: Fri, 19 Apr 2024 19:09:53 +0200 Subject: [PATCH 2/4] Locking Mechanism on getting the token for concurrent requests 1) All Waiting for Lock if Token is Null 2) First goes in Checks Again Memory Cache 3) Nothing is found and calls GetTokenFromServer and fetches token 4) Lock is released and 2nd one goes in. checks Memory Cache and its found 5) Return Token --- .../Client/Authentication/TokenHandler.cs | 71 +++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/Conductor/Client/Authentication/TokenHandler.cs b/Conductor/Client/Authentication/TokenHandler.cs index b6327eaa..44e7c57b 100644 --- a/Conductor/Client/Authentication/TokenHandler.cs +++ b/Conductor/Client/Authentication/TokenHandler.cs @@ -10,6 +10,7 @@ public class TokenHandler { private static int REFRESH_TOKEN_RETRY_COUNTER_LIMIT = 5; private static readonly object _lockObject = new object(); + private static readonly object _getTokenlockObject = new object(); private readonly MemoryCache _memoryCache; private static ILogger _logger; @@ -18,16 +19,19 @@ public TokenHandler() _memoryCache = new MemoryCache(new MemoryCacheOptions()); _logger = ApplicationLogging.CreateLogger(); } - - public string GetToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) + public string GetToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) { - string token = _memoryCache.GetOrCreate(authenticationSettings, entry => { - - entry.AbsoluteExpiration = GetTokenExpiration(); - return GetTokenFromServer(authenticationSettings, tokenClient); + string token = (string)_memoryCache.Get(authenticationSettings); + if (token != null) + { + return token; + } - }); - return token; + lock (_getTokenlockObject) + { + token = (string)_memoryCache.Get(authenticationSettings); + return token != null ? token : RefreshToken(authenticationSettings, tokenClient); + } } public string RefreshToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) @@ -35,15 +39,11 @@ public string RefreshToken(OrkesAuthenticationSettings authenticationSettings, T lock (_lockObject) { string token = GetTokenFromServer(authenticationSettings, tokenClient); - var expirationTime = GetTokenExpiration(); + var expirationTime = System.DateTimeOffset.Now.AddMinutes(30); _memoryCache.Set(authenticationSettings, token, expirationTime); return token; } } - private DateTimeOffset GetTokenExpiration() - { - return System.DateTimeOffset.Now.AddMinutes(30); - } private string GetTokenFromServer(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) { @@ -64,5 +64,50 @@ private string GetTokenFromServer(OrkesAuthenticationSettings authenticationSett } throw new Exception("Failed to refresh authentication token"); } + // public string GetToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) + // { + // string token = _memoryCache.GetOrCreate(authenticationSettings, entry => { + + // entry.AbsoluteExpiration = GetTokenExpiration(); + // return GetTokenFromServer(authenticationSettings, tokenClient); + + // }); + // return token; + // } + + // public string RefreshToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) + // { + // lock (_lockObject) + // { + // string token = GetTokenFromServer(authenticationSettings, tokenClient); + // var expirationTime = GetTokenExpiration(); + // _memoryCache.Set(authenticationSettings, token, expirationTime); + // return token; + // } + // } + // private DateTimeOffset GetTokenExpiration() + // { + // return System.DateTimeOffset.Now.AddMinutes(30); + // } + + // private string GetTokenFromServer(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) + // { + // var tokenRequest = new Client.Models.GenerateTokenRequest( + // keyId: authenticationSettings.KeyId, + // keySecret: authenticationSettings.KeySecret + // ); + // for (int attempt = 0; attempt < REFRESH_TOKEN_RETRY_COUNTER_LIMIT; attempt += 1) + // { + // try + // { + // return tokenClient.GenerateToken(tokenRequest)._token; + // } + // catch (Exception e) + // { + // _logger.LogError($"Failed to refresh authentication token, attempt = {attempt}, error = {e.Message}"); + // } + // } + // throw new Exception("Failed to refresh authentication token"); + // } } } \ No newline at end of file From ea7dbdf326f3d31f862a1490a05b5cb92dea7b19 Mon Sep 17 00:00:00 2001 From: Paul Caruana Date: Fri, 19 Apr 2024 19:10:36 +0200 Subject: [PATCH 3/4] Locking Mechanism on getting the token for concurrent requests 1) All Waiting for Lock if Token is Null 2) First goes in Checks Again Memory Cache 3) Nothing is found and calls GetTokenFromServer and fetches token 4) Lock is released and 2nd one goes in. checks Memory Cache and its found 5) Return Token --- .../Client/Authentication/TokenHandler.cs | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/Conductor/Client/Authentication/TokenHandler.cs b/Conductor/Client/Authentication/TokenHandler.cs index 44e7c57b..a8bbe47d 100644 --- a/Conductor/Client/Authentication/TokenHandler.cs +++ b/Conductor/Client/Authentication/TokenHandler.cs @@ -64,50 +64,5 @@ private string GetTokenFromServer(OrkesAuthenticationSettings authenticationSett } throw new Exception("Failed to refresh authentication token"); } - // public string GetToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) - // { - // string token = _memoryCache.GetOrCreate(authenticationSettings, entry => { - - // entry.AbsoluteExpiration = GetTokenExpiration(); - // return GetTokenFromServer(authenticationSettings, tokenClient); - - // }); - // return token; - // } - - // public string RefreshToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) - // { - // lock (_lockObject) - // { - // string token = GetTokenFromServer(authenticationSettings, tokenClient); - // var expirationTime = GetTokenExpiration(); - // _memoryCache.Set(authenticationSettings, token, expirationTime); - // return token; - // } - // } - // private DateTimeOffset GetTokenExpiration() - // { - // return System.DateTimeOffset.Now.AddMinutes(30); - // } - - // private string GetTokenFromServer(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) - // { - // var tokenRequest = new Client.Models.GenerateTokenRequest( - // keyId: authenticationSettings.KeyId, - // keySecret: authenticationSettings.KeySecret - // ); - // for (int attempt = 0; attempt < REFRESH_TOKEN_RETRY_COUNTER_LIMIT; attempt += 1) - // { - // try - // { - // return tokenClient.GenerateToken(tokenRequest)._token; - // } - // catch (Exception e) - // { - // _logger.LogError($"Failed to refresh authentication token, attempt = {attempt}, error = {e.Message}"); - // } - // } - // throw new Exception("Failed to refresh authentication token"); - // } } } \ No newline at end of file From 99cbe1ac7fcae2c8831c33aa568557a62084fbee Mon Sep 17 00:00:00 2001 From: Paul Caruana Date: Tue, 14 May 2024 22:54:14 +0200 Subject: [PATCH 4/4] merging and recommiting --- Conductor/Client/Authentication/TokenHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Conductor/Client/Authentication/TokenHandler.cs b/Conductor/Client/Authentication/TokenHandler.cs index a8bbe47d..7b78aa93 100644 --- a/Conductor/Client/Authentication/TokenHandler.cs +++ b/Conductor/Client/Authentication/TokenHandler.cs @@ -19,7 +19,7 @@ public TokenHandler() _memoryCache = new MemoryCache(new MemoryCacheOptions()); _logger = ApplicationLogging.CreateLogger(); } - public string GetToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) + public string GetToken(OrkesAuthenticationSettings authenticationSettings, TokenResourceApi tokenClient) { string token = (string)_memoryCache.Get(authenticationSettings); if (token != null)