## Description Adds a guarded retry action for Intercom imports that have not recorded progress for 15 minutes. The API reports stalled state, rotates the import run identifier under an account lock, preserves existing progress and logs, and queues a fresh worker only when no other Intercom import is active for the account. The import details page shows Retry immediately before Abandon only while the server reports the import as stalled. This is Phase 1, Task 1 of the [Intercom import optimization plan (CW-7615)](https://linear.app/chatwoot/issue/CW-7615/optimize-intercom-import-reliability-and-bulk-message-ingestion). This replaces #15049 with the updated 15-minute threshold and is based directly on the latest `develop`. ## Closes - [CW-7519](https://linear.app/chatwoot/issue/CW-7519/explore-intercom-import) ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How to test 1. Open a processing Intercom import updated within the last 15 minutes and confirm Retry is hidden. 2. Set its updated timestamp to more than 15 minutes ago and reload the details page. 3. Confirm Retry appears immediately before Abandon. 4. Retry the import and confirm it returns to Pending while existing progress, logs, and the original start time remain intact. 5. Confirm a second retry is rejected and another active Intercom import prevents queueing. ## Checklist - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have added tests that prove the change is effective - [x] New and existing focused tests pass locally with my changes
44 lines
856 B
JavaScript
44 lines
856 B
JavaScript
/* global axios */
|
|
|
|
import ApiClient from './ApiClient';
|
|
|
|
class DataImportsAPI extends ApiClient {
|
|
constructor() {
|
|
super('data_imports', { accountScoped: true });
|
|
}
|
|
|
|
start(id) {
|
|
return axios.post(`${this.url}/${id}/start`);
|
|
}
|
|
|
|
retry(id) {
|
|
return axios.post(`${this.url}/${id}/retry`);
|
|
}
|
|
|
|
abandon(id) {
|
|
return axios.post(`${this.url}/${id}/abandon`);
|
|
}
|
|
|
|
show(id, params = {}) {
|
|
return axios.get(`${this.url}/${id}`, { params });
|
|
}
|
|
|
|
validateSource(payload) {
|
|
return axios.post(`${this.url}/validate_source`, payload);
|
|
}
|
|
|
|
downloadSkipLogs(id) {
|
|
return axios.get(`${this.url}/${id}/skip_logs.csv`, {
|
|
responseType: 'blob',
|
|
});
|
|
}
|
|
|
|
downloadErrorLogs(id) {
|
|
return axios.get(`${this.url}/${id}/error_logs.csv`, {
|
|
responseType: 'blob',
|
|
});
|
|
}
|
|
}
|
|
|
|
export default new DataImportsAPI();
|