taskmanager-engine 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taskmanager_engine-0.1.0/PKG-INFO +284 -0
- taskmanager_engine-0.1.0/README.md +263 -0
- taskmanager_engine-0.1.0/pyproject.toml +50 -0
- taskmanager_engine-0.1.0/setup.cfg +4 -0
- taskmanager_engine-0.1.0/taskmanager/__init__.py +150 -0
- taskmanager_engine-0.1.0/taskmanager/api/app.py +488 -0
- taskmanager_engine-0.1.0/taskmanager/api/events.py +68 -0
- taskmanager_engine-0.1.0/taskmanager/cli.py +291 -0
- taskmanager_engine-0.1.0/taskmanager/config.py +19 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/__init__.py +3 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/django/__init__.py +6 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/django/apps.py +46 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/django/management/__init__.py +1 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/django/management/commands/__init__.py +1 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/django/management/commands/run_scheduler.py +44 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/django/management/commands/run_worker.py +72 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/django/urls.py +30 -0
- taskmanager_engine-0.1.0/taskmanager/contrib/fastapi.py +31 -0
- taskmanager_engine-0.1.0/taskmanager/core/broker.py +541 -0
- taskmanager_engine-0.1.0/taskmanager/core/builtin_tasks.py +59 -0
- taskmanager_engine-0.1.0/taskmanager/core/job.py +50 -0
- taskmanager_engine-0.1.0/taskmanager/core/task.py +224 -0
- taskmanager_engine-0.1.0/taskmanager/scheduler/cron.py +52 -0
- taskmanager_engine-0.1.0/taskmanager/scheduler/scheduler.py +178 -0
- taskmanager_engine-0.1.0/taskmanager/ui/app.js +1390 -0
- taskmanager_engine-0.1.0/taskmanager/ui/index.html +681 -0
- taskmanager_engine-0.1.0/taskmanager/ui/styles.css +1048 -0
- taskmanager_engine-0.1.0/taskmanager/worker/heartbeat.py +150 -0
- taskmanager_engine-0.1.0/taskmanager/worker/worker.py +207 -0
- taskmanager_engine-0.1.0/taskmanager_engine.egg-info/PKG-INFO +284 -0
- taskmanager_engine-0.1.0/taskmanager_engine.egg-info/SOURCES.txt +39 -0
- taskmanager_engine-0.1.0/taskmanager_engine.egg-info/dependency_links.txt +1 -0
- taskmanager_engine-0.1.0/taskmanager_engine.egg-info/entry_points.txt +2 -0
- taskmanager_engine-0.1.0/taskmanager_engine.egg-info/requires.txt +15 -0
- taskmanager_engine-0.1.0/taskmanager_engine.egg-info/top_level.txt +1 -0
- taskmanager_engine-0.1.0/tests/test_api.py +304 -0
- taskmanager_engine-0.1.0/tests/test_contrib_django.py +47 -0
- taskmanager_engine-0.1.0/tests/test_core.py +106 -0
- taskmanager_engine-0.1.0/tests/test_library.py +84 -0
- taskmanager_engine-0.1.0/tests/test_scheduler.py +99 -0
- taskmanager_engine-0.1.0/tests/test_worker.py +132 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: taskmanager-engine
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: High-performance background task execution engine with dynamic cron scheduling and Linear-themed SPA dashboard
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: fastapi>=0.110.0
|
|
8
|
+
Requires-Dist: uvicorn[standard]>=0.28.0
|
|
9
|
+
Requires-Dist: redis[hiredis]>=5.0.0
|
|
10
|
+
Requires-Dist: pydantic>=2.6.0
|
|
11
|
+
Requires-Dist: croniter>=2.0.0
|
|
12
|
+
Requires-Dist: psutil>=5.9.0
|
|
13
|
+
Requires-Dist: fakeredis>=2.21.0
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
17
|
+
Requires-Dist: fakeredis>=2.21.0; extra == "dev"
|
|
18
|
+
Requires-Dist: ruff>=0.3.0; extra == "dev"
|
|
19
|
+
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
20
|
+
Requires-Dist: websockets>=12.0; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# TaskManager ⚡
|
|
23
|
+
|
|
24
|
+
<div align="center">
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+

|
|
28
|
+

|
|
29
|
+

|
|
30
|
+

