Skip to main content

Mountain/ProcessManagement/NodeResolver/
ResolveNodeBinary.rs

1
2//! Resolve the Node binary used to spawn Cocoon and cache for the life of
3//! the process. If everything fails returns `node` so `Command::new` still
4//! tries a bare PATH lookup at spawn time, matching legacy behaviour while
5//! logging the chain of misses.
6
7use std::sync::OnceLock;
8
9use tauri::{AppHandle, Runtime};
10
11use crate::{
12	ProcessManagement::NodeResolver::{CheckMinMajor, QueryNodeVersion, ResolveUncached, ResolvedNode},
13	dev_log,
14};
15
16static RESOLVED:OnceLock<ResolvedNode::Struct> = OnceLock::new();
17
18pub fn Fn<R:Runtime>(ApplicationHandle:&AppHandle<R>) -> ResolvedNode::Struct {
19	if let Some(Cached) = RESOLVED.get() {
20		return Cached.clone();
21	}
22
23	let Resolved = ResolveUncached::Fn(ApplicationHandle);
24
25	let Version = QueryNodeVersion::Fn(&Resolved.Path);
26
27	match &Version {
28		Some(Reported) => {
29			dev_log!(
30				"cocoon",
31				"[NodeResolver] Using: {} (source={}, version={})",
32				Resolved.Path.display(),
33				Resolved.Source.AsLabel(),
34				Reported
35			);
36
37			CheckMinMajor::Fn(Reported);
38		},
39
40		None => {
41			dev_log!(
42				"cocoon",
43				"[NodeResolver] Using: {} (source={}, version=unknown)",
44				Resolved.Path.display(),
45				Resolved.Source.AsLabel()
46			);
47		},
48	}
49
50	// `OnceLock::set` is benign-racy: parallel callers resolve to the same
51	// value; the first store wins.
52	let _ = RESOLVED.set(Resolved.clone());
53
54	Resolved
55}