fix sse error handling if shop api error part 2

This commit is contained in:
team2
2026-04-25 20:21:59 +02:00
parent cf970d2b49
commit 2044a465ad
3 changed files with 37 additions and 3 deletions

View File

@@ -3,12 +3,12 @@
parameters: parameters:
retriex.commerce.enabled: true retriex.commerce.enabled: true
retriex.commerce.max_shop_results: '%env(SHOPWARE_STORE_API_MAX_RESULT)%' retriex.commerce.max_shop_results: '%env(SHOPWARE_STORE_API_MAX_RESULT)%'
retriex.commerce.shop_timeout: 5 retriex.commerce.shop_timeout: 3
retriex.commerce.store_api_base_url: '%env(SHOPWARE_STORE_API_BASE_URL)%' retriex.commerce.store_api_base_url: '%env(SHOPWARE_STORE_API_BASE_URL)%'
retriex.commerce.sales_channel_access_key: '%env(SHOPWARE_SALES_CHANNEL_ACCESS_KEY)%' retriex.commerce.sales_channel_access_key: '%env(SHOPWARE_SALES_CHANNEL_ACCESS_KEY)%'
retriex.commerce.search_repair.enabled: true retriex.commerce.search_repair.enabled: true
retriex.commerce.search_repair.max_queries: 3 retriex.commerce.search_repair.max_queries: 2
retriex.commerce.search_repair.min_primary_results_without_repair: 2 retriex.commerce.search_repair.min_primary_results_without_repair: 2
# Shop matching and presentation configuration. # Shop matching and presentation configuration.

View File

@@ -386,12 +386,24 @@ document.addEventListener('DOMContentLoaded', () => {
const source = new EventSource(`/ask-sse/${encodeURIComponent(jobId)}`); const source = new EventSource(`/ask-sse/${encodeURIComponent(jobId)}`);
state.eventSource = source; state.eventSource = source;
let networkErrorTimer = null;
const clearNetworkErrorTimer = () => {
if (!networkErrorTimer) {
return;
}
clearTimeout(networkErrorTimer);
networkErrorTimer = null;
};
const complete = () => { const complete = () => {
if (finished) { if (finished) {
return; return;
} }
finished = true; finished = true;
clearNetworkErrorTimer();
finishEventStream(); finishEventStream();
resolve(); resolve();
}; };
@@ -402,6 +414,7 @@ document.addEventListener('DOMContentLoaded', () => {
} }
finished = true; finished = true;
clearNetworkErrorTimer();
finishEventStream(); finishEventStream();
reject(err); reject(err);
}; };
@@ -409,12 +422,18 @@ document.addEventListener('DOMContentLoaded', () => {
state.completeStream = complete; state.completeStream = complete;
state.failStream = fail; state.failStream = fail;
source.onopen = () => {
clearNetworkErrorTimer();
};
source.onmessage = (event) => { source.onmessage = (event) => {
if (state.abortRequested || finished) { if (state.abortRequested || finished) {
complete(); complete();
return; return;
} }
clearNetworkErrorTimer();
if (event.data === undefined || event.data === null || event.data === '') { if (event.data === undefined || event.data === null || event.data === '') {
return; return;
} }
@@ -442,7 +461,18 @@ document.addEventListener('DOMContentLoaded', () => {
return; return;
} }
if (source.readyState === EventSource.CLOSED) {
fail(new Error('EventSource connection closed'));
return;
}
if (!networkErrorTimer) {
networkErrorTimer = setTimeout(() => {
if (!finished && !state.abortRequested) {
fail(new Error('EventSource connection error')); fail(new Error('EventSource connection error'));
}
}, 20000);
}
}); });
}); });
} catch (err) { } catch (err) {

View File

@@ -49,7 +49,11 @@ final readonly class StoreApiClient
'sw-access-key' => $this->salesChannelAccessKey, 'sw-access-key' => $this->salesChannelAccessKey,
], ],
'body' => $body, 'body' => $body,
// Keep Shopware calls bounded. During SSE responses the browser only
// receives data between blocking HTTP calls, so long Store API waits
// can look like a broken stream to proxies or the browser.
'timeout' => $this->timeoutSeconds, 'timeout' => $this->timeoutSeconds,
'max_duration' => max(1, $this->timeoutSeconds + 1),
]); ]);
$statusCode = $response->getStatusCode(); $statusCode = $response->getStatusCode();