Tots els articles

Gestors de canal i marketplaces: el problema d'integració que ningú t'explica

Publicat 10 d’oct. del 20253 min de lectura
  • Enginyeria
  • Lueira
Gestors de canal i marketplaces: el problema d'integració que ningú t'explica

Idees clau

  • La feina real d'un gestor de canal és absorbir el ritme de webhooks, els límits de polling i els modes de fallada de cada marketplace sense que es filtrin al calendari d'una escola.
  • Tracta el teu propi motor de disponibilitat com l'única font de veritat; cada connexió amb un marketplace hauria de ser una capa de sincronització, no un igual.
  • Els webhooks arriben duplicats, desordenats o no arriben mai — cada reserva entrant necessita un ID extern estable per fer dedupe, a més d'una política clara per quan el doble booking encara passa.

Cada post anterior d'aquesta sèrie donava per fet una cosa que ja no puc donar per feta: que controlem tot el sistema. El post sobre el motor de reserves tractava de reservar una plaça sense competir amb tu mateix. El post sobre disponibilitat en temps real tractava de mantenir els números consistents a cada pantalla que un client pogués estar mirant. El post sobre multi-tenancy tractava d'aïllar escoles que comparteixen infraestructura. Tot això viu dins dels límits propis de Lueira — la nostra base de dades, la nostra API, les nostres regles.

Els gestors de canal no tenen aquest luxe. Lueira permet que una escola connecti les seves activitats a marketplaces d'activitats de tercers "de forma rápida y eficiente" — com diu literalment la descripció de la funcionalitat al web — de manera que l'inventari d'una escola d'esquí aparegui a la venda en una plataforma externa, no només al seu propi storefront de Lueira. Aquesta frase és senzilla. El que implica per sota, no ho és.

1. El que promet de veritat un gestor de canal

El discurs cap a una escola és directe: connecta un cop, ven a tot arreu. Les teves cinc places de classe d'esquí de dimarts al matí són les mateixes cinc places, tant si un client reserva a través de la teva pròpia web com a través d'un marketplace que agrega activitats d'una dotzena d'operadors de la vall. Perquè aquesta promesa es mantingui, Lueira ha de parlar amb l'API de cada marketplace, traduir el nostre model intern d'activitats, places i preus a la forma que esperi aquell marketplace, i mantenir les dues bandes honestes sobre quantes places queden realment. Aquest és el 20% fàcil de la funcionalitat — un adaptador per marketplace. El 80% difícil és el que passa després de la primera sincronització, a cada canvi a partir d'aleshores.

2. Disponibilitat que no controles

El problema de disponibilitat en temps real que vam resoldre abans donava per fet una única font de veritat: la nostra pròpia base de dades, les nostres pròpies escriptures, els nostres propis locks. Un gestor de canal trenca aquesta suposició a propòsit. Ara, les fonts de veritat que importen per a la reserva d'un client inclouen sistemes que no gestionem en absolut.

Cada marketplace és diferent. Alguns envien webhooks en l'instant en què alguna cosa canvia al seu costat; d'altres esperen que fem polling, limitat pels seus rate limits. Uns actualitzen gairebé a l'instant; d'altres encuen canvis durant pics de càrrega. I cadascun falla de manera diferent: una API que senzillament està caiguda durant una hora, una subscripció de webhook que deixa d'entregar en silenci, un marketplace que confirma una petició i després mai arriba a aplicar-la.

3. Gestionar el doble booking que encara passa

Una reserva feta en un marketplace extern ha de reduir la disponibilitat a tots els altres llocs — el propi storefront de Lueira i qualsevol altre marketplace connectat — pràcticament a l'instant. No podem simplement consultar el nostre propi estat en viu, perquè l'estat que acaba de canviar viu als servidors d'algú altre. Hi ha una finestra en què els nostres números estan desactualitzats a tot arreu excepte al marketplace que acaba de vendre la plaça.

func handleMarketplaceBooking(w http.ResponseWriter, r *http.Request) {
    var evt MarketplaceBookingEvent
    if err := json.NewDecoder(r.Body).Decode(&evt); err != nil {
        http.Error(w, "bad payload", http.StatusBadRequest)
        return
    }

    // Cada reserva de marketplace porta un ID extern. Aquesta és la
    // nostra clau de dedupe — els webhooks poden arribar duplicats,
    // desordenats, o després que ja haguem recollit la mateixa reserva via polling.
    if existing, _ := store.FindByExternalRef(evt.MarketplaceID, evt.ExternalBookingID); existing != nil {
        w.WriteHeader(http.StatusOK) // ja processat, confirmem i seguim
        return
    }

    slot, err := availability.Reserve(evt.ActivityID, evt.SlotID, evt.Spots)
    if err != nil {
        // Algú altre ja s'ha quedat la plaça. Aquest és el flux de disculpa.
        notifyOversell(evt)
        w.WriteHeader(http.StatusConflict)
        return
    }

    store.RecordExternalBooking(evt.MarketplaceID, evt.ExternalBookingID, slot)
    channels.PushAvailabilityUpdate(evt.ActivityID, slot) // propaga a cada altre canal
    w.WriteHeader(http.StatusOK)
}

Quan aquesta branca de conflicte salta de veritat, el client d'algú rep un missatge de disculpa, un reemborsament i, si és possible, una plaça alternativa. No hem trobat la manera de fer aquesta branca impossible — només maneres de fer-la rara i de gestionar-la amb elegància en lloc de en silenci.

4. Mantenir la font de veritat en un sol lloc

La decisió de disseny que evita que això es converteixi en un caos és negar-se a tractar els marketplaces externs com igualment autoritatius. El propi motor de disponibilitat de Lueira segueix sent l'única font de veritat. Cada integració de canal és una capa de sincronització a sobre, no un igual.

A sobre d'això necessitàvem també una capa de reconciliació, perquè els webhooks no són un mecanisme d'entrega fiable — arriben duplicats, desordenats, o no arriben mai. Cada notificació de reserva entrant necessita un ID extern estable amb què fer dedupe, més tasques de reconciliació periòdiques que comparin la nostra visió amb la del marketplace.

Hem estat honestos amb nosaltres mateixos que això no tanca la bretxa del tot. Un doble booking encara passa de tant en tant. El que vam construir no és una garantia que no pugui passar — és una política de què passa quan passa. Els gestors de canal són, per sota del llenguatge de màrqueting, un problema de sistemes distribuïts disfressat d'indústria del viatge.