@@ -224,14 +224,14 @@ void getServiceStatusReportsAuthFailuresAndMissingPlugins() throws Exception {
224224 server .enqueue ("GET" , healthPath , 401 , "{\" detail\" :\" denied\" }" );
225225 AirflowRESTClient authFailureClient = newClient (server , basePath );
226226 PipelineServiceClientResponse authFailure = authFailureClient .getServiceStatusInternal ();
227- assertEquals (500 , authFailure .getCode ());
227+ assertEquals (401 , authFailure .getCode ());
228228 assertTrue (authFailure .getReason ().contains ("Authentication failed" ));
229229
230230 server .enqueue ("GET" , healthPath , 200 , "{\" version\" :\" " + version + "\" }" );
231231 server .enqueue ("GET" , healthPath , 404 , "{\" detail\" :\" missing\" }" );
232232 AirflowRESTClient missingPluginClient = newClient (server , basePath );
233233 PipelineServiceClientResponse missingPlugin = missingPluginClient .getServiceStatusInternal ();
234- assertEquals (500 , missingPlugin .getCode ());
234+ assertEquals (404 , missingPlugin .getCode ());
235235 assertTrue (missingPlugin .getReason ().contains ("Airflow APIs not found" ));
236236 }
237237 }
@@ -249,7 +249,7 @@ void getServiceStatusReportsVersionMismatch() throws Exception {
249249 AirflowRESTClient client = newClient (server , basePath );
250250 PipelineServiceClientResponse status = client .getServiceStatusInternal ();
251251
252- assertEquals (500 , status .getCode ());
252+ assertEquals (422 , status .getCode ());
253253 assertTrue (
254254 status .getReason ().contains ("upgrade your server" )
255255 || status .getReason ().contains ("upgrade your ingestion client" ));
@@ -500,6 +500,54 @@ void runPipelineThrowsDeploymentExceptionWhenAirflowReturnsAnError() throws Exce
500500 }
501501 }
502502
503+ @ Test
504+ void getServiceStatusRecoversFromTransientFailure () throws Exception {
505+ try (AirflowTestServer server = new AirflowTestServer ()) {
506+ String basePath = "/airflow" ;
507+ String healthPath = basePath + "/pluginsv2/api/v2/openmetadata/health-auth" ;
508+ String version = PipelineServiceClient .getServerVersion ();
509+
510+ // First call: detection probe succeeds
511+ server .enqueue ("GET" , healthPath , 200 , "{\" version\" :\" " + version + "\" }" );
512+ // Second call (first getServiceStatus attempt): transient 500
513+ server .enqueue ("GET" , healthPath , 500 , "{\" error\" :\" selector manager closed\" }" );
514+ // Third call (retry): healthy response
515+ server .enqueue ("GET" , healthPath , 200 , "{\" version\" :\" " + version + "\" }" );
516+
517+ AirflowRESTClient client = newClient (server , basePath );
518+
519+ PipelineServiceClientResponse status = client .getServiceStatus ();
520+
521+ assertEquals (200 , status .getCode ());
522+ assertEquals (version , status .getVersion ());
523+ List <RequestRecord > healthRequests = server .requests ("GET" , healthPath );
524+ assertEquals (3 , healthRequests .size ());
525+ }
526+ }
527+
528+ @ Test
529+ void getServiceStatusDoesNotRetryOnAuthError () throws Exception {
530+ try (AirflowTestServer server = new AirflowTestServer ()) {
531+ String basePath = "/airflow" ;
532+ String healthPath = basePath + "/pluginsv2/api/v2/openmetadata/health-auth" ;
533+ String version = PipelineServiceClient .getServerVersion ();
534+
535+ // Detection probe succeeds
536+ server .enqueue ("GET" , healthPath , 200 , "{\" version\" :\" " + version + "\" }" );
537+ // Auth failure — should NOT be retried
538+ server .enqueue ("GET" , healthPath , 401 , "{\" error\" :\" unauthorized\" }" );
539+
540+ AirflowRESTClient client = newClient (server , basePath );
541+
542+ PipelineServiceClientResponse status = client .getServiceStatus ();
543+
544+ assertEquals (401 , status .getCode ());
545+ // Only 2 requests: detection probe + single 401 (no retry)
546+ List <RequestRecord > healthRequests = server .requests ("GET" , healthPath );
547+ assertEquals (2 , healthRequests .size ());
548+ }
549+ }
550+
503551 private static AirflowRESTClient newClient (AirflowTestServer server , String basePath )
504552 throws KeyStoreException {
505553 Parameters parameters = new Parameters ();
@@ -512,7 +560,12 @@ private static AirflowRESTClient newClient(AirflowTestServer server, String base
512560 config .setApiEndpoint (server .url (basePath ));
513561 config .setMetadataApiEndpoint ("http://localhost:8585/api" );
514562 config .setParameters (parameters );
515- return new AirflowRESTClient (config );
563+ return new AirflowRESTClient (config ) {
564+ @ Override
565+ protected long getRetryBackoffMillis () {
566+ return 0L ;
567+ }
568+ };
516569 }
517570
518571 private static IngestionPipeline ingestionPipeline (String name , boolean enabled ) {
@@ -527,9 +580,18 @@ private static Map<String, List<String>> cookieHeaders(String... values) {
527580 }
528581
529582 private static void invokePrivate (Object target , String methodName ) throws Exception {
530- Method method = target .getClass ().getDeclaredMethod (methodName );
531- method .setAccessible (true );
532- method .invoke (target );
583+ Class <?> clazz = target .getClass ();
584+ while (clazz != null ) {
585+ try {
586+ Method method = clazz .getDeclaredMethod (methodName );
587+ method .setAccessible (true );
588+ method .invoke (target );
589+ return ;
590+ } catch (NoSuchMethodException e ) {
591+ clazz = clazz .getSuperclass ();
592+ }
593+ }
594+ throw new NoSuchMethodException (target .getClass ().getName () + "." + methodName + "()" );
533595 }
534596
535597 private record RequestRecord (
0 commit comments