How MiroFish Handles Asynchronous Tasks for Long-Running Simulations
MiroFish leverages Python's asyncio framework with a global shutdown event, signal handlers, and asyncio.gather() to execute Twitter and Reddit simulations concurrently while maintaining responsive control over potentially endless processes.
The 666ghj/mirofish repository implements a sophisticated asynchronous architecture to manage long-running social media simulations. By utilizing Python's native asyncio library, the system can execute complex Twitter and Reddit simulations without blocking the interpreter, while providing robust mechanisms for graceful shutdown and external command integration.
Core Async Architecture
Global Event Loop and Shutdown Coordination
At the heart of the system is a global asyncio.Event named _shutdown_event, instantiated in backend/scripts/run_parallel_simulation.py (lines 25-28). This event serves as a coordination mechanism that all coroutines monitor to detect termination requests.
# From run_parallel_simulation.py lines 25-28
_shutdown_event = asyncio.Event()
def signal_handler(signum, frame):
logger.info(f"Received signal {signum}, shutting down...")
_shutdown_event.set()
Async Simulation Loops
Each platform simulation runs as an independent async def coroutine. The run_twitter_simulation and run_reddit_simulation functions (lines 28-34) implement the main execution loops that repeatedly determine active agents, build dictionaries of LLMAction() objects, execute await env.step(actions), and read SQLite traces to log actions.
Execution Control and Resource Management
Round Limiting via CLI
To prevent infinite execution, the system accepts a --max-rounds parameter through the CLI. In run_parallel_simulation.py (lines 20-24), the configuration-derived round count is truncated to this limit, enabling controlled testing and CI/CD integration.
python backend/scripts/run_parallel_simulation.py \
--config simulations/run1/simulation_config.json \
--max-rounds 200
Graceful Shutdown Implementation
The system registers signal handlers for SIGINT and SIGTERM in setup_signal_handlers (lines 63-72). When triggered, the handler sets _shutdown_event, which unblocks coroutines waiting on await asyncio.wait_for(_shutdown_event.wait(), timeout=0.5). The environments then close via await env.close() before the process exits cleanly.
Parallel Execution and IPC
Concurrent Platform Simulation
When neither --twitter-only nor --reddit-only flags are present, the system launches both simulations concurrently using asyncio.gather() (lines 84-88). Each platform maintains independent loggers and SQLite databases while sharing the global shutdown event for coordinated termination.
# From run_parallel_simulation.py lines 84-88
await asyncio.gather(
run_twitter_simulation(twitter_env, config, logger, max_rounds),
run_reddit_simulation(reddit_env, config, logger, max_rounds)
)
Post-Simulation Command Interface
After completing the main simulation loop, the system enters an IPC (Inter-Process Communication) loop when --no-wait is not specified. The ParallelIPCHandler.process_commands coroutine polls a directory for JSON command files containing instructions such as "interview" or "batch interview", executing them asynchronously against the live OASIS environment.
Summary
- MiroFish leverages Python's
asyncioframework to execute long-running Twitter and Reddit simulations without blocking the interpreter. - A global
_shutdown_eventcoordinates graceful termination across all concurrent coroutines whenSIGINTorSIGTERMsignals are received. - The
--max-roundsCLI parameter provides deterministic execution limits for testing and CI environments. asyncio.gather()enables parallel execution of platform-specific simulations while maintaining independent logging and database resources.- The IPC command loop allows external tools to interact with running simulations via JSON file drops, supporting interview commands and batch operations.
Frequently Asked Questions
How does MiroFish prevent simulations from running indefinitely?
The system implements a round-limiting mechanism through the --max-rounds CLI argument. In backend/scripts/run_parallel_simulation.py (lines 20-24), the total round count derived from the configuration file is truncated to this specified limit, ensuring simulations terminate deterministically for testing or production constraints.
What happens when I press Ctrl+C during a simulation?
Pressing Ctrl+C sends a SIGINT signal that triggers the setup_signal_handlers function (lines 63-72). This sets the global _shutdown_event, which causes all running coroutines to exit their main loops cleanly. The system then awaits environment closure via await env.close() before terminating, preventing data corruption in the SQLite trace databases.
Can I run Twitter and Reddit simulations simultaneously?
Yes. When neither --twitter-only nor --reddit-only flags are provided, the main function uses asyncio.gather() (lines 84-88) to launch both run_twitter_simulation and run_reddit_simulation concurrently. Each platform operates with independent loggers and SQLite databases while sharing the global shutdown event for coordinated termination.
How do external tools interact with a running simulation after it completes the main loop?
When the --no-wait flag is omitted, the system enters an IPC (Inter-Process Communication) loop via ParallelIPCHandler.process_commands. This coroutine monitors a designated directory for JSON command files containing instructions such as "interview" or "batch interview". Upon detecting a valid command, it executes the operation asynchronously against the live OASIS environment and writes responses to an output directory, enabling external orchestration without restarting the simulation infrastructure.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →