diff --git a/pkcs11/src/backend/login.rs b/pkcs11/src/backend/login.rs index 38027e1..72fad12 100644 --- a/pkcs11/src/backend/login.rs +++ b/pkcs11/src/backend/login.rs @@ -160,14 +160,24 @@ impl LoginCtx { } fn next_instance(&self) -> &InstanceData { - for _ in 0..self.slot.instances.len() { - let index = self.slot.instance_balancer.fetch_add(1, Relaxed); - let index = index % self.slot.instances.len(); - let instance = &self.slot.instances[index]; + let index = self.slot.instance_balancer.fetch_add(1, Relaxed); + let index = index % self.slot.instances.len(); + let instance = &self.slot.instances[index]; + match instance.should_try() { + InstanceAttempt::Failed => {} + InstanceAttempt::Working | InstanceAttempt::Retry => return instance, + } + for i in 0..self.slot.instances.len() - 1 { + let instance = &self.slot.instances[index + i]; match instance.should_try() { InstanceAttempt::Failed => continue, - InstanceAttempt::Working | InstanceAttempt::Retry => return instance, + InstanceAttempt::Working | InstanceAttempt::Retry => { + // This not true round-robin in case of multithreaded acces + // This is degraded mode so best-effort is attempted at best + self.slot.instance_balancer.fetch_add(i, Relaxed); + return instance; + } } } @@ -255,7 +265,10 @@ impl LoginCtx { retry_count += 1; let api_call_clone = api_call.clone(); match api_call_clone(&instance.config) { - Ok(result) => return Ok(result), + Ok(result) => { + instance.clear_failed(); + return Ok(result); + } // If the server is in an unusable state, skip retries and try the next one Err(apis::Error::ResponseError(err @ ResponseContent { status: 500, .. }))