Documentación/Guía de autoría de drivers
Guía de autoría de drivers
Usa esta guía para elegir e implementar una integración de driver de base de datos de DBFlux. Cubre el camino del contribuidor sin repetir las referencias más amplias de arquitectura o protocolo RPC.
Elegir un camino de integración
| Elige | Driver Rust integrado | Driver RPC externo |
|---|---|---|
| Mejor opción cuando | El driver debe distribuirse dentro del workspace y proceso de DBFlux | El driver debe ejecutarse fuera de proceso o desarrollarse y desplegarse de forma independiente |
| Implementación | Un crate crates/dbflux_driver_<name>/ que implementa los contratos Rust del core | Un servicio que implementa el protocolo RPC de drivers |
| Registro | Wiring de features en tiempo de compilación y AppState::build_builtin_drivers() | Settings -> RPC Services con kind=driver y un socket_id |
| Clave estable | builtin:<name> | rpc:<socket_id> |
| Configuración | DriverFormDef propio del driver convertido a una variante DbConfig integrada | Datos de formulario provistos por el handshake y almacenados como DbConfig::External |
Driver integrado: camino feliz
- Copia la estructura del crate
crates/dbflux_driver_*/existente más cercano. - Implementa
DbDriveryConnection, incluyendo metadata, conversión de form/config, comportamiento de conexión, errores y columnas de resultado tipadas. - Declara solo las capacidades respaldadas por implementaciones funcionales; añade seams opcionales únicamente cuando el driver los soporte.
- Conecta el crate y el feature a través del workspace, la app y el binario,
y luego regístralo en
build_builtin_drivers(). - Añade tests focalizados, un README del crate y actualiza la matriz de soporte de drivers.
El checklist detallado del driver integrado desarrolla cada paso.
Driver RPC externo: camino feliz
- Implementa el Protocolo RPC de drivers canónico, usando el ejemplo de driver personalizado como punto de partida.
- Construye y ejecuta el servicio, ya sea de forma independiente o con un comando gestionado.
- Añádelo en Settings -> RPC Services con
kind=driver, unsocket_idestable y el comando gestionado opcional. - Reinicia DBFlux y verifica que la metadata y el formulario provistos por el handshake aparezcan en el connection manager.
Consulta la referencia de configuración de RPC Services para el comportamiento de configuración vigente. No copies flags de lanzamiento de esta guía; el protocolo, la referencia de configuración y el ejemplo son las fuentes autoritativas.
Contratos principales y regla de desacoplamiento
El contrato principal es DbDriver más Connection:
DbDriverprovee la metadata del driver, su definición de formulario de conexión, la construcción y extracción de config, la construcción de la conexión y unaDriverKeyestable.Connectionprovee el comportamiento en tiempo de ejecución de query, schema, mutation y el comportamiento específico de capacidad opcional. Existen defaults para muchas operaciones no soportadas; los métodos requeridos y las capacidades anunciadas deben seguir siendo consistentes entre sí.- Los valores
driver_key()integrados usanbuiltin:<name>. Los drivers externos usanrpc:<socket_id>.
La metadata y la adaptación se definen mediante
DriverMetadata, DatabaseCategory, QueryLanguage y DriverCapabilities,
incluyendo metadata genérica de presentación de editor. El comportamiento de
fuente y presentación en tiempo de ejecución se expone mediante seams
genéricos en Connection en traits.rs.
Regla estricta: el código de la UI y del workflow de la app no debe ramificarse por driver ID concreto. Adapta a partir de metadata, category, query language, flags de capacidad, definiciones de formulario y seams genéricos de fuente/presentación. Si una nueva distinción de UI es necesaria, añade un contrato genérico del core que otro driver también pudiera implementar.
Para los datos de resultado, completa
ColumnMeta.kind con ColumnKind.
Los charts y otros consumidores usan este kind semántico; no lo infieren de
un driver ID ni de type_name.
Checklist de driver integrado
1. Crate y contratos
- Añade
crates/dbflux_driver_<name>/Cargo.toml,src/lib.rs, los módulos de implementación y los tests. Sigue el driver más cercano en lugar de asumir que todos los drivers tienen módulos idénticos. - Implementa
DbDrivery unaConnectionthread-safe desdecrates/dbflux_core/src/core/traits.rs. - Devuelve una
DriverKeyestable con la formabuiltin:<name>. - Mantén los tipos de cliente de base de datos y el comportamiento específico del driver dentro del crate del driver; expón el comportamiento a través de los contratos del core.
2. Metadata y capacidades
- Define un
DriverMetadatafactual: identidad, campos de display,DatabaseCategory,QueryLanguage,DriverCapabilities, defaults de conexión y las estructuras de capacidad genéricas aplicables. - Usa la metadata y los seams genéricos de presentación/fuente para la adaptación de la UI. No añadas condicionales de driver ID a la UI ni a los workflows de la app.
- Anuncia una capacidad solo cuando la operación o el seam opcional correspondiente funcione. Confirma tanto las afirmaciones negativas como el comportamiento soportado.
3. Formularios y configuración
- Define y posee el
DriverFormDefdel crate; la UI de conexión lo renderiza de forma genérica. - Implementa la validación de
build_config()y los round trips de edición deextract_values(). - Mantén los secretos en los paths de secretos establecidos en lugar de embeberlos en los valores de formulario persistidos.
- Implementa el parseo/construcción de URI o los overrides de campos de export solo cuando aplique.
4. Conexiones, errores y resultados
- Construye y prueba la conexión a través de los métodos de
DbDriver, incluyendo el manejo de secretos requerido y los tests de conexión. - Implementa formateo estructurado de errores de query y conexión
mediante
QueryErrorFormatteryConnectionErrorFormatter. Preserva el contexto útil de la base de datos sin exponer secretos. - Devuelve datos de schema y query a través de tipos del core, incluyendo
ColumnMeta.kindpara cada columna de resultado usando elColumnKindcorrecto. - Prueba el mapeo de tipos directamente. No dependas de que los
consumidores deriven la semántica a partir de cadenas
type_nameen crudo.
5. Seams opcionales
Implementa estos únicamente cuando la base de datos los soporte, y mantén los flags de capacidad sincronizados con la implementación:
- Un
LanguageServiceno-default para validación específica del lenguaje y clasificación de mutations. - Comportamiento de dialecto SQL, generador de código, generador de queries o semantic planner según aplique.
- Comportamiento de contexto de fuente, catálogo de métricas, importador de dashboards o fuente de dashboards según aplique.
- Un catálogo de instancia para métricas o inspectors según aplique.
- Otros seams de schema, CRUD, cancelación, transfer o key-value representados por los traits del core y los flags de capacidad.
6. Wiring de features y registro
- Añade membresía de workspace y una dependencia de workspace en el
Cargo.tomlraíz. - Añade una dependencia opcional y un relay de feature en
crates/dbflux_app/Cargo.toml. - Reenvía el feature del binario en
crates/dbflux/Cargo.toml. - Añade imports y registro con feature gate en
AppState::build_builtin_drivers(). - Verifica tanto el build con el feature habilitado como uno representativo con el feature deshabilitado para que el registro se mantenga correctamente controlado por el gate.
7. Tests y documentación
- Prueba metadata, declaraciones de capacidad, round trips de form/config, errores, comportamiento de conexión, mapeo de schema, resultados de query y cada seam opcional anunciado.
- Añade tests de integración donde el comportamiento cruce el límite driver/core; mantén los tests de servicio en vivo ignorados o controlados por gate según las convenciones existentes del crate.
- Añade
crates/dbflux_driver_<name>/README.mdcon secciones claras de Features y Limitations. - Actualiza Drivers y mantén sus afirmaciones de capacidad alineadas con el README del crate y la implementación.
Checklist de driver RPC externo
- Implementa handshake, form, session, query y las operaciones opcionales soportadas frente al Protocolo RPC de drivers.
- Provee metadata, capabilities y la definición de formulario a través del handshake del protocolo; mantén cada afirmación de capacidad alineada con las operaciones RPC implementadas.
- Configura el servicio bajo Settings -> RPC Services como
kind=drivercon unsocket_idestable; añade un comando gestionado solo cuando DBFlux deba controlar el ciclo de vida del proceso. - Espera la clave de runtime
rpc:<socket_id>y el almacenamiento de configuración genérico a través deDbConfig::External. - Sigue RPC Services Config para la configuración persistida y la semántica del ciclo de vida.
- Construye y haz smoke-test desde el ejemplo de driver personalizado, y luego prueba reinicio, fallo de handshake, operaciones no soportadas y round trips del formulario de conexión.
Los drivers RPC externos no usan el wiring de features de Cargo integrado ni
el path de registro de build_builtin_drivers().
Checklist de revisión
Antes de abrir un PR, confirma:
- El camino integrado o RPC seleccionado se usa de forma consistente; los dos paths de registro no se mezclan.
- Ninguna ramificación de la UI ni del workflow de la app depende de un driver ID concreto.
- La metadata, los flags de capacidad, los seams opcionales, los tests, el README del crate y Drivers afirman lo mismo.
- Los round trips de edición de form/config funcionan y los secretos no se persisten ni se registran de forma inesperada.
- Los resultados de query completan
ColumnMeta.kindcorrectamente. - Los fallos de conexión y query producen errores estructurados, útiles y seguros respecto a los secretos.
- Los builds con el feature integrado deshabilitado y habilitado pasan, o el servicio RPC completa su handshake y el smoke test de reinicio.
- Los checks del repositorio en Contributing pasan.