clickSomo

Embuts i disparadors

Un embut és un graf. Una execució és una fila. Una espera és un temps.

Aquest és tot el model, i cada propietat difícil que té aquest producte surt d'aquestes tres frases. Editar un embut en marxa és segur gràcies a elles. Un reintent no pot enviar-ho dues vegades gràcies a elles. Una persona que dona de baixa dimarts no rep res dijous gràcies a elles.

Què passa realment quan s'executa

Publicar un embut escriu una versió immutable. Algú hi entra, i apareix una fila: una execució, per a aquest contacte, fixada a aquella versió, que conté el node actual, un moment de despertar i el seu propi context.

Un worker lloga les execucions el moment de despertar de les quals ha passat, les reclama amb SKIP LOCKED perquè dos workers no puguin agafar la mateixa. Executa nodes fins que arriba a una espera o a un node terminal, després escriu el següent moment de despertar i deixa anar.

Un node és una funció pura de l'execució, el contacte i el node — i els seus efectes es confirmen en la mateixa transacció que l'avanç de la pròpia execució. Aquesta única propietat és la que fa segur un reintent. Un worker mort durant el mig segon entre «envia» i «avança» deixa o les dues coses o cap, mai només una.

I com que l'aplicació subministra l'hora en lloc de la base de dades, una fila escrita ara vence ara. Una columna de programació que pren per defecte el rellotge de la base de dades encara no vence en l'instant en què s'escriu, i perd el mateix tick que l'ha creada — un error que no sembla res fins que un missatge arriba una hora tard.

Un tick del workerExecució
  • 1Llogarwake_at <= now(), FOR UPDATE SKIP LOCKED. Una cua sense lloguers envia dues vegades per defecte.
  • 2ExecutarNodes en ordre fins a una espera o un terminal. Cadascun escriu un pas: què ha decidit, què ha emès.
  • 3ConfirmarEfectes i avanç, en una transacció. Aquest és tot el truc.
  • 4ReposaS'escriu el següent wake_at. Encara no existeixen files aigües avall, i no cal que n'hi hagi.

Una execució per contacte per versió

Catorze triggers

Què pot iniciar una execució

Algunes d'aquestes són coses que fas tu. La majoria són coses que fa —o no fa— el teu client, i l'absència d'una acció és un trigger tan bo com l'acció mateixa.

Arriben

form_submit, list_join, contact_created, tag_added i segment_enter. Un segment és un predicat en viu, així que «entra al segment» cobreix cada «s'ha convertit en» que puguis expressar — tres comandes, noranta dies en silenci, gasta per sobre d'un llindar.

Fan alguna cosa

page_visit des de l'snippet del lloc, message_opened, link_clicked, booking_made i payment_made. Que s'obri un missatge és en si mateix un esdeveniment sobre el contacte, així que un embut pot esperar una reacció a l'última cosa que ha enviat.

El temps, o tu

date_field amb un desfàs — un aniversari, una renovació, «un any des de», set dies abans o tres dies després. schedule per al recurrent. manual per a l'anunci que envies perquè tu ho has decidit.

La teva pròpia aplicació

api_event és un esdeveniment personalitzat que publiques des del teu propi codi amb el teu propi token. Qualsevol cosa que el teu producte sap es converteix en un trigger: activat, ha convidat un company, ha arribat al límit, cancel·lat, exportat. Aquest és el que converteix una eina de correu en part del teu producte.

Reentrada, decidida una vegada

Un embut és reentrant o no ho és, i la base de dades ho fa complir: una execució per contacte per embut, tret que diguis una altra cosa. El mateix trigger disparat dues vegades en el mateix segon no pot produir dues execucions per accident.

Condicions d'entrada

Un trigger es dispara i l'especificació d'entrada decideix si aquest contacte concret és elegible — un predicat de segment davant de la porta. Més barat que un node de condició al primer pas, i manté el graf centrat en què passa en lloc de en qui hi pot entrar.

Catorze coses poden iniciar-ho. Setze coses poden passar després.

Setze accions i set nodes de flux

Què pot fer un embut, i com decideix

Enviar alguna cosa

send_email, send_sms, send_push, send_letter — quatre canals, un graf — més notify_team quan la persona a qui cal avisar treballa per a tu.

Modificar el contacte

add_tag, remove_tag, add_to_list, remove_from_list, set_field. Anar marcant algú pel camí és el que fa senzill el segment del següent embut.

Arribar més enllà

http_request a allò que vulguis, create_payment contra el teu propi compte connectat, i book_slot contra un recurs de reserves. El pagador continua sent teu; ningú es converteix en client nostre.

Moure's entre embuts

enter_funnel i exit_funnel. Crea una seqüència de benvinguda i crida-la des de quatre llocs, en lloc de mantenir quatre còpies que divergeixen al març.

Genera en el moment de l'enviament

