clan_cli vars generate: prefetch all validationHashes for faster eval

This commit is contained in:
lassulus
2025-04-06 16:14:57 -07:00
committed by Jörg Thalheim
parent ab90987d17
commit da92c19367
2 changed files with 66 additions and 3 deletions

View File

@@ -468,6 +468,23 @@ class Flake:
selectors: list[str], selectors: list[str],
nix_options: list[str] | None = None, nix_options: list[str] | None = None,
) -> None: ) -> None:
"""
Retrieves specific attributes from a Nix flake using the provided selectors.
This function interacts with the Nix build system to fetch and process
attributes from a flake. It uses the provided selectors to determine which
attributes to retrieve and optionally accepts additional Nix options for
customization. The results are cached for future use.
Used mostly as a lowlevel function for `precache` and `select` methods.
Args:
selectors (list[str]): A list of attribute selectors to fetch from the flake.
nix_options (list[str] | None): Optional additional options to pass to the Nix build command.
Raises:
ClanError: If the number of outputs does not match the number of selectors.
AssertionError: If the cache or flake cache path is not properly initialized.
"""
if self._cache is None: if self._cache is None:
self.prefetch() self.prefetch()
assert self._cache is not None assert self._cache is not None
@@ -481,7 +498,7 @@ class Flake:
flake = builtins.getFlake("path:{self.store_path}?narHash={self.hash}"); flake = builtins.getFlake("path:{self.store_path}?narHash={self.hash}");
in in
flake.inputs.nixpkgs.legacyPackages.{config["system"]}.writeText "clan-flake-select" ( flake.inputs.nixpkgs.legacyPackages.{config["system"]}.writeText "clan-flake-select" (
builtins.toJSON [ ({" ".join([f"flake.clanInternals.clanLib.select ''{attr}'' flake" for attr in selectors])}) ] builtins.toJSON [ {" ".join([f"(flake.clanInternals.clanLib.select ''{attr}'' flake)" for attr in selectors])} ]
) )
""" """
if tmp_store := nix_test_store(): if tmp_store := nix_test_store():
@@ -506,11 +523,46 @@ class Flake:
self._cache.insert(outputs[i], selector) self._cache.insert(outputs[i], selector)
self._cache.save_to_file(self.flake_cache_path) self._cache.save_to_file(self.flake_cache_path)
def precache(
self,
selectors: list[str],
nix_options: list[str] | None = None,
) -> None:
"""
Ensures that the specified selectors are cached locally.
This function checks if the given selectors are already cached. If not, it
fetches them using the Nix build system and stores them in the local cache.
It ensures that the cache is initialized before performing these operations.
Args:
selectors (list[str]): A list of attribute selectors to check and cache.
nix_options (list[str] | None): Optional additional options to pass to the Nix build command.
"""
if self._cache is None:
self.prefetch()
assert self._cache is not None
assert self.flake_cache_path is not None
not_fetched_selectors = []
for selector in selectors:
if not self._cache.is_cached(selector):
not_fetched_selectors.append(selector)
if not_fetched_selectors:
self.get_from_nix(not_fetched_selectors, nix_options)
def select( def select(
self, self,
selector: str, selector: str,
nix_options: list[str] | None = None, nix_options: list[str] | None = None,
) -> Any: ) -> Any:
"""
Selects a value from the cache based on the provided selector string.
Fetches it via nix_build if it is not already cached.
Args:
selector (str): The attribute selector string to fetch the value for.
nix_options (list[str] | None): Optional additional options to pass to the Nix build command.
"""
if self._cache is None: if self._cache is None:
self.prefetch() self.prefetch()
assert self._cache is not None assert self._cache is not None

View File

@@ -17,7 +17,7 @@ from clan_cli.completions import (
from clan_cli.errors import ClanError from clan_cli.errors import ClanError
from clan_cli.git import commit_files from clan_cli.git import commit_files
from clan_cli.machines.inventory import get_all_machines, get_selected_machines from clan_cli.machines.inventory import get_all_machines, get_selected_machines
from clan_cli.nix import nix_shell, nix_test_store from clan_cli.nix import nix_config, nix_shell, nix_test_store
from clan_cli.vars._types import StoreBase from clan_cli.vars._types import StoreBase
from .check import check_vars from .check import check_vars
@@ -489,7 +489,6 @@ def generate_vars(
was_regenerated |= generate_vars_for_machine( was_regenerated |= generate_vars_for_machine(
machine, generator_name, regenerate, no_sandbox=no_sandbox machine, generator_name, regenerate, no_sandbox=no_sandbox
) )
machine.flush_caches()
except Exception as exc: except Exception as exc:
errors += [(machine, exc)] errors += [(machine, exc)]
if len(errors) == 1: if len(errors) == 1:
@@ -515,6 +514,18 @@ def generate_command(args: argparse.Namespace) -> None:
machines = get_all_machines(args.flake, args.option) machines = get_all_machines(args.flake, args.option)
else: else:
machines = get_selected_machines(args.flake, args.option, args.machines) machines = get_selected_machines(args.flake, args.option, args.machines)
# prefetch all vars
config = nix_config()
system = config["system"]
machine_names = [machine.name for machine in machines]
# test
args.flake.precache(
[
f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.clan.core.vars.generators.*.validationHash",
f"clanInternals.machines.{system}.{{{','.join(machine_names)}}}.config.system.clan.deployment.file",
]
)
generate_vars(machines, args.generator, args.regenerate, no_sandbox=args.no_sandbox) generate_vars(machines, args.generator, args.regenerate, no_sandbox=args.no_sandbox)