feat(ServiceFactory): Criação de importação de classes de forma dinâmica mais otimizada
This commit is contained in:
parent
2223db9d75
commit
433d889060
4 changed files with 86 additions and 26 deletions
64
actions/dynamic_import/service_factory.py
Normal file
64
actions/dynamic_import/service_factory.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import importlib
|
||||
import re
|
||||
from functools import lru_cache
|
||||
from typing import Type, TypeVar, Optional
|
||||
from actions.config.config import Config
|
||||
from actions.env.env_config_loader import EnvConfigLoader
|
||||
|
||||
# Genérico para garantir que o retorno respeite o Protocolo
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class ServiceFactory:
|
||||
|
||||
def __init__(self, package: str, table: str):
|
||||
|
||||
# Instancia o loader com o prefixo correto
|
||||
env = EnvConfigLoader(".env")
|
||||
|
||||
# Ex: "packages.v1"
|
||||
self.base_root = "packages.v1"
|
||||
self.package = package
|
||||
self.table = table
|
||||
|
||||
# Carrega config apenas uma vez
|
||||
self.app_config = Config.get("app.json")
|
||||
|
||||
# Define a UF da aplicação
|
||||
self.current_state = env.ORIUS_CLIENT_STATE
|
||||
|
||||
@lru_cache(maxsize=32)
|
||||
def make(self, class_name: str, interface: Type[T]) -> T:
|
||||
"""
|
||||
Instancia um serviço dinamicamente com comportamento de Autoload.
|
||||
"""
|
||||
# 1. Converte CamelCase para snake_case (Autoload style)
|
||||
# Ex: TAtoIndexService -> t_ato_index_service
|
||||
module_name = re.sub(r"(?<!^)(?=[A-Z])", "_", class_name).lower()
|
||||
|
||||
# 2. Monta o caminho completo
|
||||
# Ex: packages.v1.servicos.balcao.services.t_ato.SP.t_ato_index_service
|
||||
import_path = (
|
||||
f"{self.base_root}.{self.package}.services."
|
||||
f"{self.table}.{self.current_state}.{module_name}"
|
||||
)
|
||||
|
||||
try:
|
||||
# 3. Importação Dinâmica
|
||||
module = importlib.import_module(import_path)
|
||||
|
||||
# 4. Pega a classe do módulo
|
||||
clazz = getattr(module, class_name)
|
||||
|
||||
# 5. Retorna a INSTÂNCIA da classe (já com () )
|
||||
# Se seus serviços precisam de argumentos no __init__, altere aqui.
|
||||
return clazz()
|
||||
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
f"FATAL: Não foi possível carregar o serviço '{class_name}' para o estado '{self.current_state}'.\nCaminho tentado: {import_path}\nErro: {e}"
|
||||
)
|
||||
except AttributeError:
|
||||
raise AttributeError(
|
||||
f"FATAL: O arquivo '{module_name}.py' existe, mas a classe '{class_name}' não foi encontrada dentro dele."
|
||||
)
|
||||
10
interfaces/service_protocols.py
Normal file
10
interfaces/service_protocols.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from typing import Protocol, Any, runtime_checkable
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class ServiceProtocolsInterface(Protocol):
|
||||
"""
|
||||
Contrato que garante que todo serviço tenha um método execute.
|
||||
"""
|
||||
|
||||
def execute(self, schema: Any) -> Any: ...
|
||||
|
|
@ -1,34 +1,20 @@
|
|||
from actions.dynamic_import.dynamic_import import DynamicImport
|
||||
from packages.v1.servicos.balcao.schemas.t_ato_schema import TAtoIndexSchema
|
||||
from packages.v1.servicos.balcao.services.t_ato.t_ato_index_service import (
|
||||
TAtoIndexService,
|
||||
)
|
||||
from actions.dynamic_import.service_factory import ServiceFactory
|
||||
from interfaces.service_protocols import ServiceProtocolsInterface
|
||||
|
||||
|
||||
class TAtoController:
|
||||
"""
|
||||
Controller responsável por orquestrar as operações CRUD da tabela T_PESSOA_CARTAO,
|
||||
utilizando carregamento dinâmico de serviços via DynamicImport.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# ----------------------------------------------------
|
||||
# Inicialização do DynamicImport
|
||||
# ----------------------------------------------------
|
||||
self.dynamic_import = DynamicImport()
|
||||
self.dynamic_import.set_package("servicos.balcao")
|
||||
self.dynamic_import.set_table("t_ato")
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Lista todos os registros de T_PESSOA_CARTAO
|
||||
# ----------------------------------------------------
|
||||
def index(self, t_ato_index_schema: TAtoIndexSchema):
|
||||
# Configura o escopo deste controller
|
||||
self.factory = ServiceFactory(package="servicos.balcao", table="t_ato")
|
||||
|
||||
# Instância da classe service
|
||||
self.index_service = TAtoIndexService()
|
||||
def index(self, schema):
|
||||
|
||||
# Execução da listagem
|
||||
return {
|
||||
"message": "Registros de T_ATO localizados com sucesso.",
|
||||
"data": self.index_service.execute(t_ato_index_schema),
|
||||
}
|
||||
# Instânciamento da classe
|
||||
service = self.factory.make("TAtoIndexService", ServiceProtocolsInterface)
|
||||
|
||||
# O VS Code sabe que .execute() existe por causa do IService!
|
||||
result = service.execute(schema)
|
||||
|
||||
return {"message": "Sucesso", "data": result}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue