Skip to main content
El Fetcher Engine no es dueño de ninguna infraestructura. Llega al mundo exterior solo a través de puertos — interfaces Go que tu aplicación anfitriona implementa y pasa a engine.New. Esta página es la referencia de los ocho. La columna Sin él es el punto central de la página. La degradación controlada es el contrato con el que planificas, así que léela antes de omitir un puerto.

Los puertos de un vistazo


engine.New rechaza un puerto pasado como nil tipado, no solo como nil literal. Un valor de interfaz que envuelve un puntero nil falla en la construcción con un error de validación claro, en lugar de entrar en pánico en el primer uso.

ConnectorRegistry


Obligatorio: siempre. Es el único puerto que el Engine valida sin condiciones. El registro resuelve una factory de conector por tipo de datasource. No hace E/S, resuelve de forma determinista por tipo y reporta ok=false para un tipo que nadie registró. Construir y conectar un conector ocurre después, a través de la factory que devolvió. Sin él: engine.New devuelve un error de validación con el mensaje connector registry is required. No obtienes ningún valor de Engine, así que la extracción es imposible.

CredentialProtector


Obligatorio: solo con WithEncryptedPersistence(true). El protector cifra y descifra material de credenciales para un tenant. La llamada Protect devuelve los bytes protegidos más la versión de clave que los protegió. La llamada Reveal descifra con una versión de clave dada, así que tu host puede resolver una clave rotada. Tu host es dueño de la derivación, la rotación y el almacenamiento de claves. El Engine solo llama al punto de extensión y registra la versión de clave devuelta como metadato libre de secretos. Sin él:
  • Con la persistencia cifrada activa, engine.New falla con credential protector is required when encrypted persistence is enabled. El Engine se niega a construirse antes que persistir credenciales en texto plano.
  • Con la persistencia cifrada inactiva, el puerto es genuinamente opcional, y las credenciales llegan al ConnectionStore sin protección.

ConnectionStore


Obligatorio: opcional en la construcción, imprescindible en tiempo de ejecución. El almacén persiste y resuelve descriptores de conexión que pertenecen a un tenant. Es el único punto de persistencia que usan las operaciones de conexión — el Engine no embebe MongoDB, ni SQL, ni ningún repositorio del host. Expone nueve operaciones: crear, buscar, buscar-por-id, actualizar, actualizar-por-id, borrar, borrar-por-id, listar y listar-paginado. Tu implementación carga con dos obligaciones. Debe limitar cada registro por el tenant ID, para que un tenant nunca vea las conexiones de otro. No debe devolver material secreto — el descriptor de conexión no lleva ninguno. Sin él: engine.New tiene éxito, y luego casi todo falla. Toda operación que toca una conexión devuelve el error de validación connection store is not configured. Eso cubre las nueve operaciones de conexión más planificar, ejecutar, descubrir esquema, descubrimiento de esquema fresco, validar esquema y probar conexión. Un Engine sin almacén de conexiones solo puede reportar sus límites.
No leas ConnectionStore como una comodidad limitada al CRUD. Omitirlo también desactiva la extracción y el descubrimiento de esquemas.

ExecutionStore


Obligatorio: opcional. El almacén hace upsert del estado del ciclo de vida de una ejecución para un tenant. El Engine escribe las transiciones de forma síncrona e inline: running, y luego completed, failed o canceled. Esas escrituras son best-effort por diseño. El Engine descarta un error de guardado, así que una persistencia opcional nunca puede corromper un resultado de extracción. Un fallo de escritura en el result sink se comporta distinto y sí hace fallar la ejecución. Los dos son deliberadamente distintos. Sin él: el Engine corre sin seguimiento durable de ejecuciones, y tu host es dueño del estado de ejecución por fuera.

ResultSink


Obligatorio: opcional. Selecciona el modo de resultado. El sink persiste payloads de resultado en el storage que gestiona el host. La extracción en modo Store llama a OpenResultStream, así que el Engine escribe el resultado de forma incremental, en memoria constante. PersistResult sigue disponible para escrituras del payload completo. La forma del stream es NDJSON contractual — un objeto JSON por línea, terminada en salto de línea, sin array que lo envuelva:
Las líneas salen en orden determinista: los pasos por ordinal ascendente del plan, y las filas dentro de un paso en orden de cursor. Por eso la misma entrada produce un NDJSON idéntico byte a byte y el mismo digest SHA-256 en cada corrida. Ante un aborto — un error de escritura, un límite de tamaño superado o un contexto cancelado — el Engine abandona el escritor y nunca llama a Close. Trata un escritor sin cerrar como una escritura descartada, porque un resultado parcial nunca debe convertirse en una referencia devuelta. Sin él: el modo Store no está disponible. El modo auto por defecto se resuelve a Direct, así que la extracción devuelve bytes inline y no persiste nada. Una petición explícita de modo Store falla de entrada con store mode requires a configured result sink, antes de que el Engine construya ningún conector.

SchemaCache


Obligatorio: opcional. La caché guarda y devuelve snapshots de esquema por tenant y por nombre de configuración. El Engine la trata como un acelerador, nunca como fuente de verdad. Una lectura de caché fallida degrada a descubrimiento fresco. Una escritura de caché fallida igual devuelve al llamador el esquema descubierto. La llamada de descubrimiento siempre-fresco ignora la caché en cada invocación, incluso cuando conectaste una, para que se mantenga el contrato de datasource en vivo del endpoint de esquemas del Manager. Sin él: el Engine descubre el esquema en vivo desde el datasource en cada llamada.

ActiveExecutionChecker


Obligatorio: opcional. El verificador reporta si una conexión tiene ejecuciones activas en este momento. El Engine lo consulta antes de mutar una conexión. Así un host puede mantener el comportamiento del Manager, que bloquea un cambio mientras corren jobs contra esa conexión. El puerto es deliberadamente lógico, no un almacén durable de jobs. Tu host decide cómo responder: un repositorio de jobs, un rastreador en memoria, un lock distribuido o siempre falso. El Engine nunca importa un repositorio de jobs para hacer la pregunta. La identidad de conexión que pasa es el nombre de la configuración dentro del alcance del tenant. Tu respuesta debe estar limitada por tenant, para que el trabajo en curso de un tenant nunca bloquee la mutación de otro. Sin él: el Engine no hace control de conflictos, y las actualizaciones y los borrados de conexiones proceden sin condiciones.

Observability


Obligatorio: opcional. El contrato tiene un método. StartSpan toma un contexto y un nombre de operación, y devuelve un contexto derivado más una función de cierre que el Engine difiere. Un solo método es justamente el punto: el núcleo del Engine nunca importa una biblioteca de trazas, y tu host adapta su propio tracer detrás del punto de extensión. Sin él: la creación de spans devuelve el contexto entrante y una función de cierre no-op. Los hooks de trazas desaparecen, sin ningún otro cambio de comportamiento.

Próximos pasos


Embeber el Engine

Importa, provee los puertos y construye con un ejemplo ejecutable.

Visión general del Engine

El modelo de tres capas, la frontera de importación y los dos modos de resultado.