fix: register NIF compiler, add Nix shell NIF build, make NIF optional at boot
- Register :towerops_nif compiler in mix.exs so mix compile/test builds the C NIF - Add 'make -C c_src' to nix devShell shellHook so NIF is pre-built - Extract init_mib_resolution/0 from Application.start/2 (reduces CC) - Wrap NIF calls in try/rescue ErlangError for graceful fallback - Wrap test_helper.exs NIF calls in try/rescue ErlangError - Add .nix-postgres-version to .gitignore
This commit is contained in:
parent
b7d8ea9668
commit
e6fba0c5a3
5 changed files with 72 additions and 56 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -5,6 +5,7 @@
|
|||
.nix-mix/
|
||||
.nix-hex/
|
||||
.nix-postgres/
|
||||
.nix-postgres-version
|
||||
.nix-redis/
|
||||
.nix-services-started
|
||||
|
||||
|
|
|
|||
|
|
@ -41,46 +41,8 @@ defmodule Towerops.Application do
|
|||
Towerops.Release.migrate()
|
||||
end
|
||||
|
||||
# Configure MIB directories for NIF resolution (before supervisor starts)
|
||||
Logger.info("Configuring MIB directories for NIF resolution...")
|
||||
mib_dir = Application.app_dir(:towerops, "priv/mibs")
|
||||
|
||||
# Build list of all MIB directories (including subdirectories for vendor MIBs)
|
||||
mib_dirs =
|
||||
if File.dir?(mib_dir) do
|
||||
# Get main directory plus all subdirectories
|
||||
subdirs =
|
||||
mib_dir
|
||||
|> File.ls!()
|
||||
|> Enum.map(&Path.join(mib_dir, &1))
|
||||
|> Enum.filter(&File.dir?/1)
|
||||
|
||||
[mib_dir | subdirs]
|
||||
else
|
||||
[mib_dir]
|
||||
end
|
||||
|
||||
# Set MIBDIRS environment variable for net-snmp (must be set BEFORE init)
|
||||
# Join with colon for Unix-style path list
|
||||
mibdirs_env = Enum.join(mib_dirs, ":")
|
||||
System.put_env("MIBDIRS", mibdirs_env)
|
||||
System.put_env("MIBS", "ALL")
|
||||
|
||||
Logger.info("MIB directories configured: #{length(mib_dirs)} directories")
|
||||
|
||||
# Add each directory to net-snmp's search path
|
||||
Enum.each(mib_dirs, fn dir ->
|
||||
:ok = ToweropsNative.load_mib_directory(dir)
|
||||
end)
|
||||
|
||||
# Initialize the MIB library (loads all MIBs into memory)
|
||||
case ToweropsNative.init_mib_library() do
|
||||
result when result in ["initialized", "already_initialized"] ->
|
||||
Logger.info("MIB library initialized: #{result}")
|
||||
|
||||
other ->
|
||||
Logger.warning("Unexpected MIB library init result: #{inspect(other)}")
|
||||
end
|
||||
# Initialize MIB resolution via C NIF
|
||||
init_mib_resolution()
|
||||
|
||||
# Load antenna pattern registry (priv/antennas/*.ant) into :persistent_term
|
||||
Antenna.load_registry()
|
||||
|
|
@ -152,6 +114,48 @@ defmodule Towerops.Application do
|
|||
result
|
||||
end
|
||||
|
||||
# Configure MIB resolution via C NIF. Handles missing NIF gracefully.
|
||||
defp init_mib_resolution do
|
||||
Logger.info("Configuring MIB directories for NIF resolution...")
|
||||
mib_dir = Application.app_dir(:towerops, "priv/mibs")
|
||||
|
||||
mib_dirs =
|
||||
if File.dir?(mib_dir) do
|
||||
subdirs =
|
||||
mib_dir
|
||||
|> File.ls!()
|
||||
|> Enum.map(&Path.join(mib_dir, &1))
|
||||
|> Enum.filter(&File.dir?/1)
|
||||
|
||||
[mib_dir | subdirs]
|
||||
else
|
||||
[mib_dir]
|
||||
end
|
||||
|
||||
mibdirs_env = Enum.join(mib_dirs, ":")
|
||||
System.put_env("MIBDIRS", mibdirs_env)
|
||||
System.put_env("MIBS", "ALL")
|
||||
|
||||
Logger.info("MIB directories configured: #{length(mib_dirs)} directories")
|
||||
|
||||
try do
|
||||
Enum.each(mib_dirs, fn dir ->
|
||||
:ok = ToweropsNative.load_mib_directory(dir)
|
||||
end)
|
||||
|
||||
case ToweropsNative.init_mib_library() do
|
||||
result when result in ["initialized", "already_initialized"] ->
|
||||
Logger.info("MIB library initialized: #{result}")
|
||||
|
||||
other ->
|
||||
Logger.warning("Unexpected MIB library init result: #{inspect(other)}")
|
||||
end
|
||||
rescue
|
||||
_e in ErlangError ->
|
||||
Logger.warning("ToweropsNative NIF not loaded — MIB resolution unavailable")
|
||||
end
|
||||
end
|
||||
|
||||
# Post-startup work runs only when the supervisor came up cleanly. The Task
|
||||
# supervisor call is wrapped in try/catch so a transient noproc (the named
|
||||
# supervisor may not be ready or may already be dying) cannot exit the boot
|
||||
|
|
|
|||
2
mix.exs
2
mix.exs
|
|
@ -10,7 +10,7 @@ defmodule Towerops.MixProject do
|
|||
start_permanent: Mix.env() == :prod,
|
||||
aliases: aliases(),
|
||||
deps: deps(),
|
||||
compilers: [:phoenix_live_view] ++ Mix.compilers(),
|
||||
compilers: [:towerops_nif, :phoenix_live_view] ++ Mix.compilers(),
|
||||
prune_code_paths: false,
|
||||
listeners: [Phoenix.CodeReloader],
|
||||
dialyzer: dialyzer(),
|
||||
|
|
|
|||
|
|
@ -326,6 +326,12 @@ mkShell {
|
|||
mix local.hex --force --if-missing > /dev/null 2>&1
|
||||
mix local.rebar --force --if-missing > /dev/null 2>&1
|
||||
|
||||
# Compile C NIF if not already built (uses Nix-provided gcc/make/net-snmp)
|
||||
if [ ! -f "priv/towerops_nif.so" ]; then
|
||||
echo "🔧 Building C NIF..."
|
||||
make -C c_src
|
||||
fi
|
||||
|
||||
# Auto-start services on first shell entry.
|
||||
# Run in a detached subshell to prevent nix develop from waiting
|
||||
# on daemonized PostgreSQL/Redis child processes.
|
||||
|
|
|
|||
|
|
@ -18,22 +18,27 @@ if File.dir?(mib_dir) do
|
|||
System.put_env("MIBDIRS", mibdirs_env)
|
||||
System.put_env("MIBS", "ALL")
|
||||
|
||||
# Add each directory to net-snmp's search path
|
||||
Enum.each(mib_dirs, fn dir ->
|
||||
case ToweropsNative.load_mib_directory(dir) do
|
||||
:ok -> :ok
|
||||
# Ignore errors in test environment
|
||||
{:error, _reason} -> :ok
|
||||
# Add each directory to net-snmp's search path (NIF may not be loaded)
|
||||
try do
|
||||
Enum.each(mib_dirs, fn dir ->
|
||||
case ToweropsNative.load_mib_directory(dir) do
|
||||
:ok -> :ok
|
||||
# Ignore errors in test environment
|
||||
{:error, _reason} -> :ok
|
||||
end
|
||||
end)
|
||||
|
||||
# Explicitly initialize the MIB library with correct environment variables
|
||||
case ToweropsNative.init_mib_library() do
|
||||
result when result in ["initialized", "already_initialized"] ->
|
||||
IO.puts("Test MIB library initialized: #{result}")
|
||||
|
||||
other ->
|
||||
IO.puts("Warning: Unexpected MIB library init result: #{inspect(other)}")
|
||||
end
|
||||
end)
|
||||
|
||||
# Explicitly initialize the MIB library with correct environment variables
|
||||
case ToweropsNative.init_mib_library() do
|
||||
result when result in ["initialized", "already_initialized"] ->
|
||||
IO.puts("Test MIB library initialized: #{result}")
|
||||
|
||||
other ->
|
||||
IO.puts("Warning: Unexpected MIB library init result: #{inspect(other)}")
|
||||
rescue
|
||||
_e in ErlangError ->
|
||||
IO.puts("ToweropsNative NIF not available — MIB resolution disabled in tests")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue