dataloom-engine 0.3.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 [Dioni Padilha]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,196 @@
1
+ Metadata-Version: 2.4
2
+ Name: dataloom-engine
3
+ Version: 0.3.0
4
+ Summary: DataLoom: Um orquestrador de threads leve e eficiente para dados.
5
+ Author-email: Dioni Padilha <dionipdl@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dionipadilha/dataloom
8
+ Project-URL: Changelog, https://github.com/dionipadilha/dataloom/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/dionipadilha/dataloom/issues
10
+ Keywords: pipeline,data,threading,loom,concurrency
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: numpy>=1.21.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
+ Requires-Dist: ruff>=0.4; extra == "dev"
30
+ Requires-Dist: mypy>=1.8; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # 🧵 DataLoom
34
+
35
+ > Um motor de orquestração multi-thread leve, eficiente e seguro para Python.
36
+
37
+ [![CI](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml/badge.svg)](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml) ![Python](https://img.shields.io/badge/python-3.9%2B-blue) ![License](https://img.shields.io/badge/license-MIT-green)
38
+
39
+ <img width="2752" height="1536" alt="DataLoom: Um motor de orquestração multi-thread leve, eficiente e seguro para Python." src="https://github.com/user-attachments/assets/c1f3fc98-5eaf-4add-a38c-2717ae699cd5" />
40
+
41
+ O **DataLoom** é uma biblioteca projetada para processar fluxos de dados utilizando o padrão **Produtor-Consumidor** com múltiplas threads (Weavers). Ele abstrai a complexidade de filas (`Queues`), sincronização (`Locks`) e gerenciamento de ciclo de vida, permitindo que você foque apenas na lógica de transformação dos dados.
42
+
43
+ ## Por que usar o DataLoom?
44
+ ⚡ Performance: Processamento paralelo real para tarefas I/O bound.
45
+ 🧩 Simplicidade: API intuitiva inspirada na metáfora de tecelagem.
46
+ 🛡️ Segurança: Thread-safety garantido por design em todo o pipeline.
47
+ 📦 Leve: Dependências mínimas, pronto para rodar em qualquer ambiente Python.
48
+
49
+ ### Por que não usar só `ThreadPoolExecutor`?
50
+
51
+ Pergunta justa — a stdlib resolve o *paralelismo*, mas não o *pipeline*. O
52
+ `concurrent.futures` te dá um pool de threads; tudo ao redor fica por sua conta:
53
+
54
+ | Você precisa de... | Com a stdlib | Com o DataLoom |
55
+ | --------------------------------------------------- | ------------------------ | --------------------------------- |
56
+ | Fluxo contínuo produtor-consumidor | `Queue` + loops manuais | `Loom` + `Source` |
57
+ | Backpressure (produtor mais rápido que consumidores) | `Queue(maxsize=...)` manual | Padrão, configurável |
58
+ | Shutdown limpo (drenar fila, fechar recursos) | Sentinelas e joins manuais | `stop()` / `with Loom(...)` |
59
+ | Worker que sobrevive a erros e os reporta | try/except em cada worker | `hooks.on_error` centralizado |
60
+ | Métricas por item processado | Instrumentação manual | `hooks.on_batch_processed` |
61
+ | Escrita concorrente segura em arquivo | Lock manual | Sinks prontos (JSON, CSV, callback) |
62
+
63
+ Se o seu caso é "aplicar uma função a uma lista e coletar os resultados",
64
+ use `ThreadPoolExecutor.map` — é a ferramenta certa. O DataLoom é para
65
+ **fluxos contínuos ou longos** onde ciclo de vida, resiliência e
66
+ observabilidade importam. E, como toda solução baseada em threads no
67
+ CPython, o ganho de paralelismo vale para cargas **I/O bound**; para
68
+ CPU bound, prefira multiprocessing.
69
+
70
+ ## ✨ Características
71
+
72
+ - **API Coesa:** Conceitos alinhados (`Loom`, `Weaver`, `Sink`).
73
+ - **Concorrente:** Gerencia automaticamente múltiplos _Weavers_ (threads) em paralelo.
74
+ - **Seguro:** Sinks padrão são thread-safe e exceções são tipadas (`LoomError`).
75
+ - **Resiliente:** Erros de processamento não derrubam os Weavers e são reportados via hooks.
76
+ - **Gerenciável:** `Loom` é um context manager — `with Loom(...) as loom:` garante `stop()` automático.
77
+ - **Backpressure:** Fila de tarefas limitada por padrão (`queue_maxsize`), evitando crescimento de memória sem controle.
78
+ - **Observável:** Hooks de ciclo de vida e métricas por lote (`on_batch_processed` com resultado e duração), além de Logs integrados.
79
+
80
+ ## 📦 Instalação
81
+
82
+ ```bash
83
+ pip install dataloom-engine
84
+ ```
85
+
86
+ > ⚠️ **Atenção ao nome:** o pacote instala o módulo `dataloom_engine`
87
+ > (`import dataloom_engine`). Não confunda com o pacote `dataloom` do PyPI,
88
+ > que é um ORM de outro autor e não tem relação com este projeto.
89
+
90
+ Para desenvolver ou usar a versão mais recente do repositório:
91
+
92
+ ```bash
93
+ git clone https://github.com/dionipadilha/dataloom.git
94
+ cd dataloom
95
+ pip install -e .
96
+ ```
97
+
98
+ ## 🚀 Uso Rápido
99
+
100
+ Aqui está um exemplo completo de como tecer um pipeline de dados:
101
+
102
+ ```python
103
+ from pathlib import Path
104
+ import numpy as np
105
+ from dataloom_engine import (
106
+ Loom,
107
+ LoomConfig,
108
+ LoomLogs,
109
+ Processor,
110
+ JsonFileSink,
111
+ ThreadedBufferedSink
112
+ )
113
+ from dataloom_engine.sources import RandomNumPySource
114
+
115
+ # 1. Defina sua lógica de processamento (Stateless)
116
+ class MyFilterProcessor(Processor):
117
+ def process(self, batch: np.ndarray) -> dict:
118
+ # 'batch' é um array numpy com o tamanho definido na config
119
+ avg = float(batch.mean())
120
+ return {
121
+ "processed_items": len(batch),
122
+ "average_value": avg,
123
+ "status": "high" if avg > 0.5 else "low"
124
+ }
125
+
126
+ # 2. Configuração Inicial
127
+ if __name__ == "__main__":
128
+ # Configura logs no console
129
+ LoomLogs.setup()
130
+
131
+ # Define parâmetros do motor
132
+ config = LoomConfig(
133
+ output_dir=Path("./data_out"),
134
+ batch_size=100, # Processa 100 itens por vez
135
+ interval_seconds=1 # Gera um novo lote a cada 1 segundo
136
+ )
137
+
138
+ # 3. Fonte de Dados
139
+ # Agora desvinculada do motor, permitindo fontes customizadas (DB, CSV, S3)
140
+ source = RandomNumPySource(config)
141
+
142
+ # 4. Sink Arquivado e Otimizado
143
+ # ThreadedBufferedSink evita que o I/O bloqueie o processamento
144
+ file_sink = JsonFileSink(config.output_dir)
145
+ sink = ThreadedBufferedSink(file_sink)
146
+
147
+ # 5. Inicializa o Loom (O Orquestrador)
148
+ loom = Loom(
149
+ config=config,
150
+ processor=MyFilterProcessor(),
151
+ sink=sink,
152
+ source=source,
153
+ num_weavers=4 # 4 Threads trabalhando em paralelo
154
+ )
155
+
156
+ print("🧵 DataLoom iniciado! Pressione Ctrl+C para parar.")
157
+ try:
158
+ # O context manager garante stop() e limpeza dos recursos,
159
+ # mesmo em caso de exceção ou Ctrl+C
160
+ with loom:
161
+ loom.start()
162
+ except KeyboardInterrupt:
163
+ print("\n🛑 Tear parado.")
164
+ ```
165
+
166
+ ## 🏗️ Arquitetura
167
+
168
+ O DataLoom utiliza uma metáfora de tecelagem:
169
+
170
+ - **Loom (Tear):** A máquina principal. Gerencia a fila de tarefas e o ciclo de vida.
171
+ - **Weaver (Tecelão):** As threads trabalhadoras. Elas pegam a matéria-prima (batch), processam e entregam.
172
+ - **Processor:** A lógica de negócio. Transforma dados brutos em informação.
173
+ - **Sink:** O destino final. Onde o produto acabado é depositado (ex: `JsonFileSink`, `CsvFileSink`, ou qualquer destino via `CallbackSink`).
174
+
175
+ ## 🛠️ Desenvolvimento e Testes
176
+
177
+ Para contribuir com o projeto ou rodar os testes unitários:
178
+
179
+ 1. Instale as dependências de desenvolvimento:
180
+
181
+ ```bash
182
+ pip install -e ".[dev]"
183
+ ```
184
+
185
+ 2. Rode a suíte de testes (via pytest):
186
+ ```bash
187
+ pytest
188
+ ```
189
+
190
+ ## 📄 Licença
191
+
192
+ Este projeto está licenciado sob a licença MIT - veja o arquivo [LICENSE](LICENSE) para detalhes.
193
+
194
+ ## 🗒️ Histórico de versões
195
+
196
+ As mudanças de cada versão estão documentadas no [CHANGELOG](CHANGELOG.md).
@@ -0,0 +1,164 @@
1
+ # 🧵 DataLoom
2
+
3
+ > Um motor de orquestração multi-thread leve, eficiente e seguro para Python.
4
+
5
+ [![CI](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml/badge.svg)](https://github.com/dionipadilha/dataloom/actions/workflows/ci.yml) ![Python](https://img.shields.io/badge/python-3.9%2B-blue) ![License](https://img.shields.io/badge/license-MIT-green)
6
+
7
+ <img width="2752" height="1536" alt="DataLoom: Um motor de orquestração multi-thread leve, eficiente e seguro para Python." src="https://github.com/user-attachments/assets/c1f3fc98-5eaf-4add-a38c-2717ae699cd5" />
8
+
9
+ O **DataLoom** é uma biblioteca projetada para processar fluxos de dados utilizando o padrão **Produtor-Consumidor** com múltiplas threads (Weavers). Ele abstrai a complexidade de filas (`Queues`), sincronização (`Locks`) e gerenciamento de ciclo de vida, permitindo que você foque apenas na lógica de transformação dos dados.
10
+
11
+ ## Por que usar o DataLoom?
12
+ ⚡ Performance: Processamento paralelo real para tarefas I/O bound.
13
+ 🧩 Simplicidade: API intuitiva inspirada na metáfora de tecelagem.
14
+ 🛡️ Segurança: Thread-safety garantido por design em todo o pipeline.
15
+ 📦 Leve: Dependências mínimas, pronto para rodar em qualquer ambiente Python.
16
+
17
+ ### Por que não usar só `ThreadPoolExecutor`?
18
+
19
+ Pergunta justa — a stdlib resolve o *paralelismo*, mas não o *pipeline*. O
20
+ `concurrent.futures` te dá um pool de threads; tudo ao redor fica por sua conta:
21
+
22
+ | Você precisa de... | Com a stdlib | Com o DataLoom |
23
+ | --------------------------------------------------- | ------------------------ | --------------------------------- |
24
+ | Fluxo contínuo produtor-consumidor | `Queue` + loops manuais | `Loom` + `Source` |
25
+ | Backpressure (produtor mais rápido que consumidores) | `Queue(maxsize=...)` manual | Padrão, configurável |
26
+ | Shutdown limpo (drenar fila, fechar recursos) | Sentinelas e joins manuais | `stop()` / `with Loom(...)` |
27
+ | Worker que sobrevive a erros e os reporta | try/except em cada worker | `hooks.on_error` centralizado |
28
+ | Métricas por item processado | Instrumentação manual | `hooks.on_batch_processed` |
29
+ | Escrita concorrente segura em arquivo | Lock manual | Sinks prontos (JSON, CSV, callback) |
30
+
31
+ Se o seu caso é "aplicar uma função a uma lista e coletar os resultados",
32
+ use `ThreadPoolExecutor.map` — é a ferramenta certa. O DataLoom é para
33
+ **fluxos contínuos ou longos** onde ciclo de vida, resiliência e
34
+ observabilidade importam. E, como toda solução baseada em threads no
35
+ CPython, o ganho de paralelismo vale para cargas **I/O bound**; para
36
+ CPU bound, prefira multiprocessing.
37
+
38
+ ## ✨ Características
39
+
40
+ - **API Coesa:** Conceitos alinhados (`Loom`, `Weaver`, `Sink`).
41
+ - **Concorrente:** Gerencia automaticamente múltiplos _Weavers_ (threads) em paralelo.
42
+ - **Seguro:** Sinks padrão são thread-safe e exceções são tipadas (`LoomError`).
43
+ - **Resiliente:** Erros de processamento não derrubam os Weavers e são reportados via hooks.
44
+ - **Gerenciável:** `Loom` é um context manager — `with Loom(...) as loom:` garante `stop()` automático.
45
+ - **Backpressure:** Fila de tarefas limitada por padrão (`queue_maxsize`), evitando crescimento de memória sem controle.
46
+ - **Observável:** Hooks de ciclo de vida e métricas por lote (`on_batch_processed` com resultado e duração), além de Logs integrados.
47
+
48
+ ## 📦 Instalação
49
+
50
+ ```bash
51
+ pip install dataloom-engine
52
+ ```
53
+
54
+ > ⚠️ **Atenção ao nome:** o pacote instala o módulo `dataloom_engine`
55
+ > (`import dataloom_engine`). Não confunda com o pacote `dataloom` do PyPI,
56
+ > que é um ORM de outro autor e não tem relação com este projeto.
57
+
58
+ Para desenvolver ou usar a versão mais recente do repositório:
59
+
60
+ ```bash
61
+ git clone https://github.com/dionipadilha/dataloom.git
62
+ cd dataloom
63
+ pip install -e .
64
+ ```
65
+
66
+ ## 🚀 Uso Rápido
67
+
68
+ Aqui está um exemplo completo de como tecer um pipeline de dados:
69
+
70
+ ```python
71
+ from pathlib import Path
72
+ import numpy as np
73
+ from dataloom_engine import (
74
+ Loom,
75
+ LoomConfig,
76
+ LoomLogs,
77
+ Processor,
78
+ JsonFileSink,
79
+ ThreadedBufferedSink
80
+ )
81
+ from dataloom_engine.sources import RandomNumPySource
82
+
83
+ # 1. Defina sua lógica de processamento (Stateless)
84
+ class MyFilterProcessor(Processor):
85
+ def process(self, batch: np.ndarray) -> dict:
86
+ # 'batch' é um array numpy com o tamanho definido na config
87
+ avg = float(batch.mean())
88
+ return {
89
+ "processed_items": len(batch),
90
+ "average_value": avg,
91
+ "status": "high" if avg > 0.5 else "low"
92
+ }
93
+
94
+ # 2. Configuração Inicial
95
+ if __name__ == "__main__":
96
+ # Configura logs no console
97
+ LoomLogs.setup()
98
+
99
+ # Define parâmetros do motor
100
+ config = LoomConfig(
101
+ output_dir=Path("./data_out"),
102
+ batch_size=100, # Processa 100 itens por vez
103
+ interval_seconds=1 # Gera um novo lote a cada 1 segundo
104
+ )
105
+
106
+ # 3. Fonte de Dados
107
+ # Agora desvinculada do motor, permitindo fontes customizadas (DB, CSV, S3)
108
+ source = RandomNumPySource(config)
109
+
110
+ # 4. Sink Arquivado e Otimizado
111
+ # ThreadedBufferedSink evita que o I/O bloqueie o processamento
112
+ file_sink = JsonFileSink(config.output_dir)
113
+ sink = ThreadedBufferedSink(file_sink)
114
+
115
+ # 5. Inicializa o Loom (O Orquestrador)
116
+ loom = Loom(
117
+ config=config,
118
+ processor=MyFilterProcessor(),
119
+ sink=sink,
120
+ source=source,
121
+ num_weavers=4 # 4 Threads trabalhando em paralelo
122
+ )
123
+
124
+ print("🧵 DataLoom iniciado! Pressione Ctrl+C para parar.")
125
+ try:
126
+ # O context manager garante stop() e limpeza dos recursos,
127
+ # mesmo em caso de exceção ou Ctrl+C
128
+ with loom:
129
+ loom.start()
130
+ except KeyboardInterrupt:
131
+ print("\n🛑 Tear parado.")
132
+ ```
133
+
134
+ ## 🏗️ Arquitetura
135
+
136
+ O DataLoom utiliza uma metáfora de tecelagem:
137
+
138
+ - **Loom (Tear):** A máquina principal. Gerencia a fila de tarefas e o ciclo de vida.
139
+ - **Weaver (Tecelão):** As threads trabalhadoras. Elas pegam a matéria-prima (batch), processam e entregam.
140
+ - **Processor:** A lógica de negócio. Transforma dados brutos em informação.
141
+ - **Sink:** O destino final. Onde o produto acabado é depositado (ex: `JsonFileSink`, `CsvFileSink`, ou qualquer destino via `CallbackSink`).
142
+
143
+ ## 🛠️ Desenvolvimento e Testes
144
+
145
+ Para contribuir com o projeto ou rodar os testes unitários:
146
+
147
+ 1. Instale as dependências de desenvolvimento:
148
+
149
+ ```bash
150
+ pip install -e ".[dev]"
151
+ ```
152
+
153
+ 2. Rode a suíte de testes (via pytest):
154
+ ```bash
155
+ pytest
156
+ ```
157
+
158
+ ## 📄 Licença
159
+
160
+ Este projeto está licenciado sob a licença MIT - veja o arquivo [LICENSE](LICENSE) para detalhes.
161
+
162
+ ## 🗒️ Histórico de versões
163
+
164
+ As mudanças de cada versão estão documentadas no [CHANGELOG](CHANGELOG.md).
@@ -0,0 +1,43 @@
1
+ # dataloom_engine/__init__.py
2
+
3
+ """
4
+ DataLoom: Um motor de orquestração multi-thread leve e eficiente.
5
+
6
+ Este módulo expõe a API pública do pacote. Observe que classes internas
7
+ como 'Weaver' não são expostas propositalmente, mantendo a superfície
8
+ de uso limpa e segura para o consumidor.
9
+ """
10
+
11
+ from dataloom_engine.config import LoomConfig
12
+ from dataloom_engine.exceptions import ConfigurationError, LoomError, WeaverError
13
+ from dataloom_engine.hooks import LoomHooks
14
+ from dataloom_engine.logs import LoomLogs
15
+ from dataloom_engine.loom import Loom
16
+ from dataloom_engine.processors import Processor
17
+ from dataloom_engine.sinks import (
18
+ CallbackSink,
19
+ CsvFileSink,
20
+ JsonFileSink,
21
+ Sink,
22
+ ThreadedBufferedSink,
23
+ )
24
+ from dataloom_engine.sources import Source
25
+ from dataloom_engine.types import LoomState
26
+
27
+ __all__ = [
28
+ "Loom",
29
+ "LoomConfig",
30
+ "LoomState",
31
+ "Processor",
32
+ "Sink",
33
+ "JsonFileSink",
34
+ "CsvFileSink",
35
+ "CallbackSink",
36
+ "ThreadedBufferedSink",
37
+ "Source",
38
+ "LoomHooks",
39
+ "LoomLogs",
40
+ "LoomError",
41
+ "WeaverError",
42
+ "ConfigurationError",
43
+ ]
@@ -0,0 +1,52 @@
1
+ # dataloom_engine/config.py
2
+
3
+ """
4
+ Gerenciamento de configuração do orquestrador.
5
+ Centraliza parâmetros operacionais como diretórios e tamanhos de lote.
6
+ """
7
+
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+ from typing import Optional, Union
11
+
12
+ from dataloom_engine.exceptions import ConfigurationError
13
+
14
+
15
+ @dataclass
16
+ class LoomConfig:
17
+ """
18
+ Objeto de configuração principal do DataLoom.
19
+
20
+ Args:
21
+ output_dir (Path): Diretório base onde os Sinks padrão salvarão dados.
22
+ Strings são convertidas para Path automaticamente.
23
+ batch_size (int): Quantidade de itens gerados por ciclo de processamento.
24
+ interval_seconds (float): Intervalo de tempo entre gerações de tarefas.
25
+ queue_maxsize (Optional[int]): Capacidade máxima da fila de tarefas
26
+ (backpressure). None usa o padrão do Loom (num_weavers * 4);
27
+ 0 significa fila ilimitada.
28
+
29
+ Raises:
30
+ ConfigurationError: se algum parâmetro for inválido.
31
+ """
32
+
33
+ output_dir: Union[str, Path]
34
+ batch_size: int = 10
35
+ interval_seconds: float = 1.0
36
+ queue_maxsize: Optional[int] = None
37
+
38
+ def __post_init__(self) -> None:
39
+ self.output_dir = Path(self.output_dir)
40
+
41
+ if self.batch_size <= 0:
42
+ raise ConfigurationError(
43
+ f"batch_size deve ser maior que zero (recebido: {self.batch_size})."
44
+ )
45
+ if self.interval_seconds < 0:
46
+ raise ConfigurationError(
47
+ f"interval_seconds não pode ser negativo (recebido: {self.interval_seconds})."
48
+ )
49
+ if self.queue_maxsize is not None and self.queue_maxsize < 0:
50
+ raise ConfigurationError(
51
+ f"queue_maxsize não pode ser negativo (recebido: {self.queue_maxsize})."
52
+ )
@@ -0,0 +1,25 @@
1
+ # dataloom_engine/exceptions.py
2
+
3
+ """
4
+ Exceções personalizadas para o DataLoom.
5
+ Permite que consumidores capturem erros específicos da biblioteca
6
+ sem depender de exceções genéricas do Python.
7
+ """
8
+
9
+
10
+ class LoomError(Exception):
11
+ """Exceção base para todos os erros do DataLoom."""
12
+
13
+ pass
14
+
15
+
16
+ class ConfigurationError(LoomError):
17
+ """Lançado quando há problemas na validação do LoomConfig."""
18
+
19
+ pass
20
+
21
+
22
+ class WeaverError(LoomError):
23
+ """Lançado quando um Weaver falha de forma irrecuperável."""
24
+
25
+ pass
@@ -0,0 +1,50 @@
1
+ # dataloom_engine/hooks.py
2
+
3
+ """
4
+ Pontos de extensão para observabilidade (Hooks).
5
+ Permite injetar lógica de monitoramento sem acoplar ao core do engine.
6
+ """
7
+
8
+ from typing import Any, Dict
9
+
10
+
11
+ class LoomHooks:
12
+ """
13
+ Classe base para hooks do ciclo de vida.
14
+ Todos os métodos são opcionais e no-op por padrão: sobrescreva apenas
15
+ os pontos de interesse. (Deliberadamente não é um ABC — não há método
16
+ obrigatório a implementar.)
17
+ """
18
+
19
+ def on_start(self) -> None:
20
+ """Chamado imediatamente antes dos Weavers serem iniciados."""
21
+ pass
22
+
23
+ def on_stop(self) -> None:
24
+ """Chamado após o encerramento gracioso do orquestrador."""
25
+ pass
26
+
27
+ def on_error(self, error: Exception) -> None:
28
+ """
29
+ Chamado quando ocorre uma exceção no loop principal do Loom ou
30
+ durante o processamento de um lote em um Weaver (WeaverError).
31
+
32
+ Atenção: pode ser invocado a partir de múltiplas threads Weaver
33
+ simultaneamente — implementações devem ser thread-safe.
34
+ """
35
+ pass
36
+
37
+ def on_batch_processed(self, result: Dict[str, Any], duration_seconds: float) -> None:
38
+ """
39
+ Chamado após cada lote processado e entregue ao Sink com sucesso.
40
+
41
+ Args:
42
+ result: O dicionário produzido pelo Processor para o lote.
43
+ duration_seconds: Tempo gasto em process() + send(), medido
44
+ com relógio monotônico.
45
+
46
+ Atenção: assim como on_error, é invocado a partir das threads
47
+ Weaver — implementações devem ser thread-safe e rápidas, pois
48
+ rodam no caminho quente do pipeline.
49
+ """
50
+ pass
@@ -0,0 +1,28 @@
1
+ # dataloom_engine/logs.py
2
+
3
+ """
4
+ Utilitários de configuração de logging para o DataLoom.
5
+ Fornece um namespace estático para configuração rápida.
6
+ """
7
+
8
+ import logging
9
+
10
+
11
+ class LoomLogs:
12
+ """
13
+ Namespace utilitário para gerenciamento de logs do DataLoom.
14
+ Não deve ser instanciado, apenas usado estaticamente.
15
+ """
16
+
17
+ @staticmethod
18
+ def setup(level: int = logging.INFO) -> None:
19
+ """
20
+ Configura o logging básico para stdout.
21
+
22
+ Uso:
23
+ LoomLogs.setup(level=logging.DEBUG)
24
+ """
25
+ logging.basicConfig(
26
+ level=level,
27
+ format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
28
+ )