Coordinación del chat service con Firestore y Gemini usando mocks
Clase 16 de 21 • Curso de Firebase con Angular 20
Resumen
Un flujo de chat sólido se construye con un chat service que orquesta Firestore y Gemini, controla observables y aplica mocks para avanzar sin bloquear el desarrollo. Aquí se explica cómo inicializar el historial, enviar mensajes con UI optimista, manejar el estado de asistente respondiendo y persistir datos, incluso ante errores.
¿Cómo se organiza el chat service y qué servicios coordina?
El núcleo coordina tres piezas: el service de chat, Firestore y Gemini. Mientras se implementan Firestore Service y Gemini Service reales, se usan Firestore Service Mock y Gemini Service Mock para simular lectura y escritura de mensajes. También se apoya en un auth service ya implementado para identificar al usuario actual.
- Observables clave: mensajes y asistente respondiendo. Activan cambios en la vista cuando su estado cambia.
- Carga de historial: un booleano evita inicializaciones duplicadas mientras se obtiene el historial.
- Inicialización: intenta leer mensajes del usuario en Firestore; si no está implementado o hay error, coloca un array vacío en el observable de mensajes para iniciar la vista.
¿Qué roles cumplen los mocks y por qué?
Los mocks permiten que el flujo complete de chat funcione antes de las integraciones reales.
- Firestore Service Mock: lee y guarda mensajes como lo haría Firestore real.
- Gemini Service Mock: genera una “respuesta del asistente” con el mismo modelo que luego usará Gemini.
- Beneficio: desarrollo incremental sin bloquear por dependencias externas.
¿Qué estados y tipos manejan los mensajes?
Cada mensaje se mapea a un modelo consistente.
- tipo: usuario o asistente.
- estado: enviando para el mensaje del usuario, enviado para el mensaje final y para la respuesta del asistente.
- fecha: new Date al crear el mensaje.
- contenido: texto con espacios recortados.
- usuarioId: ID o UUID del usuario actual, según el modelo.
¿Cómo se envía un mensaje y se actualiza la UI?
El service gestiona validaciones, UI optimista, guardado y respuesta del asistente.
- Verificación de usuario actual: si falta, lanza error.
- Validación de contenido: si está vacío, no se envía.
- Mapeo del mensaje: tipo usuario, estado enviando, fecha actual, contenido recortado, ID de usuario.
- UI optimista: se inserta el mensaje en el observable de mensajes sin esperar al backend.
- Guardado en Firestore: se inicia el guardado; con mock hasta implementar el real.
- Asistente respondiendo: se marca en el observable para que la vista lo muestre.
- Preparación de historial: se toma el historial actual y se envía a Gemini; con mock hasta integrar el servicio real.
- Respuesta del asistente: tipo asistente, estado enviado, fecha actual y contenido moqueado.
- Persistencia: tras mostrar la respuesta en pantalla, se guarda también en Firestore.
- Manejo de errores con catch: captura y guarda un mensaje de error en Firebase, además de notificar en la UI.
- Finalización: asistente respondiendo vuelve a false para permitir nuevos envíos.
// Mapeo del mensaje del usuario
const mensaje = {
tipo: 'usuario',
estado: 'enviando',
fecha: new Date(),
contenido: contenido.trim(),
usuarioId: usuarioActual.id,
};
// UI optimista
mensajes$.next([...mensajes$.value, mensaje]);
asistenteRespondiendo$.next(true);
try {
// Guardar en Firestore o mock
await firestore.save(mensaje);
// Preparar historial y pedir respuesta a Gemini o mock
const respuestaGemini = await gemini.reply(historialActualizado);
const respuesta = {
tipo: 'asistente',
estado: 'enviado',
fecha: new Date(),
contenido: respuestaGemini,
usuarioId: usuarioActual.uuid,
};
mensajes$.next([...mensajes$.value, respuesta]);
await firestore.save(respuesta);
} catch (err) {
const errorMsg = { tipo: 'asistente', estado: 'enviado', fecha: new Date(), contenido: 'Error al obtener respuesta.', usuarioId: usuarioActual.id };
mensajes$.next([...mensajes$.value, errorMsg]);
await firestore.save(errorMsg);
} finally {
asistenteRespondiendo$.next(false);
}
¿Qué integrar en el componente y qué métodos expone el servicio?
En el archivo TS del component, se descomentan y activan las líneas que conectan el chat service con la vista: inicialización, suscripciones, envío y limpieza del chat.
- Inicialización: llama a la función que carga historial desde Firestore o mock.
- Suscripciones: una a mensajes y otra al agente; se agregan al arreglo de suscripciones del component.
- Enviar mensaje: utiliza el método del service descrito arriba.
- Limpiar chat: borra el contenido del observable asignando un array vacío.
¿Qué suscripciones y observables son clave?
El component escucha cambios para reflejarlos en pantalla.
- mensajes: emite el array de mensajes en cada cambio.
- asistente respondiendo: controla indicadores de estado en la vista.
¿Qué utilidades adicionales ofrece el chat service?
Facilitan control de estado y retorno a autenticación.
- obtener mensajes: retorna el valor actual del observable de mensajes.
- limpiar el chat: asigna array vacío para reestablecer la conversación.
- chat listo: devuelve un booleano según el usuario logueado y un indicador interno de geminiConfigurado; permite limpiar y volver a auth mientras se implementa Gemini.
¿Te gustaría que se añadan ejemplos con Firestore Service y Gemini Service reales cuando estén listos? Deja tus preguntas y comentarios.