Packages
Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.
Current section
Files
Jump to
Current section
Files
lib/raxol/cloud/edge_computing.ex
defmodule Raxol.Cloud.EdgeComputing do
@moduledoc """
Edge computing support for Raxol applications.
This module provides functionality for optimizing Raxol applications
at the edge, allowing for improved performance, reduced latency,
and offline capabilities.
Features:
* Edge processing configuration
* Offline mode and data synchronization
* Resource optimization for edge devices
* Automatic failover between edge and cloud
* Edge-specific monitoring and diagnostics
* Edge-to-cloud data streaming
"""
alias Raxol.Cloud.EdgeComputing.{Core, Execution, Connection}
@doc """
Initializes the edge computing system.
## Options
* `:mode` - Operation mode (:edge_only, :cloud_only, :hybrid) (default: :hybrid)
* `:connection_check_interval` - Time in ms between connection checks (default: 5000)
* `:sync_interval` - Time in ms between cloud syncs (default: 30000)
* `:retry_limit` - Number of retry attempts for operations (default: 5)
* `:compression_enabled` - Whether to compress data for transfer (default: true)
* `:offline_cache_size` - Maximum size in bytes for offline cache (default: 100MB)
* `:priority_functions` - List of functions that should prioritize edge execution
## Examples
iex> init(mode: :hybrid)
:ok
"""
defdelegate init(opts \\ []), to: Core
@doc """
Updates the edge computing configuration.
"""
defdelegate update_config(state \\ nil, config), to: Core
@doc """
Executes a function at the edge or in the cloud based on current mode and conditions.
## Options
* `:force_edge` - Force execution at the edge even in hybrid mode (default: false)
* `:force_cloud` - Force execution in the cloud even in hybrid mode (default: false)
* `:fallback_fn` - Function to execute if primary execution fails (default: nil)
* `:timeout` - Timeout in milliseconds for the operation (default: 5000)
* `:retry` - Number of retry attempts (default: from config)
## Examples
iex> execute(fn -> process_data(data) end)
{:ok, result}
"""
defdelegate execute(func, opts \\ []), to: Execution
@doc """
Synchronizes data between edge and cloud.
## Options
* `:force` - Force immediate synchronization (default: false)
* `:selective` - List of data types to synchronize (default: all)
* `:direction` - Sync direction (:both, :to_cloud, :from_cloud) (default: :both)
* `:conflict_resolution` - Strategy for resolving conflicts (default: :latest_wins)
## Examples
iex> sync(force: true)
{:ok, %{status: :completed, synced_items: 5}}
"""
def sync(_opts \\ []) do
# Sync with cloud
:ok
end
@doc """
Checks if the system is currently operating in offline mode.
"""
defdelegate offline?, to: Core
@doc """
Gets the current status of the edge computing system.
"""
defdelegate status, to: Core
@doc """
Manually checks the cloud connection status and updates the system state.
"""
defdelegate check_connection, to: Connection
@doc """
Forces the system into a specific mode.
"""
defdelegate force_mode(mode), to: Core
@doc """
Gets metrics for the edge computing system.
"""
defdelegate get_metrics, to: Core
@doc """
Clears the edge cache.
"""
defdelegate clear_cache, to: Core
# All private functions have been moved to focused modules
end
# Cache implementation for edge computing
defmodule Raxol.Cloud.EdgeComputing.Cache do
@moduledoc false
# Process dictionary key for cache
@cache_key :raxol_edge_cache
def init(config) do
cache = %{
items: %{},
size: 0,
max_size: config.offline_cache_size
}
Process.put(@cache_key, cache)
:ok
end
def put(key, value, opts \\ []) do
cache = get_cache()
# Calculate size of data (simplified)
data_size = :erlang.term_to_binary(value) |> byte_size()
# Check if we have space
if cache.size + data_size > cache.max_size do
# Need to evict something
evict(data_size)
end
# Add the item
item = %{
value: value,
size: data_size,
created_at: DateTime.utc_now(),
ttl: Keyword.get(opts, :ttl),
metadata: Keyword.get(opts, :metadata, %{})
}
updated_items = Map.put(cache.items, key, item)
updated_size = cache.size + data_size
# Update cache
Process.put(@cache_key, %{cache | items: updated_items, size: updated_size})
:ok
end
def get(key) do
cache = get_cache()
case Map.get(cache.items, key) do
nil ->
nil
item ->
# Check TTL
if item.ttl &&
DateTime.diff(DateTime.utc_now(), item.created_at) > item.ttl do
# Item expired
delete(key)
nil
else
item.value
end
end
end
def delete(key) do
cache = get_cache()
case Map.get(cache.items, key) do
nil ->
:ok
item ->
# Update cache
updated_items = Map.delete(cache.items, key)
updated_size = cache.size - item.size
Process.put(@cache_key, %{
cache
| items: updated_items,
size: updated_size
})
:ok
end
end
def clear do
cache = get_cache()
# Reset cache
Process.put(@cache_key, %{cache | items: %{}, size: 0})
:ok
end
def usage do
cache = get_cache()
%{
item_count: map_size(cache.items),
size: cache.size,
max_size: cache.max_size,
percentage_used: cache.size / cache.max_size * 100
}
end
# Private helpers
defp get_cache do
Process.get(@cache_key) || %{items: %{}, size: 0, max_size: 100_000_000}
end
defp evict(needed_size) do
cache = get_cache()
if map_size(cache.items) == 0 do
:ok
else
# Simple LRU eviction strategy
# Sort by creation time (oldest first)
sorted_items =
cache.items
|> Enum.sort_by(fn {_, item} -> item.created_at end, DateTime)
# Start evicting until we have enough space
{updated_items, updated_size} =
evict_items(sorted_items, cache.items, cache.size, needed_size)
# Update cache
Process.put(@cache_key, %{
cache
| items: updated_items,
size: updated_size
})
:ok
end
end
defp evict_items([], items, size, _) do
# Nothing left to evict
{items, size}
end
defp evict_items([{key, item} | rest], items, size, needed_size) do
# Remove this item
updated_items = Map.delete(items, key)
updated_size = size - item.size
# Check if we have enough space now
if size - updated_size >= needed_size do
# We've freed enough space
{updated_items, updated_size}
else
# Need to evict more
evict_items(rest, updated_items, updated_size, needed_size)
end
end
end
# Queue implementation for edge computing
defmodule Raxol.Cloud.EdgeComputing.Queue do
@moduledoc false
# Process dictionary key for queue
@queue_key :raxol_edge_queue
def init(_config) do
queue = %{
operations: [],
next_id: 1
}
Process.put(@queue_key, queue)
:ok
end
def enqueue_operation(type, data) do
queue = get_queue()
operation = %{
id: queue.next_id,
type: type,
data: data,
created_at: DateTime.utc_now(),
attempts: 0
}
# Add operation to queue
updated_operations = queue.operations ++ [operation]
# Update queue
Process.put(@queue_key, %{
queue
| operations: updated_operations,
next_id: queue.next_id + 1
})
operation.id
end
def pending_count do
queue = get_queue()
length(queue.operations)
end
@doc """
Process all pending operations in the queue.
"""
def process_pending do
queue = get_queue()
# Process each operation
{processed, remaining} =
Enum.split_with(queue.operations, fn operation ->
result = process_operation(operation)
result == :ok || result == :failed
end)
# Update queue with remaining operations
Process.put(@queue_key, %{queue | operations: remaining})
# Return number of processed operations
length(processed)
end
# Private helpers
defp get_queue do
Process.get(@queue_key) || %{operations: [], next_id: 1}
end
defp process_operation(operation) do
# Increment attempt counter
operation = %{operation | attempts: operation.attempts + 1}
# Process based on type
case operation.type do
:function ->
# Execute the function in the cloud
func = operation.data.function
_opts = operation.data.options
try do
# Simulate cloud execution
_result = func.()
:ok
rescue
_ ->
if operation.attempts >= 3 do
:failed
else
:retry
end
end
:sync ->
Raxol.Cloud.EdgeComputing.SyncManager.sync(operation.data)
_ ->
:failed
end
end
end
# Sync manager implementation for edge computing
defmodule Raxol.Cloud.EdgeComputing.SyncManager do
@moduledoc false
# Process dictionary key for sync state
@sync_key :raxol_edge_sync_state
def init(config) do
sync_state = %{
last_sync: nil,
config: config,
pending_changes: %{},
conflict_strategy: :latest_wins
}
Process.put(@sync_key, sync_state)
:ok
end
def sync(_opts \\ []) do
sync_state = get_sync_state()
# Record the sync attempt
updated_sync_state = %{sync_state | last_sync: DateTime.utc_now()}
Process.put(@sync_key, updated_sync_state)
# Simulate sync
# In a real implementation, this would communicate with a cloud service
Process.sleep(100)
# Return success with some stats
{:ok,
%{
status: :completed,
synced_items: map_size(sync_state.pending_changes),
timestamp: DateTime.utc_now()
}}
end
# Private helpers
defp get_sync_state do
Process.get(@sync_key) ||
%{
last_sync: nil,
config: %{},
pending_changes: %{},
conflict_strategy: :latest_wins
}
end
end