mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-07-03 15:16:56 +00:00
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:
parent
028664f58b
commit
a875a39ff5
@ -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;
|
||||||
|
@ -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"]');
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user