ai_generate omple les variables de fusió per contacte, amb mesurament contra la teva quota i memòria cau per hash de creativitat i d'atribut de contacte — o pagaries per destinatari a cada enviament.

Espera, ramifica, divideix, uneix

wait accepta una durada, una data i hora, un dia de la setmana i una hora, o un camp de data amb un desfase. condition és un predicat de segment amb un sí i un no. split és A/B/n amb pesos. join torna a ajuntar les branques.

goal — l'únic que importa

Un objectiu acaba l'execució per a qualsevol que l'assoleixi. Han reservat, han comprat, han respost: la resta de la seqüència se'ls cancel·la específicament. Ningú rep un "et trobem a faltar" l'endemà d'haver tornat, i aquest és el node que ho evita.

throttle i quiet_hours

El throttle regula un pic d'enviaments perquè una bústia amb un límit de velocitat baix no es sature fins a la suspensió. Les hores de silenci retenen un missatge fins a una hora raonable — s'apliquen a la capa de missatge, no es copien a cada branca del graf.

Comprovat abans de poder executar-se

El validador et refusa les mateixes coses a tu i a la IA

Un graf es comprova abans de poder publicar-se, i la comprovació no és merament orientativa. És el mateix camí de codi tant si una persona ha dibuixat l'embut com si un model l'ha generat, i és l'única raó per la qual els embuts generats són fiables.

Exactament una entrada

Dos nodes d'entrada són una ambigüitat que ningú nota fins que la meitat equivocada d'una llista rep la seqüència equivocada.

Tots els nodes accessibles

Una branca orfe és o bé un error o bé un missatge que creus que s'envia i no s'envia. Totes dues coses valen la pena que te les diguin.

Un cicle ha de contenir una espera

Un bucle sense espera és un bucle infinit amb un enviament al mig. Aquesta regla és la diferència entre un embut i un incident.

Cada enviament té la seva creativitat

Un node send_email sense creativitat ni assumpte no es pot publicar. El missatge amb l'assumpte correcte i el cos buit és un mode de fallada real; aquí es refusa.

Tota variable és coneguda

Les variables de fusió es validen en publicar. {{frist_name}} és una errata que veus mentre edites, no un "Hola ," que arriba a quaranta mil bústies.

Després, simula-ho

Fes una prova en sec d'un contacte real per tot el graf i llegeix el camí recorregut i cada missatge que s'enviaria, amb el seu dia. Res no surt de casa.

Els casos incòmodes

Set coses que trenquen un motor ingenu

Cadascuna és un test amb un rellotge determinista al darrere, perquè totes trenquen una implementació que sembla perfectament correcta fins que es troba amb la realitat.

Contra què es prova el motorFalsació
  • 1Un embut que fa un bucle sobre si mateixLegítim, habitual i correcte — sempre que el cicle contingui una espera, cosa que el validador exigeix.
  • 2Algú es dona de baixa a mig camíLa supressió es comprova a l'enviament, no a la cua. Comprovar-ho a la cua envia correus a la gent que ha marxat durant l'espera.
  • 3L'embut s'edita amb deu mil persones dinsContinuen recorrent la versió per la qual van entrar, fins al final. Els nous entrants recorren la nova.
  • 4El mateix disparador s'activa dues vegades en un segonUna sola execució, perquè la unicitat és un índex i no una comprovació seguida d'una inserció.
  • 5Un contacte s'elimina a mig procésL'execució acaba. Una supressió que deixa una seqüència encara adreçada a algú no és una supressió.
  • 6Una espera travessa un canvi d'horari d'estiu«Tres dies a les nou del matí» significa les nou del matí a banda i banda del canvi d'hora.
  • 7Un worker mor entre l'enviament i l'avançEfectes i avanç són una única transacció. O han passat tots dos, o no n'ha passat cap.

Rellotge deterministaCada test trenca una implementació plausible

Les campanyes són l'altra meitat

Un embut reacciona. Una campanya és la difusió puntual: un públic, una programació, una limitació d'enviament i un enviament. És una cosa de forma diferent i es manté deliberadament separada en lloc de fingir que és un embut amb un sol node.

Dues regles ho fan segur. Un públic es materialitza una sola vegada i es nega a executar-se dues vegades — tornar-lo a resoldre afegiria silenciosament tothom qui s'hi hagi unit des que va començar l'enviament, i l'índex de desduplicació ho amagaria en impedir els duplicats que ell mateix ha creat. I els comptadors es recalculem a partir dels esdeveniments de lliurament, mai no s'incrementen in situ, de manera que un webhook repetit no pot inflar un informe.

Què fer servir: si passa per alguna cosa que la persona ha fet, és un embut. Si passa per alguna cosa que tu has decidit un dimarts, és una campanya. Una quantitat sorprenent d'automatització de màrqueting va malament per forçar la segona a la forma del primer.