Refactor ServiceBaseClass: Implement exponential backoff for API requests and enhance error handling in pipeline status retrieval (#20628)

* Refactor ServiceBaseClass: Implement exponential backoff for API requests and enhance error handling in pipeline status retrieval

* Enhance ServiceBaseClass: Introduce MAX_CONSECUTIVE_ERRORS constant and refactor API request handling with makeRetryRequest utility for improved error management
This commit is contained in:
Shailesh Parmar 2025-04-04 17:06:05 +05:30
parent 028664f58b
commit a875a39ff5
3 changed files with 46 additions and 9 deletions

View File

@ -91,3 +91,5 @@ export const DBT = {
dataQualityTest1: 'unique_customers_customer_id', dataQualityTest1: 'unique_customers_customer_id',
dataQualityTest2: 'not_null_customers_customer_id', dataQualityTest2: 'not_null_customers_customer_id',
}; };
export const MAX_CONSECUTIVE_ERRORS = 3;

View File

@ -18,6 +18,7 @@ import {
PlaywrightWorkerArgs, PlaywrightWorkerArgs,
TestType, TestType,
} from '@playwright/test'; } from '@playwright/test';
import { MAX_CONSECUTIVE_ERRORS } from '../../../constant/service';
import { import {
descriptionBox, descriptionBox,
getApiContext, getApiContext,
@ -30,6 +31,7 @@ import { visitServiceDetailsPage } from '../../../utils/service';
import { import {
deleteService, deleteService,
getServiceCategoryFromService, getServiceCategoryFromService,
makeRetryRequest,
Services, Services,
testConnection, testConnection,
} from '../../../utils/serviceIngestion'; } from '../../../utils/serviceIngestion';
@ -275,19 +277,31 @@ class ServiceBaseClass {
)[0]; )[0];
const oneHourBefore = Date.now() - 86400000; const oneHourBefore = Date.now() - 86400000;
let consecutiveErrors = 0;
await expect await expect
.poll( .poll(
async () => { async () => {
const response = await apiContext try {
.get( const response = await makeRetryRequest({
`/api/v1/services/ingestionPipelines/${encodeURIComponent( url: `/api/v1/services/ingestionPipelines/${encodeURIComponent(
workflowData.fullyQualifiedName workflowData.fullyQualifiedName
)}/pipelineStatus?startTs=${oneHourBefore}&endTs=${Date.now()}` )}/pipelineStatus?startTs=${oneHourBefore}&endTs=${Date.now()}`,
) page,
.then((res) => res.json()); });
consecutiveErrors = 0; // Reset error counter on success
return response.data[0]?.pipelineState; return response.data[0]?.pipelineState;
} catch (error) {
consecutiveErrors++;
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
throw new Error(
`Failed to get pipeline status after ${MAX_CONSECUTIVE_ERRORS} consecutive attempts`
);
}
return 'running';
}
}, },
{ {
// Custom expect message for reporting, optional. // Custom expect message for reporting, optional.
@ -311,7 +325,6 @@ class ServiceBaseClass {
await page.waitForSelector('[data-testid="data-assets-header"]'); await page.waitForSelector('[data-testid="data-assets-header"]');
await pipelinePromise; await pipelinePromise;
await statusPromise; await statusPromise;
await page.waitForSelector('[data-testid="ingestions"]'); await page.waitForSelector('[data-testid="ingestions"]');

View File

@ -14,7 +14,7 @@
import { expect, Page } from '@playwright/test'; import { expect, Page } from '@playwright/test';
import { GlobalSettingOptions } from '../constant/settings'; import { GlobalSettingOptions } from '../constant/settings';
import { EntityTypeEndpoint } from '../support/entity/Entity.interface'; import { EntityTypeEndpoint } from '../support/entity/Entity.interface';
import { toastNotification } from './common'; import { getApiContext, toastNotification } from './common';
import { escapeESReservedCharacters } from './entity'; import { escapeESReservedCharacters } from './entity';
export enum Services { export enum Services {
@ -160,3 +160,25 @@ export const checkServiceFieldSectionHighlighting = async (
) => { ) => {
await page.waitForSelector(`[data-id="${field}"][data-highlighted="true"]`); await page.waitForSelector(`[data-id="${field}"][data-highlighted="true"]`);
}; };
export const makeRetryRequest = async (data: {
url: string;
page: Page;
retries?: number;
}) => {
const { url, page, retries = 3 } = data;
const { apiContext } = await getApiContext(page);
for (let i = 0; i < retries; i++) {
try {
const response = await apiContext.get(url);
return response.json();
} catch (error) {
if (i === retries - 1) {
throw error;
}
await page.waitForTimeout(1000 * (i + 1)); // Exponential backoff
}
}
};