LibrePortal/scripts/source/loading/initilize_files.sh
librelad 77342c8047 feat(lazy-load): extend manifest to containers/ + skip container scan (Phase 5)
Containers used to be eager-loaded via `sourceScanFiles "containers"`
even under LP_LAZY=1 — sourcing all ~160 installer functions up front.
Phase 5 brings them into the autoload-stub mechanism.

generate_function_manifest.sh now scans BOTH scripts/ AND containers/
(maxdepth 3, matching sourceScanFiles' existing prune), with a per-entry
root selector so stub emission uses the right base directory:

  scripts/peer/peer_add.sh    →  source "${install_scripts_dir}peer/peer_add.sh"
  containers/linkding/linkding.sh →  source "${install_containers_dir}linkding/linkding.sh"

New manifest exports:
  LP_FN_MAP             funcname → relpath        (existing)
  LP_FN_ROOT            funcname → scripts|containers   NEW
  LP_EAGER_FILES        "<root>:<relpath>" entries     NEW format
  ~860 autoload stubs   (was ~700; +160 from containers)

Loader changes (initilize_files.sh):
  - Parses LP_EAGER_FILES entries as `root:path`, dispatches to the
    right install_*_dir. Pre-Phase-5 entries without a colon default to
    scripts (backwards-compatible).
  - sourceScanFiles "containers" is skipped when LP_LAZY=1 AND
    LP_FN_MAP is loaded (manifest-driven autoload covers it).
    Eager mode and lazy-with-missing-manifest both still run the scan.

Measurement target: ~70 ms saved on top of Phase 4. Verified separately
in the commit message of the next deploy.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-26 21:30:36 +01:00

148 lines
6.5 KiB
Bash
Executable File

#!/bin/bash
sourceInitilize()
{
local flag="$1"
# We will only show the header for the full app
if [[ $flag == "run" ]]; then
isHeader "Loading LibrePortal Startup Files"
isNotice "If you are experiencing loading issues..."
isNotice "Please run the following : 'libreportal reset'"
fi
# Directory containing the files to source recursively
local file_list_directory="${install_scripts_dir}source/files"
# Check if the directory exists
if [ -d "$file_list_directory" ]; then
# Use find to get a list of all files (excluding directories) in the directory and its subdirectories
local file_list=$(find "$file_list_directory" -type f -name "*.sh")
# Loop through each file in the file list
while IFS= read -r file; do
# Source the file
source "$file"
done <<< "$file_list"
else
echo "Directory $file_list_directory does not exist. Unable to start!"
fi
# For loading files needed for the full app or CLI
if [[ $flag == "run" ]]; then
source "${install_scripts_dir}source/files/app_files.sh"
files_to_source=("${files_libreportal_app[@]}")
elif [[ $flag == "cli" ]]; then
source "${install_scripts_dir}source/files/cli_files.sh"
files_to_source=("${files_libreportal_cli[@]}")
fi
# Trace setup — LP_LOAD_TRACE=1 logs `<ms>\t<file>` to LP_LOAD_TRACE_FILE
# for `libreportal debug load-trace`. Zero overhead when unset.
if [[ "$LP_LOAD_TRACE" == "1" ]]; then
: "${LP_LOAD_TRACE_FILE:=/tmp/libreportal-load-trace.$$.log}"
export LP_LOAD_TRACE_FILE
: > "$LP_LOAD_TRACE_FILE"
fi
# LP_LAZY=1: defer the bulk of file sourcing. Install autoload stubs from
# function_manifest.sh, source only the files with top-level side effects
# (LP_EAGER_FILES — set by the manifest), and skip the rest. Each stub
# sources its real file on first call; subsequent calls hit the real
# function directly (the source replaced the stub).
#
# Default (LP_LAZY unset or 0): the historical behaviour — source every
# file in files_to_source up front. Long-running processes (task
# processor, WebUI) want this so their first call to anything is hot.
if [[ "$LP_LAZY" == "1" ]]; then
local manifest="${install_scripts_dir}source/files/arrays/function_manifest.sh"
if [[ -f "$manifest" ]]; then
# Sourcing the manifest defines LP_FN_MAP, LP_EAGER_FILES, AND
# the autoload stubs (precompiled by the generator so we pay one
# parse cost instead of evaling ~700 snippets at startup).
if [[ "$LP_LOAD_TRACE" == "1" ]]; then
local _t0=$EPOCHREALTIME
source "$manifest"
local _t1=$EPOCHREALTIME
local _ms
_ms=$(awk -v a="$_t0" -v b="$_t1" 'BEGIN{printf "%.3f", (b-a)*1000}')
printf '%s\t%s\n' "$_ms" "source/files/arrays/function_manifest.sh (LAZY-manifest)" >> "$LP_LOAD_TRACE_FILE"
else
source "$manifest"
fi
# Eager-source the side-effect files. Entries are `<root>:<relpath>`
# where root selects the base dir ("scripts" → install_scripts_dir,
# "containers" → install_containers_dir). Pre-Phase-5 manifests
# without a `:` default to scripts/.
local _eager _root _path _base
for _eager in "${LP_EAGER_FILES[@]}"; do
if [[ "$_eager" == *:* ]]; then
_root="${_eager%%:*}"
_path="${_eager#*:}"
else
_root="scripts"; _path="$_eager"
fi
case "$_root" in
containers) _base="$install_containers_dir" ;;
*) _base="$install_scripts_dir" ;;
esac
[[ -f "${_base}${_path}" ]] || continue
if [[ "$LP_LOAD_TRACE" == "1" ]]; then
local _t0=$EPOCHREALTIME
source "${_base}${_path}"
local _t1=$EPOCHREALTIME
local _ms
_ms=$(awk -v a="$_t0" -v b="$_t1" 'BEGIN{printf "%.3f", (b-a)*1000}')
printf '%s\t%s\n' "$_ms" "${_root}/${_path} (LAZY-EAGER)" >> "$LP_LOAD_TRACE_FILE"
else
source "${_base}${_path}"
fi
done
else
# No manifest present — fall back to eager loading so we never
# leave the user with a broken install just because regen
# hasn't run. Silently — this is the safety net, not the path.
export LP_LAZY=0
fi
fi
# Eager path (default OR lazy-with-no-manifest fallback). Sources every
# file in files_to_source. Skipped entirely when LP_LAZY=1 succeeded.
if [[ "$LP_LAZY" != "1" ]]; then
for file_to_source in "${files_to_source[@]}"; do
if [ ! -f "${install_scripts_dir}${file_to_source}" ]; then
isNotice "Missing file: ${install_scripts_dir}${file_to_source}"
else
if [[ "$LP_LOAD_TRACE" == "1" ]]; then
local _t0=$EPOCHREALTIME
source "${install_scripts_dir}${file_to_source}"
local _t1=$EPOCHREALTIME
local _ms
_ms=$(awk -v a="$_t0" -v b="$_t1" 'BEGIN{printf "%.3f", (b-a)*1000}')
printf '%s\t%s\n' "$_ms" "$file_to_source" >> "$LP_LOAD_TRACE_FILE"
else
source "${install_scripts_dir}${file_to_source}"
fi
fi
done
fi
# Loading of all files. Three scans:
# libreportal_configs CFG_* vars from configs/* (~180 ms)
# app_configs CFG_<APP>_* vars from containers/* (~37 ms)
# containers Per-app installer functions (~70 ms)
#
# Under LP_LAZY=1 with a present manifest, the container scan is replaced
# by autoload stubs in function_manifest.sh — sourcing every container
# installer eagerly would defeat the lazy optimisation. The two config
# scans still run because bash can't lazy-load variables (Phase 6 will
# tackle this with a precompiled cache file).
sourceScanFiles "libreportal_configs";
sourceScanFiles "app_configs";
if [[ "$LP_LAZY" == "1" ]] && declare -p LP_FN_MAP >/dev/null 2>&1; then
: # containers covered by autoload stubs; skip the eager scan
else
sourceScanFiles "containers";
fi
}