I have a scenario in which I call many APIs throughout my application lifecycle.
Incase sometime the server sends me a 503 response code, it will also send a lockdown object which has a timestamp associated in one of the fields. The reason of this being that I have to block further calls to the server till the timestamp expires.
My solution consists of a retrofit client coupled with an okhttp Interceptor
Here are the steps of execution:
Interceptor (Sentinel) intercepts the request Interceptor checks a global exception value which is held by an object class (Singelton – LockDownManager ) returns a true or false based on the current timestamp. The LockDownManager is also responsible for memoizing the exception, incase the server is still locked down it helps in rethrowing the same exception.
below is my implementation, I am only including the relevant parts from Sentinel:
class Sentinel : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { // Check with global counter if request can be executed val canClientMakeRequest = LockDownManager.isServerAvailable() if (!canClientMakeRequest) { throw LockDownManager.ex as HttpStatusDetailedException } else { // Mark exception null LockDownManager.ex = null } //....... Continue execution // Response received // Check if response contains 503 object // Done by checkIfHasToMemoize(...) }
Here is how exception is memoized and parsed:
fun checkIfHasToMemoize(resp: Response) { // Parse response and derive errorObj - excluded val errorObj = httpResult.httpError if (errorObj != null) { val detailedException = HttpStatusDetailedException(httpStatusCode, "Unexpected HTTP(S) result:" + " $ result", errorObj) // Set LockDown -> isServerAvailable if (detailedException.httpCode == 503 && null != LockDownManager.ex) LockDownManager.ex = detailedException throw detailedException }
Finally here is my singleton Manager:
object LockDownManager { @Volatile var ex: HttpStatusDetailedException? = null fun isServerAvailable(): Boolean { if (ex == null) { return true } val serverAvailableTimestamp = ex?.blockUntil ?: 0L if (serverAvailableTimestamp == 0L) { return true } val c = Calendar.getInstance() c.timeZone = TimeZone.getTimeZone("UTC") val currentTime = c.timeInMillis return currentTime > serverAvailableTimestamp } }
This is a multithreaded environment and more than the semantics of my variable names I am concerned about the veracity of thread safety.
The post Thread safety of throwing exception – memoized appeared first on 100% Private Proxies - Fast, Anonymous, Quality, Unlimited USA Private Proxy!.