621e8895c9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
3.9 KiB
Markdown
80 lines
3.9 KiB
Markdown
---
|
|
name: matrix_sync_service
|
|
kind: function
|
|
lang: go
|
|
domain: infra
|
|
version: "0.1.0"
|
|
purity: impure
|
|
signature: "func MatrixSyncService(ctx context.Context, cfg MatrixSyncServiceConfig) (*MatrixSyncServiceHandle, error)"
|
|
description: "Arranca el sync loop de mautrix contra Synapse en background con backoff exponencial, emite eventos Matrix normalizados via canal Go y expone funcion de stop idempotente."
|
|
tags: [matrix, mautrix, sync, longpoll, reconnect, goroutine, channels, infra, matrix-mas]
|
|
params:
|
|
- name: ctx
|
|
desc: "Context padre. Si se cancela, la goroutine sale limpiamente y cierra los channels."
|
|
- name: cfg.Client
|
|
desc: "*mautrix.Client ya inicializado con credenciales (HomeserverURL, AccessToken, UserID). Usar matrix_client_init para crearlo. Obligatorio."
|
|
- name: cfg.InitialBackoffMS
|
|
desc: "Milisegundos de espera inicial entre reintentos tras error de sync. Default: 1000 (1s)."
|
|
- name: cfg.MaxBackoffMS
|
|
desc: "Techo del backoff exponencial en ms. Default: 60000 (60s)."
|
|
- name: cfg.ChannelBuffer
|
|
desc: "Capacidad del buffer del canal Events. Si el consumer va lento y el buffer se llena, el sync se bloquea hasta que el consumer drene. Default: 256."
|
|
output: "*MatrixSyncServiceHandle con Events <-chan MatrixSyncEvent (canal de eventos normalizados), Errors <-chan error (errores transitorios no fatales), Stop func() (cancela y cierra todo, idempotente)."
|
|
uses_functions: []
|
|
uses_types: []
|
|
returns: []
|
|
returns_optional: false
|
|
error_type: "error_go_core"
|
|
imports:
|
|
- "maunium.net/go/mautrix"
|
|
- "maunium.net/go/mautrix/event"
|
|
- "maunium.net/go/mautrix/id"
|
|
tested: true
|
|
tests:
|
|
- "RecibeMensajeYStop"
|
|
- "BackoffRecovery"
|
|
- "Error401NoExit"
|
|
- "StopIdempotente"
|
|
- "CtxCancelCierraChannels"
|
|
test_file_path: "functions/infra/matrix_sync_service_test.go"
|
|
file_path: "functions/infra/matrix_sync_service.go"
|
|
---
|
|
|
|
## Ejemplo
|
|
|
|
```go
|
|
ctx := context.Background()
|
|
h, err := MatrixSyncService(ctx, MatrixSyncServiceConfig{
|
|
Client: client, // *mautrix.Client de matrix_client_init
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer h.Stop()
|
|
|
|
// Consumir errores transitorios en goroutine separada
|
|
go func() {
|
|
for e := range h.Errors {
|
|
log.Println("matrix sync error:", e)
|
|
}
|
|
}()
|
|
|
|
// Loop de eventos (bloquea hasta que h.Stop() se llame o ctx sea cancelado)
|
|
for ev := range h.Events {
|
|
fmt.Printf("[%s] %s: %s\n", ev.Type, ev.Sender, ev.Body)
|
|
}
|
|
```
|
|
|
|
## Cuando usarla
|
|
|
|
Usar despues de `MatrixClientInit` (y opcionalmente `MatrixCryptoInit`) para recibir el stream de eventos de Matrix en tiempo real. Es el servicio long-running central de cualquier cliente Matrix: matrix_client_pc, admin_panel, bots, monitores. Un solo `MatrixSyncService` por client, durante toda la vida de la aplicacion.
|
|
|
|
## Gotchas
|
|
|
|
- **Solo UN Sync por client**: dos goroutines llamando `SyncWithContext` simultaneamente sobre el mismo client rompe el `since` token y produce duplicados o perdidas. Esta funcion garantiza una sola goroutine de sync si es llamada una sola vez. NO llamar `MatrixSyncService` dos veces sobre el mismo `*mautrix.Client`.
|
|
- **Crypto antes del Sync**: mensajes `m.room.encrypted` que llegan antes de inicializar `MatrixCryptoInit` quedan sin descifrar (emitidos con `Type:"encrypted"`, `Body:""`, `Raw:*event.Event`). Inicializar crypto siempre ANTES de llamar a esta funcion.
|
|
- **Buffer de channel**: si el consumer no drena `Events` con suficiente rapidez, el sync se bloquea en el punto de emision. Synapse puede acumular deltas. Mantener el consumer rapido o aumentar `ChannelBuffer`.
|
|
- **Errores fatales (401/M_UNKNOWN_TOKEN)**: no cierran el servicio automaticamente — se emiten a `Errors` y el servicio espera con backoff maximo. El caller decide llamar `Stop()` y re-autenticar.
|
|
- **Stop idempotente**: llamar `Stop()` multiples veces es seguro; no causa panic.
|
|
- **Build tag**: el paquete `infra` requiere `-tags goolm` para compilar tests sin libolm (dependencia C de la crypto de mautrix). Los tests usan `//go:build goolm`.
|