Skip to main content

Mountain/ProcessManagement/NodeResolver/
ResolveNodeBinary.rs

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