AstraFlux Description
Project description
AstraFlux is a lightweight distributed service framework built around a self-developed dependency injection container. It delivers enterprise-grade capabilities - task scheduling with DAG dependencies, RabbitMQ-based RPC with circuit breaker, worker management, and a web dashboard - with minimal boilerplate and zero external orchestration dependencies.
Install
pip install astraflux
Requires Python 3.9+, with MongoDB, Redis, and RabbitMQ running.
Quick Start
Create a config.yaml
mongodb:
host: 127.0.0.1
port: 27017
username: scheduleAdmin
password: scheduleAdminPassword
redis:
host: 127.0.0.1
port: 6379
password: scheduleAdminPassword
db_index: 8
rabbitmq:
host: 127.0.0.1
port: 5672
username: scheduleAdmin
password: scheduleAdminPassword
logger:
path: logs
level: INFO
web:
port: 7860
username: admin
password: admin
rpc:
call_timeout: 30
max_retries: 3
circuit_breaker_threshold: 5
circuit_breaker_recovery: 30
Write a service
from astraflux import ServiceConstructor, WorkerConstructor, rpc_decorator
class RpcFunction(ServiceConstructor):
service_name = "my_service"
@rpc_decorator
def ping(self):
return {"status": "ok"}
@rpc_decorator
def add(self, a: int, b: int) -> int:
return {"result": a + b}
class WorkerFunction(WorkerConstructor):
worker_name = "my_service"
def run(self, data: dict):
self.logger.info(f"Executing task: {data}")
return {"status": "success"}
Start everything
from astraflux import AstraFlux, launch_register, launch_start
AstraFlux(yaml_path="path/to/config.yaml", current_dir="path/to/project")
launch_register(services=[RpcFunction, WorkerFunction])
launch_start()
# Keep the process alive
import time
while True:
time.sleep(60)
Architecture
+---------------------------+
| DI Container (FixtureManager) |
| Single / Global / Thread scopes|
| Lazy resolution of dependencies|
+-------+-------------------+
|
+-------+------+----------+---------+----------+
| | | | | |
v v v v v v
MongoDB Redis RabbitMQ Scheduler Executors Web UI
(tasks) (workers) (RPC) (DAG) (pools) (Flask)
Config propagation:
config.yaml --> _settings.py (merge defaults) --> fixture_config (dict)
|
Each provider reads config[key]
(No fallback logic in business code)
Why AstraFlux?
Self-owned DI container - register once, inject everywhere. No framework lock-in.
Task DAG scheduler - dependency graphs, failure propagation, subtask management.
Production RPC - timeout, exponential backoff retry, circuit breaker.
Worker capacity management - Redis-based slot tracking, automatic scheduling.
Web management UI - out of the box, tasks, services, system monitoring.
Zero orchestration - no Kubernetes, no etcd, no ZooKeeper needed.
Modules
DI Container
The FixtureManager is the backbone of AstraFlux. Services are registered as named fixtures with configurable scopes. When a function is called, the container resolves its parameter names as fixture names and injects the values automatically.
@register_fixture(name="fixture_config")
def app_config():
yield config_data # merged with defaults
@register_fixture(name="fixture_mongodb")
def task_collection(fixture_config):
cfg = fixture_config["mongodb"]
yield MongoDatabase(cfg)
Supported scopes:
SINGLETON - one instance per process
GLOBAL - cached until explicit clear_cache()
THREAD - one cache entry per thread (thread-safe)
Cleanup is built in: when a fixture uses yield, the code after the yield runs on clear_cache(), making it trivial to release resources.
Configuration System
All defaults are defined in constants and merged by the config loader into a complete dict. Business code reads config[key] directly - no fallback logic.
Currently managed config sections:
MONGODB, REDIS, RABBITMQ, LOGGER, RPC, WEB
If a config section or key is missing from the YAML file, the system falls back to the hardcoded default - every optional field has a sensible default.
Distributed Task Scheduler
The scheduler runs as a cron job (every 10 seconds) in a single 8-step cycle:
Fetch active tasks from MongoDB
Build a DAG from task dependencies (depends_on field)
Propagate failures - if a parent fails, its children are marked failed
Find runnable tasks - all dependencies must be satisfied or in a final state
Identify priority subtasks - children of currently running parents get priority
Dispatch to RabbitMQ queues, respecting worker capacity per service
Update parent statuses based on child completion
Persist all status changes back to MongoDB
from astraflux import task_submit, task_stop, task_retry
# Submit a task to a specific worker queue
task_id = task_submit(worker_name="my_service", body={...})
# Stop a running task
task_stop(task_id)
# Retry a failed task
task_retry(task_id)
# Subtasks with dependency tracking
subtasks_create(
subtask_queue="my_service",
source_id=task_id,
subtask_list=[{...}, {...}]
)
The scheduler runs in distributed_unique mode by default - only one instance across the cluster executes the scheduling cycle. ip_unique ensures one monitor per host.
RPC
RabbitMQ-based RPC with production-grade reliability:
Timeout - configurable per-call, defaults to 30 seconds
Retry - exponential backoff with configurable base and max delay
Circuit breaker - opens after N consecutive failures, recovers after M seconds
Auto-reconnection - recovers from connection/channel errors transparently
from astraflux import proxy_call, rpc_decorator, start_consumer
# Client: call a remote method
result = proxy_call(
service_name="my_service",
method_name="add",
a=1, b=2
)
# Server: mark methods as remotely callable
class RpcFunction(ServiceConstructor):
@rpc_decorator
def add(self, a, b):
return a + b
# Start consuming RPC requests
start_consumer(queue_name="my_service", service_instance=instance)
Arguments are serialized with dill (supports most Python types) and sent to a RabbitMQ queue. The server dispatches by method name and returns the result to a private callback queue.
Worker Management
Workers are registered in Redis with their capacity and live process list. The scheduler queries this data to decide where to dispatch tasks.
from astraflux import (
redis_store_worker_data,
redis_get_available_slots,
redis_get_worker_status,
get_total_available_slots_by_server_name,
)
# Register a worker
redis_store_worker_data({
"unique_id": "my_service_192.168.1.10",
"worker_name": "my_service",
"worker_ipaddr": "192.168.1.10",
"worker_max_process": 10,
...
})
# Check available capacity before dispatching
slots = redis_get_available_slots(unique_id="my_service_192.168.1.10")
if slots > 0:
# Dispatch task...
# Service-level capacity summary
total_slots = get_total_available_slots_by_server_name("my_service")
Each worker process is spawned by multiprocessing.Process - fully isolated, robust resource management.
Launcher
The ServiceLauncher orchestrates the complete startup sequence. For each registered service:
Launch a service process - starts an RPC consumer that listens on RabbitMQ
Launch a worker process - starts a message queue consumer that processes tasks
Then, if scheduled jobs are enabled:
Start the TaskScheduler cron job (every 10 seconds, distributed-unique)
Start the SystemMonitoring cron job (every 30 seconds, ip-unique)
Optionally launch the Web UI as a separate process
from astraflux import launch_register, launch_start
launch_register(services=[RpcFunction, WorkerFunction])
launch_start(run_app=True, scheduled=True)
The launcher also handles graceful cleanup via kill() - terminates all spawned processes.
Web Management UI
Flask-based dashboard with login authentication, providing:
Service monitoring - platform info, RPC status, function listing
Task management - submit, stop, retry, paginated task list
Worker status - live capacity, run processes, available slots
System monitoring - memory, CPU, disk usage via psutil
Access: http://<bind_ip>:<port> (default 0.0.0.0:7860).
Executors
Thread and process pool executors with built-in retry and progress tracking:
from astraflux import thread_executor, process_executor
# Thread pool (shared memory, fast)
executor = thread_executor(max_workers=5, retry_delay=1.0)
executor.submit(func=my_task, arg1=val1, max_retries=3)
executor.start()
# Process pool (isolated, for CPU-bound work)
pe = process_executor(max_workers=4)
pe.submit(func=my_cpu_task, data=big_data)
pe.start()
Features: - Exponential backoff retry for failed tasks - Task status tracking (pending, running, failed, success) - Configurable queue size
Configuration Reference
Full config.yaml reference:
mongodb:
host: 127.0.0.1
port: 27017
username: scheduleAdmin
password: scheduleAdminPassword
max_connections: 20
redis:
host: 127.0.0.1
port: 6379
password: scheduleAdminPassword
db_index: 8
max_connections: 20
rabbitmq:
host: 127.0.0.1
port: 5672
username: scheduleAdmin
password: scheduleAdminPassword
logger:
path: logs
level: INFO
web:
port: 7860
bind_ip: 0.0.0.0
username: admin
password: admin
rpc:
call_timeout: 30
max_retries: 3
retry_base_delay: 1.0
retry_max_delay: 30.0
circuit_breaker_threshold: 5
circuit_breaker_recovery: 30
Any omitted key falls back to defaults.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file astraflux-1.5.0.tar.gz.
File metadata
- Download URL: astraflux-1.5.0.tar.gz
- Upload date:
- Size: 93.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c08d30b9c6f6426b0e08beb9cc552e1c2003368e559dc015ecd5c8d24277a77d
|
|
| MD5 |
59aaa45e98cb3695cefca5379e68bd05
|
|
| BLAKE2b-256 |
a656d40e037e142fe837d4952d2b82a9647d0ec816bb20e87a5f11526a3dfe32
|
File details
Details for the file astraflux-1.5.0-py3-none-any.whl.
File metadata
- Download URL: astraflux-1.5.0-py3-none-any.whl
- Upload date:
- Size: 108.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01a465643e2662ea407ffd912bb56e0cb2ff7a3472826f76a7be5f898848c3aa
|
|
| MD5 |
aea2d922456169be7af1b16d4b4c6a06
|
|
| BLAKE2b-256 |
be1ed6ee1feb608f4ec63c4860d0973deb86e03f396dab9202ce5afffa1c1e51
|