Metadata-Version: 2.4
Name: schedq
Version: 0.0.2
Summary: Lightweight, high-performance asynchronous task scheduling engine with no external dependencies.
Author-email: "Élcio M. Fernandes" <elciomfer@gmail.com>
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Framework :: AsyncIO
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# schedq

O **schedq** é um motor de agendamento de tarefas assíncronas em Python que foca em ser **extremamente leve, performático e independente**. Utilizando exclusivamente primitivas nativas da linguagem e estruturas de dados de alta performance, ele elimina a necessidade de infraestruturas pesadas para cenários concorrentes.

Inspirado na usabilidade moderna baseada em decoradores (como Prefect) e na eficiência matemática de baixo nível (uso de Filas de Prioridade), o schedq oferece controle total do tempo sem desperdício de CPU.

---

## Recursos Atuais (O que ele já faz)

- **Agendamento por Min-Heap:** Organização interna baseada no módulo nativo `heapq` rodando em C. O motor avalia apenas o topo da árvore (O(1)) e dorme o tempo exato até a próxima tarefa, resultando em **0% de uso de CPU** ociosa.
- **Concorrência Assíncrona:** Construído sobre o `asyncio`. Execuções demoradas são disparadas como _background tasks_, impedindo que uma tarefa lenta atrase o relógio das demais.
- **Rastreamento por IDs (Observabilidade):** Separação nativa entre **TID** (Task ID, fixo para a definição da tarefa) e **EID** (Execution ID, único para cada ciclo de execução), ideal para estruturação de logs.
- **Interface Fluida (Decoradores):** Sintaxe amigável e limpa para registro de rotinas com suporte a nomes customizados opcionais.

---

## Roadmap de Evolução (Próximos Passos)

Para transformar este motor leve em um orquestrador resiliente e pronto para ambientes críticos de produção, planejamos implementar os seguintes módulos de forma incremental:

### 1. Módulo de Persistência (Resiliência)

_Atualmente as tarefas vivem apenas na memória volátil do processo._

- **Objetivo:** Adicionar adaptadores opcionais para armazenamento de estados (ex: SQLite integrado ou Redis).
- **Recurso:** Mecanismo de **Misfire** para decidir o que fazer se o servidor reiniciar e perder a janela exata de execução de uma tarefa.

### 2. Módulo de Tolerância a Falhas (Retries & Circuit Breaker)

_Atualmente Exceptions dentro de uma task somem silenciosamente._

- **Objetivo:** Capturar erros em nível de execução sem derrubar o loop principal do motor.
- **Recurso:** Implementação de políticas de **Exponential Backoff** (tentativas automáticas com espaçamento de tempo crescente) e alertas para falhas definitivas.

### 3. Módulo de Controle de Concorrência (Limitação de Instâncias)

_Atualmente, se uma tarefa a cada 5s demorar 20s para rodar, o motor criará instâncias paralelas descontroladamente._

- **Objetivo:** Introduzir a propriedade `max_instances`.
- **Recurso:** Permitir que o motor pule (_skip_) ou enfileire o próximo disparo caso a instância anterior da mesma tarefa ainda esteja sendo executada.

### 4. Módulo de Controle Dinâmico (Gerenciamento em Runtime)

_Atualmente o motor roda em uma caixa preta após o `.start()`._

- **Objetivo:** Criar uma API programática para manipulação das tarefas em tempo real.
- **Recurso:** Métodos como `sched.pause(tid)`, `sched.resume(tid)` e `sched.trigger_now(tid)` para forçar a execução imediata ignorando o relógio.

### 5. Expressões Cron e Suporte a Fusos Horários (Timezones)

_Atualmente o motor suporta apenas intervalos relativos (`timedelta`)._

- **Objetivo:** Integração com parsers de Cron leves para agendamentos em horários humanos específicos (ex: "Toda segunda-feira às 08:00").
- **Recurso:** Tratamento nativo de Timezones para evitar desvios causados por fusos horários de servidores (UTC) ou horários de verão.

---

## Como Usar (Exemplo de Implementação)

```python
import asyncio
import datetime
from scheduler import Scheduler

sched = Scheduler()

@sched.task(interval=datetime.timedelta(seconds=4), name="Task name")
async def example(tid: str, eid: str, name: str):
    # Logic here
    await asyncio.sleep(1)

async def main():
    await sched.start()

if __name__ == "__main__":
    asyncio.run(main())
```

---

## Diretrizes de Design

1. **Zero Bloqueio:** Nenhuma função síncrona ou método (`time.sleep`) deve interceptar o loop principal.
2. **Dependência Opcional:** Recursos mais pesados (como bancos de dados para persistência) devem ser plugáveis e opcionais para manter o core do motor sempre leve.
3. **Foco na Developer Experience (DX):** A complexidade matemática e de concorrência deve sempre ficar escondida sob os panos do motor.
