Compare commits
1 Commits
v0.1.71-wi
...
v0.1.72-wi
| Author | SHA1 | Date | |
|---|---|---|---|
| 3228e6cdd7 |
@@ -1,23 +1,28 @@
|
||||
use bollard::Docker;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::Mutex;
|
||||
|
||||
static DOCKER: OnceLock<Result<Docker, String>> = OnceLock::new();
|
||||
static DOCKER: Mutex<Option<Docker>> = Mutex::new(None);
|
||||
|
||||
pub fn get_docker() -> Result<&'static Docker, String> {
|
||||
let result = DOCKER.get_or_init(|| {
|
||||
Docker::connect_with_local_defaults()
|
||||
.map_err(|e| format!("Failed to connect to Docker daemon: {}", e))
|
||||
});
|
||||
match result {
|
||||
Ok(docker) => Ok(docker),
|
||||
Err(e) => Err(e.clone()),
|
||||
pub fn get_docker() -> Result<Docker, String> {
|
||||
let mut guard = DOCKER.lock().map_err(|e| format!("Lock poisoned: {}", e))?;
|
||||
if let Some(docker) = guard.as_ref() {
|
||||
return Ok(docker.clone());
|
||||
}
|
||||
let docker = Docker::connect_with_local_defaults()
|
||||
.map_err(|e| format!("Failed to connect to Docker daemon: {}", e))?;
|
||||
guard.replace(docker.clone());
|
||||
Ok(docker)
|
||||
}
|
||||
|
||||
pub async fn check_docker_available() -> Result<bool, String> {
|
||||
let docker = get_docker()?;
|
||||
match docker.ping().await {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => Err(format!("Docker daemon not responding: {}", e)),
|
||||
Err(_) => {
|
||||
// Connection object exists but daemon not responding — clear cache
|
||||
let mut guard = DOCKER.lock().map_err(|e| format!("Lock poisoned: {}", e))?;
|
||||
*guard = None;
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useUpdates } from "./hooks/useUpdates";
|
||||
import { useAppState } from "./store/appState";
|
||||
|
||||
export default function App() {
|
||||
const { checkDocker, checkImage } = useDocker();
|
||||
const { checkDocker, checkImage, startDockerPolling } = useDocker();
|
||||
const { loadSettings } = useSettings();
|
||||
const { refresh } = useProjects();
|
||||
const { loadVersion, checkForUpdates, startPeriodicCheck } = useUpdates();
|
||||
@@ -22,8 +22,13 @@ export default function App() {
|
||||
// Initialize on mount
|
||||
useEffect(() => {
|
||||
loadSettings();
|
||||
let stopPolling: (() => void) | undefined;
|
||||
checkDocker().then((available) => {
|
||||
if (available) checkImage();
|
||||
if (available) {
|
||||
checkImage();
|
||||
} else {
|
||||
stopPolling = startDockerPolling();
|
||||
}
|
||||
});
|
||||
refresh();
|
||||
|
||||
@@ -34,6 +39,7 @@ export default function App() {
|
||||
return () => {
|
||||
clearTimeout(updateTimer);
|
||||
cleanup?.();
|
||||
stopPolling?.();
|
||||
};
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { useCallback, useRef } from "react";
|
||||
import { useShallow } from "zustand/react/shallow";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { useAppState } from "../store/appState";
|
||||
@@ -59,6 +59,39 @@ export function useDocker() {
|
||||
[setImageExists],
|
||||
);
|
||||
|
||||
const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
const startDockerPolling = useCallback(() => {
|
||||
// Don't start if already polling
|
||||
if (pollingRef.current) return () => {};
|
||||
|
||||
const interval = setInterval(async () => {
|
||||
try {
|
||||
const available = await commands.checkDocker();
|
||||
if (available) {
|
||||
clearInterval(interval);
|
||||
pollingRef.current = null;
|
||||
setDockerAvailable(true);
|
||||
// Also check image once Docker is available
|
||||
try {
|
||||
const exists = await commands.checkImageExists();
|
||||
setImageExists(exists);
|
||||
} catch {
|
||||
setImageExists(false);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Still not available, keep polling
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
pollingRef.current = interval;
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
pollingRef.current = null;
|
||||
};
|
||||
}, [setDockerAvailable, setImageExists]);
|
||||
|
||||
const pullImage = useCallback(
|
||||
async (imageName: string, onProgress?: (msg: string) => void) => {
|
||||
const unlisten = onProgress
|
||||
@@ -84,5 +117,6 @@ export function useDocker() {
|
||||
checkImage,
|
||||
buildImage,
|
||||
pullImage,
|
||||
startDockerPolling,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user