⚡ NeoTask
Distributed Task Scheduling System / 轻量级 Python 异步分布式任务队列管理器
中文 • Website • Documentation • PyPI
🚀 Lightweight & Async: Pure Python task queue manager designed for time-consuming jobs (AI generation, video processing, data scraping, etc.)
📦 No External Services: No extra deployment required (no Redis/PostgreSQL needed). Ships with two base dependencies
⏰ Flexible Scheduling: Native support for scheduled, periodic (cron-like), and delayed tasks
⚡ Quick Integration:pip install neotask+ few lines of configuration
💡 Why NeoTask?
NeoTask is designed to solve complex task orchestration, async queueing, and priority management for modern distributed systems and AI multi-agent pipelines.
| Pain Point | NeoTask Solution |
|---|---|
| Task blockage under heavy concurrency | Priority queueing & task worker pool isolation |
| Unreliable long-running tasks | Automatic state persistence, health check & retry mechanism |
| Complex SDK setup | Lightweight Pythonic interface with zero friction |
Features
- No External Services - Pure Python implementation, no Redis/PostgreSQL required
- Immediate Tasks - Supports priority scheduling, high-priority tasks execute first
- Scheduled Tasks - Supports delayed execution, fixed intervals, and Cron expressions
- Asynchronous Concurrency - Based on asyncio, multi-worker concurrent processing
- Automatic Retry - Failed tasks automatically retry with configurable attempts
- Persistence - Multiple storage backends: Memory/SQLite/Redis
- Distributed Support - Redis shared queue, distributed lock, node heartbeat, and failed-task reclaim
- Event Callbacks - Supports task lifecycle event listeners
Use Cases
| Scenario | Description | Recommended Configuration | Entry Point |
|---|---|---|---|
| AI Text-to-Image/Video Generation | Queue time-consuming tasks to avoid blocking main flow | worker_concurrency=3 |
TaskPool |
| Batch File Processing | Batch operations like transcoding, compression, uploading | worker_concurrency=10 |
TaskPool |
| Web Scraping Scheduling | Distributed scraping to prevent being blocked | storage_type="redis" |
TaskPool |
| Scheduled Report Sending | Send daily reports at 9 AM | cron="0 9 * * *" |
TaskScheduler |
| Delayed Notifications | Send reminders 5 minutes after user action | delay_seconds=300 |
TaskScheduler |
| Heartbeat Detection | Check service health status every 30 seconds | interval_seconds=30 |
TaskScheduler |
| Background Data Analysis | Execute data aggregation tasks at night | cron="0 2 * * *" |
TaskScheduler |
Architecture & Evolution
graph TB
subgraph User["User Application Layer"]
APP[User Code]
end
subgraph NeoTask["NeoTask Core"]
TP[TaskPool<br/>Immediate Task Entry]
TS[TaskScheduler<br/>Scheduled Task Entry]
subgraph Core["Shared Core Components"]
LM[LifecycleManager<br/>Task Lifecycle Management]
QS[QueueScheduler<br/>Priority + Delayed Queue]
WP[WorkerPool<br/>Worker Pool/Concurrency Control]
FM[FutureManager<br/>Async Wait/Result Callback]
end
subgraph Internal["Internal Components"]
EB[EventBus<br/>Event Bus]
MC[MetricsCollector<br/>Metrics Collection]
LF[LockFactory<br/>Distributed Lock]
end
EX[TaskExecutor<br/>User Business Logic]
end
subgraph Storage["Storage Layer"]
MEM[MemoryStorage]
SQLITE[(SQLiteStorage)]
REDIS[(RedisStorage)]
end
APP -->|Immediate Task| TP
APP -->|Scheduled Task| TS
TS -->|Delegates| TP
TP --> LM
TP --> QS
TP --> WP
TP --> FM
LM --> MEM
LM --> SQLITE
LM --> REDIS
WP --> EX
WP --> EB
WP --> MC
WP --> LF
Development Roadmap
timeline
title NeoTask Architecture Evolution Roadmap
section v0.1
Basic Task Pool : Local Memory Queue
: Async Execution Engine
: Memory/SQLite Storage
section v0.2
Observability : Event Bus
: Metrics Collection
: Health Check
section v0.3
Scheduled Tasks : Delayed Queue/Time Wheel
: Periodic Tasks
: Cron Expression
section v0.4
Distributed Base : Redis Shared Queue
: Distributed Lock
section v0.5
Performance Optimization : Prefetch Mechanism
: Batch Operations
: Connection Pool
section v1.0
High Availability : Watchdog Renewal
: Timeout Detection
: Automatic Fault Recovery
section v1.5
Task Orchestration : DAG Workflow
: Conditional Branch
: Parallel Execution
section v2.0
Enterprise Features : Independent Web UI
: Multi-Tenancy Isolation
: Prometheus Integration
Quick Start
Installation
Requirements: Python ≥ 3.8. The base package depends on aiosqlite (SQLite storage) and croniter (Cron expressions); Redis, psutil, and the Web UI are optional extras.
# Basic installation
pip install neotask
# With Redis distributed support
pip install neotask[redis]
# Full installation
pip install neotask[full]
Immediate Tasks (TaskPool)
from neotask import TaskPool
async def process(data):
return {"result": "done", "data": data}
# Create task pool
pool = TaskPool(executor=process)
# Submit task
task_id = pool.submit({"id": 123})
# Wait for result
result = pool.wait_for_result(task_id)
pool.shutdown()
Scheduled Tasks (TaskScheduler)
from neotask import TaskScheduler
scheduler = TaskScheduler(executor=process)
# Execute after 60 seconds delay
scheduler.submit_delayed({"id": 123}, delay_seconds=60)
# Execute every 5 minutes
scheduler.submit_interval({"id": 123}, interval_seconds=300)
# Execute daily at 9 AM
scheduler.submit_cron({"id": 123}, "0 9 * * *")
scheduler.shutdown()
Using Context Manager
with TaskPool(executor=process) as pool:
task_id = pool.submit({"id": 123})
result = pool.wait_for_result(task_id)
Using Event Callbacks
from neotask import TaskPool
async def on_task_created(event):
print(f"Task created: {event.task_id}")
async def on_task_completed(event):
print(f"Task completed: {event.task_id}, Result: {event.data}")
async def on_task_failed(event):
print(f"Task failed: {event.task_id}, Error: {event.data}")
pool = TaskPool(executor=my_executor)
pool.start()
# Register event callbacks
pool.on_created(on_task_created)
pool.on_completed(on_task_completed)
pool.on_failed(on_task_failed)
task_id = pool.submit({"test": "event"})
result = pool.wait_for_result(task_id)
API Reference
| Method | Description |
|---|---|
pool.submit(data, priority=2, delay=0) |
Submit task |
pool.wait_for_result(task_id, timeout=300) |
Wait for result |
pool.get_status(task_id) |
Get status |
pool.cancel(task_id) |
Cancel task |
scheduler.submit_delayed(data, delay) |
Delayed task |
scheduler.submit_interval(data, interval) |
Periodic task |
scheduler.submit_cron(data, cron) |
Cron task |
Detailed API documentation can be found here
Usage Notes
A few behaviors are easy to trip over, so they are documented explicitly:
get_resultvswait_for_result:wait_for_result(task_id)returns the executor's raw value, whileget_result(task_id)returns a metadata wrapper dict{task_id, status, result, error, created_at, completed_at}— the real payload is underresult.- Event keys: lifecycle event types are namespaced as
task.created/task.started/task.completed/task.failed/task.cancelled/task.retry(not barecreated). Prefer thepool.on_completed(...)helpers. - Graceful shutdown scope:
shutdown(graceful=True)drains tasks that are already enqueued (pending + running) before returning. Unexpired delayed tasks and periodic/cron schedules are not fired during shutdown — cancel periodic schedules first (cancel_periodic) or usegraceful=Falsefor an immediate return. - Crash / restart recovery: auto-recovery re-runs tasks that were already
enqueued (their ids live in the persisted queue). A record created only via
create_pending_task()and never pushed throughenqueue_task()is not part of the queue, so it will not auto-run after a restart — enqueue it explicitly. - Periodic task persistence: set
SchedulerConfig(enable_persistence=True, storage_type="sqlite"|"redis")to persist interval / cron periodic tasks and auto-restore them after a restart; slots missed while down are handled by each task'smissed_policy. Withstorage_type="memory"the store is in-process only and cannot survive a restart. - Minimum interval granularity: periodic tasks are driven by a scan loop with
SchedulerConfig.scan_interval(default1.0s).submit_intervalwith an interval smaller thanscan_intervalmay skip fires; lowerscan_intervalor enable the time wheel (enable_time_wheel=True) for finer granularity.
Usage Notes
A few behaviors are easy to trip over, so they are documented explicitly:
get_resultvswait_for_result:wait_for_result(task_id)returns the executor's raw value, whileget_result(task_id)returns a metadata wrapper dict{task_id, status, result, error, created_at, completed_at}— the real payload is underresult.- Event keys: lifecycle event types are namespaced as
task.created/task.started/task.completed/task.failed/task.cancelled/task.retry(not barecreated). Prefer thepool.on_completed(...)helpers. - Graceful shutdown scope:
shutdown(graceful=True)drains tasks that are already enqueued (pending + running) before returning. Unexpired delayed tasks and periodic/cron schedules are not fired during shutdown — cancel periodic schedules first (cancel_periodic) or usegraceful=Falsefor an immediate return. - Crash / restart recovery: auto-recovery re-runs tasks that were already
enqueued (their ids live in the persisted queue). A record created only via
create_pending_task()and never pushed throughenqueue_task()is not part of the queue, so it will not auto-run after a restart — enqueue it explicitly. - Minimum interval granularity: periodic tasks are driven by a scan loop with
SchedulerConfig.scan_interval(default1.0s).submit_intervalwith an interval smaller thanscan_intervalmay skip fires; lowerscan_intervalor enable the time wheel (enable_time_wheel=True) for finer granularity.
Configuration Example
from neotask import TaskPool, TaskPoolConfig
config = TaskPoolConfig(
worker_concurrency=10, # Number of concurrent workers
max_retries=3, # Number of retries
storage_type="sqlite", # Storage type
)
pool = TaskPool(executor=process, config=config)
Detailed usage examples can be found here
Contribution Guide
Setting Up Development Environment
# Clone repository
git clone https://github.com/neopen/neotask.git
cd neotask
# Create virtual environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/
# View test coverage
pytest --cov=neotask tests/
# Run specific module tests
pytest tests/test_task_pool.py -v
pytest tests/test_task_scheduler.py -v
Contribution Workflow
Welcome to submit Issues and Pull Requests
- Fork the project
- Create a feature branch (
git checkout -b feature/amazing) - Commit changes (
git commit -m 'Add amazing feature') - Push branch (
git push origin feature/amazing) - Submit Pull Request
Code Style
- Follow PEP 8 code style
- Add appropriate type annotations
- Write unit tests for new features (coverage ≥ 80%)
- Update relevant documentation and example code
- Commit messages follow Conventional Commits
Issue Reporting
- Submit Issue: https://github.com/neopen/neotask/issues
- Feature Suggestions: Use Enhancement label
- Bug Reports: Use Bug label and provide reproduction steps
- Security Vulnerabilities: Please send email directly to the author's email
License
MIT License © 2026 NeoPen
Acknowledgments
Thanks to all contributors and the open source community for their support.
Contact
- GitHub:https://github.com/neopen/neotask
- Email:helpenx@gmail.com
- Docs:https://task.helpenx.com/docs/
- Blog: https://pengline.cn/
Metadata
Release files for neotask 1.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| neotask-1.0.4.tar.gz | 290.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| neotask-1.0.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 462.3 kB
Release files / neotask-1.0.4.tar.gz
| Download URL | neotask-1.0.4.tar.gz |
|---|---|
| Size | 290.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
00972f57ad59bf9ce0b2462dabf8234f974cf9f1e6c0eadbc4f6c8a5818502ba
|
|
BLAKE2b-256 checksum How to use checksums |
d2abe5b86e48e5e8a42252e10d09c0b448f53dceabf235cc50782f8dcea5b0c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency logRelease files / neotask-1.0.4-py3-none-any.whl
| Download URL | neotask-1.0.4-py3-none-any.whl |
|---|---|
| Size | 171.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4490a8dc9094e625ba6a1799ff3fa97a9ce815ed2bbe44eb99e278aca1eb3b93
|
|
BLAKE2b-256 checksum How to use checksums |
0b72d4fa0e830832ef7bbf24230e06839e241d08cf2589d2798c50af903c6ee8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency log