### Development Setup Commands Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Commands to set up the development environment, including cloning the repository, installing tools, and fetching dependencies. ```shell git clone https://github.com/beardedeagle/mnesiac.git git checkout -b MyFeature asdf install mix local.hex --force mix local.rebar --force mix deps.get --force mix deps.compile --force mix compile --force ``` -------------------------------- ### Start Mnesia Standalone with Mnesiac.start/0 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Starts Mnesia as a standalone node, creating schemas and tables from scratch. ```elixir # Start Mnesia standalone (typically called via init_mnesia/1) :ok = Mnesiac.start() # This performs: # 1. Ensures Mnesia data directory exists # 2. Starts Mnesia server # 3. Copies schema to local node # 4. Initializes all configured store tables # 5. Waits for tables to be loaded ``` -------------------------------- ### Mnesiac.start/0 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Starts Mnesia as a standalone node, creating schemas and tables from scratch. ```APIDOC ## Mnesiac.start/0 ### Description Starts Mnesia as a standalone node, creating schemas and tables from scratch. This is called internally when no cluster nodes are available. ### Response - **:ok** (atom) - Success response. ``` -------------------------------- ### Initialize Mnesia with Mnesiac.init_mnesia/1 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Initializes Mnesia by attempting to join a cluster node from the provided list or starting as a standalone node. ```elixir # Initialize Mnesia with a list of potential cluster nodes nodes = [:"app@node1.example.com", :"app@node2.example.com"] :ok = Mnesiac.init_mnesia(nodes) # The function will: # 1. Filter nodes to only those currently connected via Node.list() # 2. If connected nodes found: join cluster via first available node # 3. If no connected nodes: start Mnesia standalone # Returns :ok on success, {:error, reason} on failure ``` -------------------------------- ### Mnesiac.init_mnesia/1 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Initializes Mnesia with strict host checking, joining a cluster if nodes are available or starting standalone. ```APIDOC ## Mnesiac.init_mnesia/1 ### Description Initializes Mnesia with strict host checking. If cluster nodes are found in the provided list, it joins the first available node; otherwise, it starts Mnesia as a standalone node. ### Parameters - **nodes** (list) - Required - A list of potential cluster nodes (atoms). ### Response - **:ok** (atom) - Success response. - **{:error, reason}** (tuple) - Error response on failure. ``` -------------------------------- ### Initialize Mnesia on New Node Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Run `Mnesiac.init_mnesia/1` on a new node joining the cluster to initialize and copy store contents from existing nodes. ```elixir Mnesiac.init_mnesia/1 ``` -------------------------------- ### Supervise Mnesiac Initialization Source: https://context7.com/beardedeagle/mnesiac/llms.txt Integrate Mnesiac.Supervisor into your application supervision tree, either using libcluster or by specifying nodes manually. ```elixir # In your application.ex defmodule MyApp.Application do use Application def start(_type, _args) do # With libcluster topology = Application.get_env(:libcluster, :topologies) hosts = topology[:myapp][:config][:hosts] children = [ {Cluster.Supervisor, [topology, [name: MyApp.ClusterSupervisor]]}, {Mnesiac.Supervisor, [hosts, [name: MyApp.MnesiacSupervisor]]}, # ... other children ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) end end # Without libcluster - specify nodes directly children = [ {Mnesiac.Supervisor, [ [:"node1@192.168.1.10", :"node2@192.168.1.11"], [name: MyApp.MnesiacSupervisor] ]} ] ``` -------------------------------- ### Implement Mnesiac.Store behavior Source: https://context7.com/beardedeagle/mnesiac/llms.txt Defines how Mnesia tables are created and managed by implementing the Store behavior and configuring store_options/0. ```elixir defmodule MyApp.UserStore do @moduledoc "Mnesia store for user data" use Mnesiac.Store import Record, only: [defrecord: 3] # Define the record structure defrecord(:user, __MODULE__, id: nil, email: nil, name: nil, created_at: nil ) @type user :: record(:user, id: String.t(), email: String.t(), name: String.t(), created_at: DateTime.t() ) @impl true def store_options do [ record_name: :user, attributes: user() |> user() |> Keyword.keys(), index: [:email], # Secondary index on email disc_copies: [node()] # Persist to disk on this node ] end end # Register in config.exs config :mnesiac, stores: [MyApp.UserStore] ``` -------------------------------- ### Configure Mnesiac Stores in config.exs Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Configure Mnesia stores, schema type, and table load timeout in your `config.exs` file. ```elixir config :mnesiac, stores: [MyApp.ExampleStore, ...], schema_type: :disc_copies, # defaults to :ram_copies table_load_timeout: 600_000 # milliseconds, default is 600_000 ``` -------------------------------- ### Run Test Coverage Report Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Executes tests and generates an HTML coverage report. Includes tracing and identifies the slowest tests. ```shell mix coveralls.html --trace --slowest 10 --no-start ``` -------------------------------- ### Manage tables with StoreManager Source: https://context7.com/beardedeagle/mnesiac/llms.txt Handles low-level table operations including initialization, copying, and schema management. ```elixir # Initialize tables (auto-detects cluster vs standalone) :ok = Mnesiac.StoreManager.init_tables() # Create tables on standalone node :ok = Mnesiac.StoreManager.create_tables() # Copy tables from cluster node :ok = Mnesiac.StoreManager.copy_tables(:"app@192.168.1.10") # Ensure all tables are loaded (with timeout) :ok = Mnesiac.StoreManager.ensure_tables_loaded() # Copy schema to node with configured type (:ram_copies or :disc_copies) :ok = Mnesiac.StoreManager.copy_schema(node()) # Delete local schema :ok = Mnesiac.StoreManager.delete_schema() # Delete schema copy from specific node :ok = Mnesiac.StoreManager.del_schema_copy(:"app@old-node.example.com") # Get table cookies (for detecting conflicts) {:ok, cookies} = Mnesiac.StoreManager.get_table_cookies() # => {:ok, %{MyApp.UserStore => {1234, 5678}, ...}} {:ok, remote_cookies} = Mnesiac.StoreManager.get_table_cookies(:"app@node2") ``` -------------------------------- ### Mnesiac Supervisor with libcluster Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Integrate Mnesiac.Supervisor into your supervision tree when using libcluster for automatic node discovery. ```elixir ... topology = Application.get_env(:libcluster, :topologies) hosts = topology[:myapp][:config][:hosts] children = [ {Cluster.Supervisor, [topology, [name: MyApp.ClusterSupervisor]]}, {Mnesiac.Supervisor, [hosts, [name: MyApp.MnesiacSupervisor]]}, ... ] ... ``` -------------------------------- ### Customize Store callbacks Source: https://context7.com/beardedeagle/mnesiac/llms.txt Overrides default callbacks like init_store/0, copy_store/0, and resolve_conflict/1 to customize table behavior. ```elixir defmodule MyApp.SessionStore do use Mnesiac.Store require Logger import Record, only: [defrecord: 3] defrecord(:session, __MODULE__, id: nil, user_id: nil, token: nil, expires_at: nil ) @impl true def store_options do [ record_name: :session, attributes: session() |> session() |> Keyword.keys(), index: [:user_id, :token], ram_copies: [node()] # RAM only for sessions ] end # Custom initialization with default data @impl true def init_store do :mnesia.create_table(:session, store_options()) Logger.info("[SessionStore] Table created on #{node()}") end # Custom copy logic @impl true def copy_store do :mnesia.add_table_copy(__MODULE__, node(), :ram_copies) Logger.info("[SessionStore] Table copied to #{node()}") end # Custom conflict resolution - prefer remote data @impl true def resolve_conflict(cluster_node) do Logger.warning("[SessionStore] Conflict detected with #{cluster_node}") # Delete local copy and copy from remote :mnesia.del_table_copy(__MODULE__, node()) :mnesia.add_table_copy(__MODULE__, node(), :ram_copies) :ok end end ``` -------------------------------- ### Configure Mnesiac Dependencies and Settings Source: https://context7.com/beardedeagle/mnesiac/llms.txt Add Mnesiac to your mix.exs dependencies and define store configurations in your config.exs file. ```elixir # In mix.exs def deps do [ {:mnesiac, "~> 0.3"}, {:libcluster, "~> 3.3"} # Optional, for automatic node discovery ] end # In config/config.exs config :mnesiac, stores: [MyApp.UserStore, MyApp.SessionStore], schema_type: :disc_copies, # :ram_copies (default) or :disc_copies table_load_timeout: 600_000 # 10 minutes (default) ``` -------------------------------- ### Clean Mnesia Database Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Run this command before testing to ensure a clean Mnesia database state. ```shell mix purge.db ``` -------------------------------- ### Mnesiac.Store Behavior Source: https://context7.com/beardedeagle/mnesiac/llms.txt Defines how Mnesia tables are created and managed using the Store behavior. ```APIDOC ## Mnesiac.Store ### Description The Store behavior allows developers to define Mnesia table configurations. Implement `use Mnesiac.Store` and define `store_options/0` to configure table attributes, indices, and storage types. ### Callbacks - **store_options/0** - Returns a keyword list of Mnesia table options. - **init_store/0** - Optional callback for custom table initialization. - **copy_store/0** - Optional callback for custom table copy logic. - **resolve_conflict/1** - Optional callback for handling table conflicts. ``` -------------------------------- ### Mnesiac.StoreManager Source: https://context7.com/beardedeagle/mnesiac/llms.txt Handles low-level table operations including initialization, copying, and schema management. ```APIDOC ## Mnesiac.StoreManager ### Description Provides functions for managing the Mnesia schema and table lifecycle across the cluster. ### Operations - **init_tables/0** - Initializes tables, auto-detecting cluster vs standalone mode. - **create_tables/0** - Creates tables on a standalone node. - **copy_tables/1** - Copies tables from a specified cluster node. - **ensure_tables_loaded/0** - Ensures all tables are loaded. - **copy_schema/1** - Copies schema to a node. - **delete_schema/0** - Deletes the local schema. - **del_schema_copy/1** - Deletes a schema copy from a specific node. - **get_table_cookies/0-1** - Retrieves table cookies for conflict detection. ``` -------------------------------- ### Connect to a Cluster Node with Mnesiac.connect/1 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Adds a specified node as an extra Mnesia database node. ```elixir # Connect to a cluster node cluster_node = :"app@192.168.1.10" case Mnesiac.connect(cluster_node) do :ok -> IO.puts("Connected to #{cluster_node}") {:error, {:failed_to_connect_node, node}} -> IO.puts("Failed to connect to #{node}") {:error, reason} -> IO.puts("Connection error: #{inspect(reason)}") end ``` -------------------------------- ### Join a Cluster with Mnesiac.join_cluster/1 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Joins an existing Mnesia cluster by connecting to a specified node, resetting the local schema, and copying tables. ```elixir # Join an existing Mnesia cluster cluster_node = :"app@192.168.1.10" :ok = Mnesiac.join_cluster(cluster_node) # This performs: # 1. Ensures Mnesia data directory exists # 2. Stops Mnesia if running # 3. Deletes local schema (clean slate) # 4. Starts Mnesia server # 5. Connects to cluster node # 6. Copies schema and tables from cluster # 7. Waits for tables to be loaded ``` -------------------------------- ### Minimal Mnesiac Store Implementation Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Defines a minimal Mnesiac store with record structure, types, and essential store options including record name, attributes, and indexes. ```elixir defmodule MyApp.ExampleStore do @moduledoc """ Provides the structure of ExampleStore records for a minimal example of Mnesiac. """ use Mnesiac.Store import Record, only: [defrecord: 3] @doc """ Record definition for ExampleStore example record. """ defrecord( :example, __MODULE__, id: nil, topic_id: nil, event: nil ) @typedoc """ ExampleStore example record field type definitions. """ @type example :: record( :example, id: String.t(), topic_id: String.t(), event: String.t() ) @impl true def store_options, do: [ record_name: :example, attributes: example() |> example() |> Keyword.keys(), index: [:topic_id], ram_copies: [node()] ] end ``` -------------------------------- ### Mnesiac.connect/1 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Connects to a cluster node by adding it as an extra Mnesia database node. ```APIDOC ## Mnesiac.connect/1 ### Description Connects to a cluster node by adding it as an extra Mnesia database node. ### Parameters - **cluster_node** (atom) - Required - The node to connect to. ### Response - **:ok** (atom) - Success response. - **{:error, reason}** (tuple) - Error response on failure. ``` -------------------------------- ### Mnesiac.join_cluster/1 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Joins an existing Mnesia cluster by connecting to a specified node, deleting local schema, and copying tables. ```APIDOC ## Mnesiac.join_cluster/1 ### Description Joins an existing Mnesia cluster by connecting to a specified node, deleting local schema, and copying tables from the cluster. ### Parameters - **cluster_node** (atom) - Required - The node to connect to. ### Response - **:ok** (atom) - Success response. ``` -------------------------------- ### Mnesiac Supervisor without libcluster Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Integrate Mnesiac.Supervisor into your supervision tree when manually specifying cluster nodes. ```elixir ... children = [ { Mnesiac.Supervisor, [ [:"test01@127.0.0.1", :"test02@127.0.0.1"], [name: MyApp.MnesiacSupervisor] ] }, ... ] ... ``` -------------------------------- ### Add Mnesiac to mix.exs Dependencies Source: https://github.com/beardedeagle/mnesiac/blob/master/README.md Add Mnesiac to your project's dependencies in the `mix.exs` file. ```elixir def deps do [ {:mnesiac, "~> 0.3"} ] end ``` -------------------------------- ### Write a user record in Mnesia Source: https://context7.com/beardedeagle/mnesiac/llms.txt Use this function to write a new user record to the Mnesia table. It includes a timestamp for creation. ```elixir defmodule MyApp.Users do require MyApp.UserStore # Write a user record def create_user(id, email, name) do record = MyApp.UserStore.user( id: id, email: email, name: name, created_at: DateTime.utc_now() ) :mnesia.transaction(fn -> :mnesia.write(record) end) end # Read user by ID def get_user(id) do :mnesia.transaction(fn -> case :mnesia.read({MyApp.UserStore, id}) do [record] -> {:ok, record} [] -> {:error, :not_found} end end) end # Query users by email (using index) def find_by_email(email) do :mnesia.transaction(fn -> :mnesia.index_read(MyApp.UserStore, email, :email) end) end # Delete user def delete_user(id) do :mnesia.transaction(fn -> :mnesia.delete({MyApp.UserStore, id}) end) end # List all users def list_users do :mnesia.transaction(fn -> :mnesia.foldl(fn record, acc -> [record | acc] end, [], MyApp.UserStore) end) end end ``` -------------------------------- ### Verify active database node Source: https://context7.com/beardedeagle/mnesiac/llms.txt Checks if a specific node is currently running as a Mnesia database node. ```elixir # Check if a specific node is running node = :"app@192.168.1.10" if Mnesiac.running_db_node?(node) do IO.puts("Node #{node} is active") else IO.puts("Node #{node} is not running") end ``` -------------------------------- ### Retrieve running Mnesia nodes Source: https://context7.com/beardedeagle/mnesiac/llms.txt Returns a list of all currently running Mnesia database nodes in the cluster. Useful for load balancing or failover logic. ```elixir # Get all running Mnesia nodes running = Mnesiac.running_nodes() # => [:"app@node1.example.com", :"app@node2.example.com"] # Use for load balancing or failover logic case Mnesiac.running_nodes() do [] -> {:error, :no_mnesia_nodes} [node | _] -> {:ok, node} end ``` -------------------------------- ### Check Cluster Status with Mnesiac.cluster_status/0 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Retrieves the current status of the Mnesia cluster, identifying running and stopped nodes. ```elixir # Check cluster status status = Mnesiac.cluster_status() # => [{:running_nodes, [:"app@node1", :"app@node2"]}] # With stopped nodes: # => [{:running_nodes, [:"app@node1"]}, {:stopped_nodes, [:"app@node2"]}] # Use in monitoring or health checks case Mnesiac.cluster_status() do [{:running_nodes, nodes}] when length(nodes) >= 2 -> {:ok, :healthy} [{:running_nodes, _}, {:stopped_nodes, stopped}] -> {:warning, "Nodes down: #{inspect(stopped)}"} end ``` -------------------------------- ### Mnesiac.cluster_status/0 Source: https://context7.com/beardedeagle/mnesiac/llms.txt Returns the current status of the Mnesia cluster, showing running and stopped nodes. ```APIDOC ## Mnesiac.cluster_status/0 ### Description Returns the current status of the Mnesia cluster, showing running and stopped nodes. ### Response - **list** (list) - A list containing tuples of :running_nodes and :stopped_nodes. ``` -------------------------------- ### Mnesiac Node Inspection Source: https://context7.com/beardedeagle/mnesiac/llms.txt Functions for checking the status of Mnesia nodes within a cluster. ```APIDOC ## Mnesiac.running_nodes/0 ### Description Returns a list of all currently running Mnesia database nodes in the cluster. ### Response - **nodes** (list) - A list of atoms representing the running node names. ## Mnesiac.node_in_cluster?/1 ### Description Checks if a specific node is part of the Mnesia cluster (running or stopped). ### Parameters #### Arguments - **node** (atom) - Required - The node name to check. ## Mnesiac.running_db_node?/1 ### Description Checks if a specific node is currently running as a Mnesia database node. ### Parameters #### Arguments - **node** (atom) - Required - The node name to check. ``` -------------------------------- ### Check node cluster membership Source: https://context7.com/beardedeagle/mnesiac/llms.txt Checks if a specific node is part of the Mnesia cluster, regardless of whether it is currently running or stopped. ```elixir # Check if node is in cluster if Mnesiac.node_in_cluster?(:"app@backup.example.com") do IO.puts("Backup node is part of the cluster") else IO.puts("Backup node needs to be added to cluster") end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.