Domain Module
Overview
At a Glance
- Purpose:
Typed domain objects representing core simulation concepts
- Location:
fusion/domain/- Key Files:
config.py,request.py,lightpath.py,network_state.py,results.py- Depends On:
numpy,networkx- Used By:
fusion.core,fusion.pipelines,fusion.interfaces,fusion.rl
The domain module defines the shared vocabulary for the entire FUSION simulator.
It contains typed, validated dataclasses that represent fundamental simulation concepts:
what a request looks like, how lightpaths track capacity, what network state contains,
and what results pipelines return.
Why this module matters:
Every other module imports from
domainto work with these core conceptsType safety catches bugs at development time, not runtime
Immutable result objects prevent accidental state corruption
Legacy conversion methods enable gradual migration from dict-based code
In This Section
Domain Objects - Detailed documentation of each domain object
Object Lifecycle in the Pipeline - How objects flow through the request pipeline
When you work here:
Adding new fields to existing domain objects
Creating new result types for pipeline stages
Understanding how data flows through the simulator
Debugging request processing or allocation issues
How Domain Differs from Configs and CLI
New developers often confuse these three modules. Here’s how they relate:
+------------------+ +------------------+ +------------------+
| CLI | | Configs | | Domain |
| (Entry Point) | | (File Parsing) | | (Runtime Objects)|
+------------------+ +------------------+ +------------------+
| | ^
| User runs | INI files | Used throughout
| fusion-sim | parsed into | simulation
v v |
+------------------+ +------------------+ |
| Parse arguments |---->| Merge with INI | |
| --network NSFNet | | configuration | |
+------------------+ +------------------+ |
| |
v |
+------------------+ |
| Create engine_ |----------->|
| props dict | |
+------------------+ |
| |
v |
+------------------+ +------+-------+
| SimulationConfig |---->| Orchestrator |
| (domain object) | | uses config |
+------------------+ +--------------+
Aspect |
CLI ( |
Configs ( |
Domain ( |
|---|---|---|---|
Purpose |
Entry point, argument parsing |
INI file parsing, validation |
Runtime data structures |
When Used |
At startup only |
At startup only |
Throughout simulation |
Key Classes |
|
|
|
Data Flow |
Args -> engine_props |
INI -> engine_props |
engine_props -> typed objects |
Mutability |
N/A (procedural) |
Mutable dicts |
Immutable dataclasses |
In short:
CLI: How users invoke the simulator (command-line arguments)
Configs: How configuration files are parsed (INI templates, validation)
Domain: The typed objects used during simulation (requests, lightpaths, results)
Key Concepts
Understanding these concepts is essential before working with domain objects:
- Immutability
Most domain objects use
@dataclass(frozen=True)making them immutable after creation. This prevents bugs where objects are accidentally modified and enables safe sharing between components.- Validation on Creation
All domain objects validate their invariants in
__post_init__. Invalid data fails fast with clear error messages rather than causing subtle bugs later.- Legacy Conversion
Domain objects provide
from_legacy_dict()andto_legacy_dict()methods for interoperability with older code that uses plain dictionaries. These will be removed in v6.1.0 once migration is complete.- Result Objects
Pipeline stages return immutable result objects (
RouteResult,SpectrumResult, etc.) that capture the outcome. Thesuccessfield is the single source of truth for whether an operation succeeded.- State vs. Configuration
SimulationConfigis immutable configuration set once at startup.NetworkStateis mutable state that changes as requests are processed.RequestandLightpathtrack individual connection lifecycle.
Architecture
Module Structure
fusion/domain/
|-- __init__.py # Public API exports
|-- config.py # SimulationConfig - immutable configuration
|-- request.py # Request, RequestType, RequestStatus, BlockReason
|-- lightpath.py # Lightpath - optical path with capacity tracking
|-- network_state.py # NetworkState, LinkSpectrum - mutable network state
|-- results.py # Pipeline result objects (frozen dataclasses)
|-- README.md # Module documentation
|-- TODO.md # Development roadmap
`-- tests/ # Unit tests
|-- test_config.py
|-- test_request.py
|-- test_network_state.py
`-- test_results.py
Object Relationship Diagram
The following diagram shows how domain objects relate to each other:
+-------------------+
| SimulationConfig | (immutable, created once at startup)
+-------------------+
|
| provides parameters for
v
+-------------------+ +-------------------+
| NetworkState |<------->| Lightpath |
| (mutable state) | owns | (capacity mgmt) |
+-------------------+ +-------------------+
^ ^
| |
| queries/updates | creates/uses
| |
+-------------------+ +-------------------+
| Request |-------->| AllocationResult |
| (service request) | yields | (pipeline output) |
+-------------------+ +-------------------+
|
| contains
v
+-------------------+
| RouteResult |
| SpectrumResult |
| GroomingResult |
| SNRResult |
| SlicingResult |
| ProtectionResult |
+-------------------+
Data Flow Summary
Configuration:
SimulationConfigis created fromengine_propsat startupState Initialization:
NetworkStateis created with topology and empty spectrumRequest Arrival:
Requestobjects are generated with source, destination, bandwidthPipeline Processing: Orchestrator processes request through pipeline stages
Result Objects: Each stage returns an immutable result (
RouteResult, etc.)State Updates:
NetworkStateis updated with new lightpaths and spectrum allocationsFinal Result:
AllocationResultcaptures whether request was served or blocked
Components
config.py
- Purpose:
Immutable simulation configuration
- Key Classes:
SimulationConfig
Replaces the mutable engine_props dictionary with a typed, validated, frozen
dataclass. Provides type safety, IDE autocompletion, and clear defaults.
from fusion.domain import SimulationConfig
# Create from legacy dict
config = SimulationConfig.from_engine_props(engine_props)
# Access with type safety
print(config.network_name) # IDE knows this is str
print(config.cores_per_link) # IDE knows this is int
request.py
- Purpose:
Network service request with lifecycle tracking
- Key Classes:
Request,RequestType,RequestStatus,BlockReason,ProtectionStatus
Represents a connection request from source to destination with bandwidth requirement. Tracks lifecycle state from PENDING through ALLOCATED or BLOCKED.
from fusion.domain import Request, RequestType, RequestStatus
request = Request(
request_id=1,
source="0",
destination="5",
bandwidth_gbps=100,
arrive=0.5,
depart=1.5,
)
# Lifecycle tracking
print(request.status) # RequestStatus.PENDING
lightpath.py
- Purpose:
Allocated optical path with capacity management
- Key Classes:
Lightpath
Represents an established optical connection with spectrum assignment. Supports traffic grooming by tracking capacity and per-request bandwidth allocations.
from fusion.domain import Lightpath
lp = Lightpath(
lightpath_id=1,
path=["0", "2", "5"],
start_slot=10,
end_slot=18,
core=0,
band="c",
modulation="QPSK",
total_bandwidth_gbps=100,
remaining_bandwidth_gbps=100,
)
# Capacity management
if lp.can_accommodate(50):
lp.allocate_bandwidth(request_id=42, bandwidth_gbps=50)
network_state.py
- Purpose:
Mutable network state container
- Key Classes:
NetworkState,LinkSpectrum
The single source of truth for network state during simulation. Owns all
LinkSpectrum objects and the lightpath registry.
from fusion.domain import NetworkState
# Check spectrum availability
if state.is_spectrum_available(path, start, end, core, band):
lightpath_id = state.create_lightpath(...)
results.py
- Purpose:
Immutable pipeline stage outputs
- Key Classes:
RouteResult,SpectrumResult,GroomingResult,SlicingResult,SNRResult,ProtectionResult,AllocationResult
Each pipeline stage returns a frozen result object. AllocationResult is the
final output indicating success or failure with detailed tracking.
from fusion.domain import AllocationResult, BlockReason
# Successful allocation
result = AllocationResult(
success=True,
lightpaths_created=(1,),
total_bandwidth_allocated_gbps=100,
)
# Blocked request
result = AllocationResult(
success=False,
block_reason=BlockReason.CONGESTION,
)
Dependencies
This Module Depends On
numpy- Spectrum array storage in LinkSpectrumnetworkx- Topology queries in NetworkStateStandard Library:
dataclasses,enum,typing
Modules That Depend On This
fusion.core- SimulationEngine, SDNOrchestrator, SDNControllerfusion.pipelines- All pipeline implementationsfusion.interfaces- Pipeline protocols reference domain typesfusion.rl- RL adapters work with Request and NetworkStatefusion.modules- Routing, spectrum, SNR modules
Testing
- Test Location:
fusion/domain/tests/- Run Tests:
pytest fusion/domain/tests/ -v- Coverage Target:
80%+
Test files:
test_config.py- SimulationConfig creation and conversiontest_request.py- Request lifecycle and enumstest_network_state.py- NetworkState and LinkSpectrum operationstest_results.py- All result dataclasses
Adding new tests:
def test_lightpath_when_capacity_exceeded_then_returns_false():
"""Test that allocate_bandwidth returns False when insufficient capacity."""
# Arrange
lp = Lightpath(
lightpath_id=1,
path=["0", "5"],
start_slot=0,
end_slot=8,
core=0,
band="c",
modulation="QPSK",
total_bandwidth_gbps=100,
remaining_bandwidth_gbps=50,
)
# Act
result = lp.allocate_bandwidth(request_id=1, bandwidth_gbps=100)
# Assert
assert result is False
assert lp.remaining_bandwidth_gbps == 50 # Unchanged