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
28	match &Version {
29		Some(Reported) => {
30			dev_log!(
31				"cocoon",
32				"[NodeResolver] Using: {} (source={}, version={})",
33				Resolved.Path.display(),
34				Resolved.Source.AsLabel(),
35				Reported
36			);
37
38			CheckMinMajor::Fn(Reported);
39		},
40
41		None => {
42			dev_log!(
43				"cocoon",
44				"[NodeResolver] Using: {} (source={}, version=unknown)",
45				Resolved.Path.display(),
46				Resolved.Source.AsLabel()
47			);
48		},
49	}
50
51	// `OnceLock::set` is benign-racy: parallel callers resolve to the same
52	// value; the first store wins.
53	let _ = RESOLVED.set(Resolved.clone());
54
55	Resolved
56}