|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
**Engine moderna de execução e gerenciamento de background tasks em Python inspirada no Celery e BullMQ.**
|
|
34
|
+
*Agendador Cron Dinâmico • Observabilidade LGTM Completa • Dead Letter Queue Multi-Fila • Telemetria com Backpressure • Dashboard SPA Linear Dark.*
|
|
35
|
+
|
|
36
|
+
<br/>
|
|
37
|
+
|
|
38
|
+
<img src="docs/images/01_dashboard_overview.png" alt="TaskManager Dashboard Overview" width="100%" style="border-radius: 12px; border: 1px solid #23252a; box-shadow: 0 20px 40px rgba(0,0,0,0.6);" />
|
|
39
|
+
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 🌟 Principais Destaques
|
|
45
|
+
|
|
46
|
+
- **🚀 Asyncio & Sync Worker Runtime**: Suporte nativo e transparente para corrotinas assíncronas (`async def`) e funções síncronas (`def`), com concorrência ajustável e timeouts granulares.
|
|
47
|
+
- **📦 Redis Broker com Durabilidade AOF**: Sem brokers pesados. Utiliza listas atômicas do Redis (`LPOP`/`BLPOP`), conjuntos ordenados para jobs agendados e histórico, e persistência AOF para garantia de *Zero Data Loss*.
|
|
48
|
+
- **🧠 Fallback In-Memory Automático**: Modo de desenvolvimento zero-dependência (`fakeredis`) quando o Redis local não estiver em execução.
|
|
49
|
+
- **✨ Decorator `@task` & Introspecção**: Enfileiramento via `.delay(*args, **kwargs)` ou `.apply_async(...)` com geração automática de schemas e payload no painel.
|
|
50
|
+
- **⏰ Agendador Cron & Intervalos em Tempo Real**: Sintaxe padrão de 5 posições (`*/5 * * * *`) ou intervalo em segundos com distributed leader locking e execução garantida.
|
|
51
|
+
- **🛡️ Resiliência, DLQ & Backpressure**: Retentativas com exponential backoff, Dead Letter Queue (DLQ) com inspeção de stacktrace e *One-Click Replay*. Circuit breaker de CPU e Memória RSS por worker.
|
|
52
|
+
- **📊 Observabilidade LGTM Nativa**:
|
|
53
|
+
- **📈 Mimir / Prometheus**: KPIs em tempo real (Taxa de Sucesso %, Duração Média ms, Latência P95 ms, Throughput/min).
|
|
54
|
+
- **📜 Loki**: Console de logs de execução, erros e tracebacks capturados.
|
|
55
|
+
- **⏱️ Tempo**: Linha do tempo em cascata (Enqueued ➔ Dequeued ➔ Executing ➔ Finished/Failed).
|
|
56
|
+
- **🎨 Design System Linear Dark**: Interface minimalista com atalho global **`Ctrl+K` (Command Palette)**, menu de ação unificado **`+ Criar ▾`**, e realce suave de linhas.
|
|
57
|
+
- **🔌 Plug-and-Play em Qualquer Framework**: Use como aplicação independente ou embarque facilmente dentro do seu projeto **FastAPI**, **Django** ou **Flask**.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 📦 Como Usar o TaskManager no seu Projeto (Biblioteca / Framework)
|
|
62
|
+
|
|
63
|
+
Você pode adicionar o TaskManager ao seu projeto Python existente de 3 maneiras:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Instalar no seu projeto:
|
|
67
|
+
pip install taskmanager
|
|
68
|
+
# ou usando UV:
|
|
69
|
+
uv add taskmanager
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### Método 1: Embutir no FastAPI / Starlette (Sub-Aplicação / Mount)
|
|
75
|
+
|
|
76
|
+
Monte o dashboard e os endpoints do TaskManager diretamente dentro da sua aplicação FastAPI existente:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# main.py
|
|
80
|
+
from fastapi import FastAPI
|
|
81
|
+
from taskmanager import TaskManager, task
|
|
82
|
+
|
|
83
|
+
# 1. Cria sua aplicação principal
|
|
84
|
+
app = FastAPI(title="Minha API Principal")
|
|
85
|
+
|
|
86
|
+
# 2. Configura a instância do TaskManager apontando para o Redis
|
|
87
|
+
tm = TaskManager(redis_url="redis://localhost:6379/0", prefix="meu_app")
|
|
88
|
+
|
|
89
|
+
# 3. Define tarefas usando o decorator @task
|
|
90
|
+
@task(name="emails.enviar_boas_vindas", queue="emails", max_retries=3)
|
|
91
|
+
async def enviar_boas_vindas(email: str, nome: str):
|
|
92
|
+
print(f"Enviando e-mail para {nome} <{email}>...")
|
|
93
|
+
return {"status": "enviado"}
|
|
94
|
+
|
|
95
|
+
# 4. Monta o dashboard do TaskManager sob a rota /tasks
|
|
96
|
+
tm.mount_to(app, path="/tasks")
|
|
97
|
+
|
|
98
|
+
@app.post("/cadastro")
|
|
99
|
+
async def cadastrar_usuario(email: str, nome: str):
|
|
100
|
+
# Enfileira o job em background
|
|
101
|
+
job = await enviar_boas_vindas.delay(email=email, nome=nome)
|
|
102
|
+
return {"mensagem": "Usuário cadastrado!", "job_id": job.id}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
*Ao acessar `http://localhost:8000/tasks/`, o dashboard completo estará rodando dentro da sua própria aplicação!*
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### Método 2: Integração com Django (`taskmanager.contrib.django`)
|
|
110
|
+
|
|
111
|
+
O TaskManager possui integração de primeira classe com o ecossistema Django:
|
|
112
|
+
|
|
113
|
+
1. Adicione `'taskmanager.contrib.django'` ao seu `INSTALLED_APPS` em `settings.py`:
|
|
114
|
+
```python
|
|
115
|
+
# settings.py
|
|
116
|
+
INSTALLED_APPS = [
|
|
117
|
+
"django.contrib.admin",
|
|
118
|
+
"django.contrib.auth",
|
|
119
|
+
...,
|
|
120
|
+
"taskmanager.contrib.django", # <- Adicione aqui
|
|
121
|
+
"meu_app_vendas",
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
# Configurações opcionais do Redis
|
|
125
|
+
TASKMANAGER_REDIS_URL = "redis://localhost:6379/0"
|
|
126
|
+
TASKMANAGER_REDIS_PREFIX = "django_app"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
2. Crie um arquivo `tasks.py` dentro dos seus apps Django:
|
|
130
|
+
```python
|
|
131
|
+
# meu_app_vendas/tasks.py
|
|
132
|
+
from taskmanager import task
|
|
133
|
+
|
|
134
|
+
@task(name="vendas.gerar_fatura", queue="faturamento", max_retries=2)
|
|
135
|
+
async def gerar_fatura(pedido_id: int):
|
|
136
|
+
# O taskmanager.contrib.django descobre e carrega automaticamente
|
|
137
|
+
# todos os módulos tasks.py de todos os apps em INSTALLED_APPS!
|
|
138
|
+
...
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
3. Adicione as URLs no seu `urls.py`:
|
|
142
|
+
```python
|
|
143
|
+
# urls.py
|
|
144
|
+
from django.urls import path, include
|
|
145
|
+
|
|
146
|
+
urlpatterns = [
|
|
147
|
+
path("admin/", admin.site.urls),
|
|
148
|
+
path("tasks/", include("taskmanager.contrib.django.urls")), # <- Dashboard
|
|
149
|
+
]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
4. Execute workers e schedulers nativamente com `manage.py`:
|
|
153
|
+
```bash
|
|
154
|
+
# Iniciar worker consumindo as filas do Django:
|
|
155
|
+
python manage.py run_worker --queues faturamento,default --concurrency 5
|
|
156
|
+
|
|
157
|
+
# Iniciar o scheduler de rotinas cron:
|
|
158
|
+
python manage.py run_scheduler
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### Método 3: Modo Standalone / CLI (Sidecar Desacoplado)
|
|
164
|
+
|
|
165
|
+
Se preferir manter o TaskManager como um serviço separado (sidecar):
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Modo Dev (Dashboard + Worker + Scheduler apontando para seus módulos de tarefas):
|
|
169
|
+
taskmanager dev --modules meu_projeto.tasks --port 8000
|
|
170
|
+
|
|
171
|
+
# Processos isolados para Produção:
|
|
172
|
+
taskmanager worker --modules meu_projeto.tasks --queues emails,default -c 8
|
|
173
|
+
taskmanager scheduler --modules meu_projeto.tasks
|
|
174
|
+
taskmanager server --port 8080
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 📂 Pasta de Exemplos Práticos (`samples/`)
|
|
180
|
+
|
|
181
|
+
O repositório inclui projetos de exemplo completos e prontos para rodar:
|
|
182
|
+
|
|
183
|
+
| Exemplo | Descrição | Como Executar |
|
|
184
|
+
| :--- | :--- | :--- |
|
|
185
|
+
| [📁 samples/fastapi_sample](samples/fastapi_sample) | API FastAPI completa montando o TaskManager em `/tasks/` com endpoints de checkout e e-mail. | `uv run python -m samples.fastapi_sample.main` |
|
|
186
|
+
| [📁 samples/django_sample](samples/django_sample) | Projeto Django configurado com `taskmanager.contrib.django`, `tasks.py` e comandos `manage.py`. | `python samples/django_sample/manage.py run_worker` |
|
|
187
|
+
| [📁 samples/standalone_cli](samples/standalone_cli) | Demonstração de uso puro via linha de comando desacoplada. | `uv run taskmanager dev --modules samples.standalone_cli.tasks` |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 🛠️ Como Compilar e Publicar a Biblioteca (PyPI)
|
|
192
|
+
|
|
193
|
+
Para gerar os pacotes `.whl` (Wheel) e `.tar.gz` (Source Distribution) com todos os arquivos de UI embutidos:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# 1. Compilar os artefatos de distribuição
|
|
197
|
+
uv build
|
|
198
|
+
# (ou via python -m build)
|
|
199
|
+
|
|
200
|
+
# 2. Testar instalação local em modo editável
|
|
201
|
+
pip install -e .
|
|
202
|
+
|
|
203
|
+
# 3. Publicar no PyPI
|
|
204
|
+
uv publish --token <SEU_TOKEN_PYPI>
|
|
205
|
+
# (ou twine upload dist/*)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 📸 Galeria de Telas do Dashboard
|
|
211
|
+
|
|
212
|
+
### 1. Visão Geral & Métricas em Tempo Real
|
|
213
|
+
Acompanhe o estado de todas as filas, consumo de hardware dos workers e log de eventos ao vivo via WebSockets.
|
|
214
|
+
<img src="docs/images/01_dashboard_overview.png" alt="Visão Geral" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### 2. Menu Unificado `+ Criar ▾` & Paleta de Comandos (`Ctrl+K`)
|
|
219
|
+
Navegue e execute qualquer ação em milissegundos sem tirar as mãos do teclado.
|
|
220
|
+
<div align="center">
|
|
221
|
+
<img src="docs/images/08_quick_create_menu.png" alt="Menu Criar" width="48%" style="border-radius: 8px; border: 1px solid #23252a; margin-right: 2%;" />
|
|
222
|
+
<img src="docs/images/07_command_palette.png" alt="Command Palette Ctrl+K" width="48%" style="border-radius: 8px; border: 1px solid #23252a;" />
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### 3. Gerenciamento de Workers & Proteção de Recursos
|
|
228
|
+
Monitore o uso de CPU/RAM de cada worker individual e pause ou interrompa processos com um clique.
|
|
229
|
+
<img src="docs/images/02_workers_management.png" alt="Gerenciamento de Workers" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
### 4. Agendamentos Cron & Rotinas Periódicas
|
|
234
|
+
Crie e edite agendamentos em tempo real sem precisar reiniciar os serviços ou fazer deploy.
|
|
235
|
+
<img src="docs/images/04_cron_schedules.png" alt="Agendamentos Cron" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### 5. Dead Letter Queue (DLQ) & Inspeção de Falhas
|
|
240
|
+
Monitore jobs que esgotaram retentativas, visualize o stacktrace completo e faça o replay imediato para a fila.
|
|
241
|
+
<img src="docs/images/05_dlq_inspector.png" alt="Dead Letter Queue" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
### 6. Observabilidade & Trace Waterfall (LGTM Stack)
|
|
246
|
+
Inspecione a linha do tempo exata de execução de cada tarefa com logs capturados e payloads serializados.
|
|
247
|
+
<img src="docs/images/06_observability_trace.png" alt="Observabilidade e Tracing" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 🐳 Stack Docker & Docker Compose
|
|
252
|
+
|
|
253
|
+
Suba o cluster completo em contêineres com um único comando:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# Iniciar todos os serviços com Redis AOF persistente
|
|
257
|
+
docker compose up --build -d
|
|
258
|
+
|
|
259
|
+
# Visualizar status e healthchecks
|
|
260
|
+
docker compose ps
|
|
261
|
+
|
|
262
|
+
# Escalar workers dinamicamente
|
|
263
|
+
docker compose up -d --scale worker-emails=3
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 🧪 Testes & Qualidade
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Executar suíte completa de testes
|
|
272
|
+
uv run pytest -v tests/
|
|
273
|
+
|
|
274
|
+
# Executar linter de código
|
|
275
|
+
uv run ruff check taskmanager tests samples
|
|
276
|
+
|
|
277
|
+
# Sensor de Spec Drift (SDD)
|
|
278
|
+
node .agents/scripts/check-spec-drift.js
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## 📄 Licença
|
|
284
|
+
Distribuído sob a licença [MIT](LICENSE). Pronto para uso individual ou corporativo.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# TaskManager ⚡
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
**Engine moderna de execução e gerenciamento de background tasks em Python inspirada no Celery e BullMQ.**
|
|
13
|
+
*Agendador Cron Dinâmico • Observabilidade LGTM Completa • Dead Letter Queue Multi-Fila • Telemetria com Backpressure • Dashboard SPA Linear Dark.*
|
|
14
|
+
|
|
15
|
+
<br/>
|
|
16
|
+
|
|
17
|
+
<img src="docs/images/01_dashboard_overview.png" alt="TaskManager Dashboard Overview" width="100%" style="border-radius: 12px; border: 1px solid #23252a; box-shadow: 0 20px 40px rgba(0,0,0,0.6);" />
|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 🌟 Principais Destaques
|
|
24
|
+
|
|
25
|
+
- **🚀 Asyncio & Sync Worker Runtime**: Suporte nativo e transparente para corrotinas assíncronas (`async def`) e funções síncronas (`def`), com concorrência ajustável e timeouts granulares.
|
|
26
|
+
- **📦 Redis Broker com Durabilidade AOF**: Sem brokers pesados. Utiliza listas atômicas do Redis (`LPOP`/`BLPOP`), conjuntos ordenados para jobs agendados e histórico, e persistência AOF para garantia de *Zero Data Loss*.
|
|
27
|
+
- **🧠 Fallback In-Memory Automático**: Modo de desenvolvimento zero-dependência (`fakeredis`) quando o Redis local não estiver em execução.
|
|
28
|
+
- **✨ Decorator `@task` & Introspecção**: Enfileiramento via `.delay(*args, **kwargs)` ou `.apply_async(...)` com geração automática de schemas e payload no painel.
|
|
29
|
+
- **⏰ Agendador Cron & Intervalos em Tempo Real**: Sintaxe padrão de 5 posições (`*/5 * * * *`) ou intervalo em segundos com distributed leader locking e execução garantida.
|
|
30
|
+
- **🛡️ Resiliência, DLQ & Backpressure**: Retentativas com exponential backoff, Dead Letter Queue (DLQ) com inspeção de stacktrace e *One-Click Replay*. Circuit breaker de CPU e Memória RSS por worker.
|
|
31
|
+
- **📊 Observabilidade LGTM Nativa**:
|
|
32
|
+
- **📈 Mimir / Prometheus**: KPIs em tempo real (Taxa de Sucesso %, Duração Média ms, Latência P95 ms, Throughput/min).
|
|
33
|
+
- **📜 Loki**: Console de logs de execução, erros e tracebacks capturados.
|
|
34
|
+
- **⏱️ Tempo**: Linha do tempo em cascata (Enqueued ➔ Dequeued ➔ Executing ➔ Finished/Failed).
|
|
35
|
+
- **🎨 Design System Linear Dark**: Interface minimalista com atalho global **`Ctrl+K` (Command Palette)**, menu de ação unificado **`+ Criar ▾`**, e realce suave de linhas.
|
|
36
|
+
- **🔌 Plug-and-Play em Qualquer Framework**: Use como aplicação independente ou embarque facilmente dentro do seu projeto **FastAPI**, **Django** ou **Flask**.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 📦 Como Usar o TaskManager no seu Projeto (Biblioteca / Framework)
|
|
41
|
+
|
|
42
|
+
Você pode adicionar o TaskManager ao seu projeto Python existente de 3 maneiras:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Instalar no seu projeto:
|
|
46
|
+
pip install taskmanager
|
|
47
|
+
# ou usando UV:
|
|
48
|
+
uv add taskmanager
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### Método 1: Embutir no FastAPI / Starlette (Sub-Aplicação / Mount)
|
|
54
|
+
|
|
55
|
+
Monte o dashboard e os endpoints do TaskManager diretamente dentro da sua aplicação FastAPI existente:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
# main.py
|
|
59
|
+
from fastapi import FastAPI
|
|
60
|
+
from taskmanager import TaskManager, task
|
|
61
|
+
|
|
62
|
+
# 1. Cria sua aplicação principal
|
|
63
|
+
app = FastAPI(title="Minha API Principal")
|
|
64
|
+
|
|
65
|
+
# 2. Configura a instância do TaskManager apontando para o Redis
|
|
66
|
+
tm = TaskManager(redis_url="redis://localhost:6379/0", prefix="meu_app")
|
|
67
|
+
|
|
68
|
+
# 3. Define tarefas usando o decorator @task
|
|
69
|
+
@task(name="emails.enviar_boas_vindas", queue="emails", max_retries=3)
|
|
70
|
+
async def enviar_boas_vindas(email: str, nome: str):
|
|
71
|
+
print(f"Enviando e-mail para {nome} <{email}>...")
|
|
72
|
+
return {"status": "enviado"}
|
|
73
|
+
|
|
74
|
+
# 4. Monta o dashboard do TaskManager sob a rota /tasks
|
|
75
|
+
tm.mount_to(app, path="/tasks")
|
|
76
|
+
|
|
77
|
+
@app.post("/cadastro")
|
|
78
|
+
async def cadastrar_usuario(email: str, nome: str):
|
|
79
|
+
# Enfileira o job em background
|
|
80
|
+
job = await enviar_boas_vindas.delay(email=email, nome=nome)
|
|
81
|
+
return {"mensagem": "Usuário cadastrado!", "job_id": job.id}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
*Ao acessar `http://localhost:8000/tasks/`, o dashboard completo estará rodando dentro da sua própria aplicação!*
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### Método 2: Integração com Django (`taskmanager.contrib.django`)
|
|
89
|
+
|
|
90
|
+
O TaskManager possui integração de primeira classe com o ecossistema Django:
|
|
91
|
+
|
|
92
|
+
1. Adicione `'taskmanager.contrib.django'` ao seu `INSTALLED_APPS` em `settings.py`:
|
|
93
|
+
```python
|
|
94
|
+
# settings.py
|
|
95
|
+
INSTALLED_APPS = [
|
|
96
|
+
"django.contrib.admin",
|
|
97
|
+
"django.contrib.auth",
|
|
98
|
+
...,
|
|
99
|
+
"taskmanager.contrib.django", # <- Adicione aqui
|
|
100
|
+
"meu_app_vendas",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
# Configurações opcionais do Redis
|
|
104
|
+
TASKMANAGER_REDIS_URL = "redis://localhost:6379/0"
|
|
105
|
+
TASKMANAGER_REDIS_PREFIX = "django_app"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
2. Crie um arquivo `tasks.py` dentro dos seus apps Django:
|
|
109
|
+
```python
|
|
110
|
+
# meu_app_vendas/tasks.py
|
|
111
|
+
from taskmanager import task
|
|
112
|
+
|
|
113
|
+
@task(name="vendas.gerar_fatura", queue="faturamento", max_retries=2)
|
|
114
|
+
async def gerar_fatura(pedido_id: int):
|
|
115
|
+
# O taskmanager.contrib.django descobre e carrega automaticamente
|
|
116
|
+
# todos os módulos tasks.py de todos os apps em INSTALLED_APPS!
|
|
117
|
+
...
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
3. Adicione as URLs no seu `urls.py`:
|
|
121
|
+
```python
|
|
122
|
+
# urls.py
|
|
123
|
+
from django.urls import path, include
|
|
124
|
+
|
|
125
|
+
urlpatterns = [
|
|
126
|
+
path("admin/", admin.site.urls),
|
|
127
|
+
path("tasks/", include("taskmanager.contrib.django.urls")), # <- Dashboard
|
|
128
|
+
]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
4. Execute workers e schedulers nativamente com `manage.py`:
|
|
132
|
+
```bash
|
|
133
|
+
# Iniciar worker consumindo as filas do Django:
|
|
134
|
+
python manage.py run_worker --queues faturamento,default --concurrency 5
|
|
135
|
+
|
|
136
|
+
# Iniciar o scheduler de rotinas cron:
|
|
137
|
+
python manage.py run_scheduler
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### Método 3: Modo Standalone / CLI (Sidecar Desacoplado)
|
|
143
|
+
|
|
144
|
+
Se preferir manter o TaskManager como um serviço separado (sidecar):
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Modo Dev (Dashboard + Worker + Scheduler apontando para seus módulos de tarefas):
|
|
148
|
+
taskmanager dev --modules meu_projeto.tasks --port 8000
|
|
149
|
+
|
|
150
|
+
# Processos isolados para Produção:
|
|
151
|
+
taskmanager worker --modules meu_projeto.tasks --queues emails,default -c 8
|
|
152
|
+
taskmanager scheduler --modules meu_projeto.tasks
|
|
153
|
+
taskmanager server --port 8080
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 📂 Pasta de Exemplos Práticos (`samples/`)
|
|
159
|
+
|
|
160
|
+
O repositório inclui projetos de exemplo completos e prontos para rodar:
|
|
161
|
+
|
|
162
|
+
| Exemplo | Descrição | Como Executar |
|
|
163
|
+
| :--- | :--- | :--- |
|
|
164
|
+
| [📁 samples/fastapi_sample](samples/fastapi_sample) | API FastAPI completa montando o TaskManager em `/tasks/` com endpoints de checkout e e-mail. | `uv run python -m samples.fastapi_sample.main` |
|
|
165
|
+
| [📁 samples/django_sample](samples/django_sample) | Projeto Django configurado com `taskmanager.contrib.django`, `tasks.py` e comandos `manage.py`. | `python samples/django_sample/manage.py run_worker` |
|
|
166
|
+
| [📁 samples/standalone_cli](samples/standalone_cli) | Demonstração de uso puro via linha de comando desacoplada. | `uv run taskmanager dev --modules samples.standalone_cli.tasks` |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 🛠️ Como Compilar e Publicar a Biblioteca (PyPI)
|
|
171
|
+
|
|
172
|
+
Para gerar os pacotes `.whl` (Wheel) e `.tar.gz` (Source Distribution) com todos os arquivos de UI embutidos:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# 1. Compilar os artefatos de distribuição
|
|
176
|
+
uv build
|
|
177
|
+
# (ou via python -m build)
|
|
178
|
+
|
|
179
|
+
# 2. Testar instalação local em modo editável
|
|
180
|
+
pip install -e .
|
|
181
|
+
|
|
182
|
+
# 3. Publicar no PyPI
|
|
183
|
+
uv publish --token <SEU_TOKEN_PYPI>
|
|
184
|
+
# (ou twine upload dist/*)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 📸 Galeria de Telas do Dashboard
|
|
190
|
+
|
|
191
|
+
### 1. Visão Geral & Métricas em Tempo Real
|
|
192
|
+
Acompanhe o estado de todas as filas, consumo de hardware dos workers e log de eventos ao vivo via WebSockets.
|
|
193
|
+
<img src="docs/images/01_dashboard_overview.png" alt="Visão Geral" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### 2. Menu Unificado `+ Criar ▾` & Paleta de Comandos (`Ctrl+K`)
|
|
198
|
+
Navegue e execute qualquer ação em milissegundos sem tirar as mãos do teclado.
|
|
199
|
+
<div align="center">
|
|
200
|
+
<img src="docs/images/08_quick_create_menu.png" alt="Menu Criar" width="48%" style="border-radius: 8px; border: 1px solid #23252a; margin-right: 2%;" />
|
|
201
|
+
<img src="docs/images/07_command_palette.png" alt="Command Palette Ctrl+K" width="48%" style="border-radius: 8px; border: 1px solid #23252a;" />
|
|
202
|
+
</div>
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### 3. Gerenciamento de Workers & Proteção de Recursos
|
|
207
|
+
Monitore o uso de CPU/RAM de cada worker individual e pause ou interrompa processos com um clique.
|
|
208
|
+
<img src="docs/images/02_workers_management.png" alt="Gerenciamento de Workers" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### 4. Agendamentos Cron & Rotinas Periódicas
|
|
213
|
+
Crie e edite agendamentos em tempo real sem precisar reiniciar os serviços ou fazer deploy.
|
|
214
|
+
<img src="docs/images/04_cron_schedules.png" alt="Agendamentos Cron" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### 5. Dead Letter Queue (DLQ) & Inspeção de Falhas
|
|
219
|
+
Monitore jobs que esgotaram retentativas, visualize o stacktrace completo e faça o replay imediato para a fila.
|
|
220
|
+
<img src="docs/images/05_dlq_inspector.png" alt="Dead Letter Queue" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### 6. Observabilidade & Trace Waterfall (LGTM Stack)
|
|
225
|
+
Inspecione a linha do tempo exata de execução de cada tarefa com logs capturados e payloads serializados.
|
|
226
|
+
<img src="docs/images/06_observability_trace.png" alt="Observabilidade e Tracing" width="100%" style="border-radius: 8px; border: 1px solid #23252a; margin-bottom: 24px;" />
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 🐳 Stack Docker & Docker Compose
|
|
231
|
+
|
|
232
|
+
Suba o cluster completo em contêineres com um único comando:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Iniciar todos os serviços com Redis AOF persistente
|
|
236
|
+
docker compose up --build -d
|
|
237
|
+
|
|
238
|
+
# Visualizar status e healthchecks
|
|
239
|
+
docker compose ps
|
|
240
|
+
|
|
241
|
+
# Escalar workers dinamicamente
|
|
242
|
+
docker compose up -d --scale worker-emails=3
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## 🧪 Testes & Qualidade
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Executar suíte completa de testes
|
|
251
|
+
uv run pytest -v tests/
|
|
252
|
+
|
|
253
|
+
# Executar linter de código
|
|
254
|
+
uv run ruff check taskmanager tests samples
|
|
255
|
+
|
|
256
|
+
# Sensor de Spec Drift (SDD)
|
|
257
|
+
node .agents/scripts/check-spec-drift.js
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 📄 Licença
|
|
263
|
+
Distribuído sob a licença [MIT](LICENSE). Pronto para uso individual ou corporativo.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "taskmanager-engine"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "High-performance background task execution engine with dynamic cron scheduling and Linear-themed SPA dashboard"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"fastapi>=0.110.0",
|
|
9
|
+
"uvicorn[standard]>=0.28.0",
|
|
10
|
+
"redis[hiredis]>=5.0.0",
|
|
11
|
+
"pydantic>=2.6.0",
|
|
12
|
+
"croniter>=2.0.0",
|
|
13
|
+
"psutil>=5.9.0",
|
|
14
|
+
"fakeredis>=2.21.0",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
dev = [
|
|
19
|
+
"pytest>=8.0.0",
|
|
20
|
+
"pytest-asyncio>=0.23.0",
|
|
21
|
+
"fakeredis>=2.21.0",
|
|
22
|
+
"ruff>=0.3.0",
|
|
23
|
+
"httpx>=0.27.0",
|
|
24
|
+
"websockets>=12.0",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
taskmanager = "taskmanager.cli:main"
|
|
29
|
+
|
|
30
|
+
[build-system]
|
|
31
|
+
requires = ["setuptools>=61.0"]
|
|
32
|
+
build-backend = "setuptools.build_meta"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
include = ["taskmanager*"]
|
|
36
|
+
|
|
37
|
+
[tool.setuptools.package-data]
|
|
38
|
+
"taskmanager.ui" = ["*.html", "*.css", "*.js", "*.svg", "*.ico", "*.png"]
|
|
39
|
+
|
|
40
|
+
[tool.pytest.ini_options]
|
|
41
|
+
asyncio_mode = "auto"
|
|
42
|
+
testpaths = ["tests"]
|
|
43
|
+
|
|
44
|
+
[tool.ruff]
|
|
45
|
+
line-length = 100
|
|
46
|
+
target-version = "py311"
|
|
47
|
+
|
|
48
|
+
[tool.ruff.lint]
|
|
49
|
+
select = ["E", "F", "W", "I"]
|
|
50
|
+
ignore = ["E501"]
|