mirror of https://github.com/buster-so/buster.git
Merge pull request #710 from buster-so/staging
hotfix on multiple trigger tasks for download
This commit is contained in:
commit
e2a6454b33
|
@ -121,12 +121,19 @@ describe('downloadMetricFileHandler', () => {
|
|||
organizationId: mockOrganizationId,
|
||||
});
|
||||
|
||||
// Verify task was triggered with correct parameters
|
||||
expect(tasks.trigger).toHaveBeenCalledWith('export-metric-data', {
|
||||
metricId: mockMetricId,
|
||||
userId: mockUser.id,
|
||||
organizationId: mockOrganizationId,
|
||||
});
|
||||
// Verify task was triggered with correct parameters and idempotency
|
||||
expect(tasks.trigger).toHaveBeenCalledWith(
|
||||
'export-metric-data',
|
||||
{
|
||||
metricId: mockMetricId,
|
||||
userId: mockUser.id,
|
||||
organizationId: mockOrganizationId,
|
||||
},
|
||||
{
|
||||
idempotencyKey: `export-${mockUser.id}-${mockMetricId}`,
|
||||
idempotencyKeyTTL: '5m',
|
||||
}
|
||||
);
|
||||
|
||||
// Verify successful response
|
||||
expect(result).toMatchObject({
|
||||
|
|
|
@ -50,12 +50,21 @@ export async function downloadMetricFileHandler(
|
|||
}
|
||||
|
||||
try {
|
||||
// Trigger the export task
|
||||
const handle = await tasks.trigger('export-metric-data', {
|
||||
metricId,
|
||||
userId: user.id,
|
||||
organizationId,
|
||||
});
|
||||
// Trigger the export task with idempotency to prevent duplicates
|
||||
// If the same user tries to download the same metric within 5 minutes,
|
||||
// it will return the existing task instead of creating a new one
|
||||
const handle = await tasks.trigger(
|
||||
'export-metric-data',
|
||||
{
|
||||
metricId,
|
||||
userId: user.id,
|
||||
organizationId,
|
||||
},
|
||||
{
|
||||
idempotencyKey: `export-${user.id}-${metricId}`,
|
||||
idempotencyKeyTTL: '5m', // 5 minutes TTL
|
||||
}
|
||||
);
|
||||
|
||||
// Poll for task completion with timeout
|
||||
const startTime = Date.now();
|
||||
|
|
|
@ -22,9 +22,9 @@ export const MetricDataTruncatedWarning: React.FC<MetricDataTruncatedWarningProp
|
|||
setIsDownloading(true);
|
||||
setHasError(false);
|
||||
|
||||
// Create a timeout promise that rejects after 3 minutes
|
||||
// Create a timeout promise that rejects after 2 minutes (matching backend timeout)
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
setTimeout(() => reject(new Error('Download timeout')), 3 * 60 * 1000); // 3 minutes
|
||||
setTimeout(() => reject(new Error('Download timeout')), 2 * 60 * 1000); // 2 minutes
|
||||
});
|
||||
|
||||
// Race between the API call and the timeout
|
||||
|
@ -36,14 +36,17 @@ export const MetricDataTruncatedWarning: React.FC<MetricDataTruncatedWarningProp
|
|||
// Simply navigate to the download URL
|
||||
// The response-content-disposition header will force a download
|
||||
window.location.href = response.downloadUrl;
|
||||
|
||||
// Keep button disabled for longer since download is async
|
||||
// User can click again after 5 seconds if needed
|
||||
setTimeout(() => {
|
||||
setIsDownloading(false);
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
console.error('Failed to download metric file:', error);
|
||||
setHasError(true);
|
||||
} finally {
|
||||
// Add a small delay before removing loading state since download happens async
|
||||
setTimeout(() => {
|
||||
setIsDownloading(false);
|
||||
}, 1000);
|
||||
// Re-enable button immediately on error so user can retry
|
||||
setIsDownloading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue