mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-17 11:45:05 +02:00
Fix backend issues in desktop app (#4995)
# Description of Changes Fixes two distinct but related issues in the backend of the desktop app: - Correctly shows tools as unavaialable when the backend doesn't have the dependencies or has disabled them etc. (same as web version - this primarily didn't work on desktop because the app spawns before the backend is running) - Fixes infinite re-rendering issues caused by the app polling whether the backend is healthy or not
This commit is contained in:
@@ -10,7 +10,6 @@ class BackendHealthMonitor {
|
||||
private readonly intervalMs: number;
|
||||
private state: BackendHealthState = {
|
||||
status: tauriBackendService.getBackendStatus(),
|
||||
isChecking: false,
|
||||
error: null,
|
||||
isHealthy: tauriBackendService.getBackendStatus() === 'healthy',
|
||||
};
|
||||
@@ -26,20 +25,30 @@ class BackendHealthMonitor {
|
||||
message: status === 'healthy'
|
||||
? i18n.t('backendHealth.online', 'Backend Online')
|
||||
: this.state.message ?? i18n.t('backendHealth.offline', 'Backend Offline'),
|
||||
isChecking: status === 'healthy' ? false : this.state.isChecking,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private updateState(partial: Partial<BackendHealthState>) {
|
||||
const nextStatus = partial.status ?? this.state.status;
|
||||
this.state = {
|
||||
const nextState = {
|
||||
...this.state,
|
||||
...partial,
|
||||
status: nextStatus,
|
||||
isHealthy: nextStatus === 'healthy',
|
||||
};
|
||||
this.listeners.forEach((listener) => listener(this.state));
|
||||
|
||||
// Only notify listeners if meaningful state changed
|
||||
const meaningfulChange =
|
||||
this.state.status !== nextState.status ||
|
||||
this.state.error !== nextState.error ||
|
||||
this.state.message !== nextState.message;
|
||||
|
||||
this.state = nextState;
|
||||
|
||||
if (meaningfulChange) {
|
||||
this.listeners.forEach((listener) => listener(this.state));
|
||||
}
|
||||
}
|
||||
|
||||
private ensurePolling() {
|
||||
@@ -60,29 +69,19 @@ class BackendHealthMonitor {
|
||||
}
|
||||
|
||||
private async pollOnce(): Promise<boolean> {
|
||||
this.updateState({
|
||||
isChecking: true,
|
||||
lastChecked: Date.now(),
|
||||
error: this.state.error ?? 'Backend offline',
|
||||
});
|
||||
|
||||
try {
|
||||
const healthy = await tauriBackendService.checkBackendHealth();
|
||||
if (healthy) {
|
||||
this.updateState({
|
||||
status: 'healthy',
|
||||
isChecking: false,
|
||||
message: i18n.t('backendHealth.online', 'Backend Online'),
|
||||
error: null,
|
||||
lastChecked: Date.now(),
|
||||
});
|
||||
} else {
|
||||
this.updateState({
|
||||
status: 'unhealthy',
|
||||
isChecking: false,
|
||||
message: i18n.t('backendHealth.offline', 'Backend Offline'),
|
||||
error: i18n.t('backendHealth.offline', 'Backend Offline'),
|
||||
lastChecked: Date.now(),
|
||||
});
|
||||
}
|
||||
return healthy;
|
||||
@@ -90,10 +89,8 @@ class BackendHealthMonitor {
|
||||
console.error('[BackendHealthMonitor] Health check failed:', error);
|
||||
this.updateState({
|
||||
status: 'unhealthy',
|
||||
isChecking: false,
|
||||
message: 'Backend is unavailable',
|
||||
error: 'Backend offline',
|
||||
lastChecked: Date.now(),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,8 @@ export class TauriBackendService {
|
||||
async checkBackendHealth(): Promise<boolean> {
|
||||
const mode = await connectionModeService.getCurrentMode();
|
||||
|
||||
// For self-hosted mode, check the configured remote server
|
||||
// Determine base URL based on mode
|
||||
let baseUrl: string;
|
||||
if (mode === 'selfhosted') {
|
||||
const serverConfig = await connectionModeService.getServerConfig();
|
||||
if (!serverConfig) {
|
||||
@@ -141,47 +142,37 @@ export class TauriBackendService {
|
||||
this.setStatus('unhealthy');
|
||||
return false;
|
||||
}
|
||||
baseUrl = serverConfig.url.replace(/\/$/, '');
|
||||
} else {
|
||||
// SaaS mode - check bundled local backend
|
||||
if (!this.backendStarted) {
|
||||
this.setStatus('stopped');
|
||||
return false;
|
||||
}
|
||||
if (!this.backendPort) {
|
||||
return false;
|
||||
}
|
||||
baseUrl = `http://localhost:${this.backendPort}`;
|
||||
}
|
||||
|
||||
try {
|
||||
const baseUrl = serverConfig.url.replace(/\/$/, '');
|
||||
const healthUrl = `${baseUrl}/api/v1/info/status`;
|
||||
const response = await fetch(healthUrl, {
|
||||
method: 'GET',
|
||||
connectTimeout: 5000,
|
||||
});
|
||||
// Check if backend is ready (dependencies checked)
|
||||
try {
|
||||
const configUrl = `${baseUrl}/api/v1/config/app-config`;
|
||||
const response = await fetch(configUrl, {
|
||||
method: 'GET',
|
||||
connectTimeout: 5000,
|
||||
});
|
||||
|
||||
const isHealthy = response.ok;
|
||||
this.setStatus(isHealthy ? 'healthy' : 'unhealthy');
|
||||
return isHealthy;
|
||||
} catch (error) {
|
||||
const errorStr = String(error);
|
||||
if (!errorStr.includes('connection refused') && !errorStr.includes('No connection could be made')) {
|
||||
console.error('[TauriBackendService] Self-hosted server health check failed:', error);
|
||||
}
|
||||
if (!response.ok) {
|
||||
this.setStatus('unhealthy');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// For SaaS mode, check the bundled local backend via Rust
|
||||
if (!this.backendStarted) {
|
||||
this.setStatus('stopped');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.backendPort) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const isHealthy = await invoke<boolean>('check_backend_health', { port: this.backendPort });
|
||||
this.setStatus(isHealthy ? 'healthy' : 'unhealthy');
|
||||
return isHealthy;
|
||||
} catch (error) {
|
||||
const errorStr = String(error);
|
||||
if (!errorStr.includes('connection refused') && !errorStr.includes('No connection could be made')) {
|
||||
console.error('[TauriBackendService] Bundled backend health check failed:', error);
|
||||
}
|
||||
const data = await response.json();
|
||||
const dependenciesReady = data.dependenciesReady === true;
|
||||
this.setStatus(dependenciesReady ? 'healthy' : 'starting');
|
||||
return dependenciesReady;
|
||||
} catch {
|
||||
this.setStatus('unhealthy');
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user