feat(oracle): auto-recover Oracle pool + surface status, stop silent import failures
After a power loss the app started before Oracle was ready; init_oracle() failed
once, the pool stayed None forever (no retry), and every sync silently failed
("Oracle pool not initialized") while still hammering the GoMag API each minute,
and order-detail 500'd.
- database.ensure_oracle_pool(force): thread-safe (re)create of the pool, called
at the start of every sync cycle → self-heals within one cycle once Oracle is
back (incl. after an Oracle service restart). init_oracle_client made idempotent
so re-init can't fall back to thin mode.
- database.oracle_status() exposed; main.py startup is non-fatal via ensure pool.
- run_sync ensures the pool before the GoMag download; on failure it records a
clear run status instead of crashing and skips the wasted API calls.
- /api/sync/health reports oracle_ready/last_error; dashboard health pill shows
"Oracle indisponibil" (top priority). Recovery via the existing Start Sync button.
- order_detail degrades gracefully (200 without CODMAT + notice) instead of 500.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -184,7 +184,14 @@ function renderHealthPill(h) {
|
||||
const recent = h.recent_phase_failures || {};
|
||||
const recentCount = Object.values(recent).reduce((a, b) => a + (b || 0), 0);
|
||||
|
||||
if (h.escalation_phase || h.last_sync_status === 'halted_escalation') {
|
||||
if (h.oracle_ready === false) {
|
||||
state = 'escalated';
|
||||
iconCls = 'bi-database-x';
|
||||
text = 'Oracle indisponibil';
|
||||
tooltip = `Oracle indisponibil — importurile sunt oprite.\n`
|
||||
+ `${h.oracle_last_error || ''}\n`
|
||||
+ `Se reincearca automat la urmatorul sync. Apasa Start Sync pentru a reincerca acum.`;
|
||||
} else if (h.escalation_phase || h.last_sync_status === 'halted_escalation') {
|
||||
state = 'escalated';
|
||||
iconCls = 'bi-x-octagon-fill';
|
||||
text = 'Blocat';
|
||||
|
||||
@@ -865,9 +865,13 @@ async function renderOrderDetailModal(orderNumber, opts) {
|
||||
// Render compact header info (partner + addresses)
|
||||
_renderHeaderInfo(order);
|
||||
|
||||
if (order.error_message) {
|
||||
document.getElementById('detailError').textContent = order.error_message;
|
||||
document.getElementById('detailError').style.display = '';
|
||||
const detailErrEl = document.getElementById('detailError');
|
||||
if (order.oracle_available === false) {
|
||||
detailErrEl.textContent = '⚠ Oracle indisponibil — CODMAT-urile nu pot fi incarcate momentan. Reincearca dupa restabilirea conexiunii.';
|
||||
detailErrEl.style.display = '';
|
||||
} else if (order.error_message) {
|
||||
detailErrEl.textContent = order.error_message;
|
||||
detailErrEl.style.display = '';
|
||||
}
|
||||
|
||||
// Configure footer action buttons BEFORE any early-return on items —
|
||||
|
||||
Reference in New Issue
Block a user