[{"data":1,"prerenderedAt":1590},["ShallowReactive",2],{"navigation_docs_hu":3,"-hu-events-outbox":442,"-hu-events-outbox-surround":1585},[4,45,60,81,112,129,146,173,197,213,242,280,357,373,385,404,430],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Kezdő lépések","i-lucide-rocket","\u002Fhu\u002Fgetting-started","hu\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Bevezetés","\u002Fhu\u002Fgetting-started\u002Fintroduction","hu\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Laravelből érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-laravel","hu\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Symfonyból érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-symfony","hu\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Telepítés","\u002Fhu\u002Fgetting-started\u002Finstallation","hu\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Az első modulod","\u002Fhu\u002Fgetting-started\u002Ffirst-module","hu\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Projektstruktúra","\u002Fhu\u002Fgetting-started\u002Fproject-structure","hu\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"A shop mintaalkalmazás","\u002Fhu\u002Fgetting-started\u002Fsample-app","hu\u002F1.getting-started\u002F7.sample-app","i-lucide-shopping-cart",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"queue","i-lucide-layers","\u002Fhu\u002Fqueue","hu\u002F10.queue",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Áttekintés","\u002Fhu\u002Fqueue\u002Foverview","hu\u002F10.queue\u002F1.overview","i-lucide-list-ordered",{"title":57,"path":58,"stem":59,"icon":47},"Taskok","\u002Fhu\u002Fqueue\u002Ftasks","hu\u002F10.queue\u002F2.tasks",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":44},"events","i-lucide-workflow","\u002Fhu\u002Fevents","hu\u002F11.events",[66,71,76],{"title":67,"path":68,"stem":69,"icon":70},"Események","\u002Fhu\u002Fevents\u002Foverview","hu\u002F11.events\u002F1.overview","i-lucide-radio",{"title":72,"path":73,"stem":74,"icon":75},"Outbox","\u002Fhu\u002Fevents\u002Foutbox","hu\u002F11.events\u002F2.outbox","i-lucide-inbox",{"title":77,"path":78,"stem":79,"icon":80},"Ütemezés","\u002Fhu\u002Fevents\u002Fscheduler","hu\u002F11.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":82,"icon":83,"path":84,"stem":85,"children":86,"page":44},"auth","i-lucide-shield-check","\u002Fhu\u002Fauth","hu\u002F12.auth",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Autentikáció","\u002Fhu\u002Fauth\u002Foverview","hu\u002F12.auth\u002F1.overview","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"RBAC","\u002Fhu\u002Fauth\u002Frbac","hu\u002F12.auth\u002F2.rbac","i-lucide-users",{"title":98,"path":99,"stem":100,"icon":101},"Policy-k","\u002Fhu\u002Fauth\u002Fpolicy","hu\u002F12.auth\u002F3.policy","i-lucide-gavel",{"title":103,"path":104,"stem":105,"icon":106},"Az auth önálló használata","\u002Fhu\u002Fauth\u002Fstandalone","hu\u002F12.auth\u002F4.standalone","i-lucide-plug",{"title":108,"path":109,"stem":110,"icon":111},"Social login goth-tal, önállóan","\u002Fhu\u002Fauth\u002Fsocial-standalone","hu\u002F12.auth\u002F5.social-standalone","i-lucide-log-in",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":44},"mail","i-lucide-mail","\u002Fhu\u002Fmail","hu\u002F13.mail",[118,121,125],{"title":52,"path":119,"stem":120,"icon":114},"\u002Fhu\u002Fmail\u002Foverview","hu\u002F13.mail\u002F1.overview",{"title":122,"path":123,"stem":124,"icon":114},"SMTP","\u002Fhu\u002Fmail\u002Fsmtp","hu\u002F13.mail\u002F2.smtp",{"title":126,"path":127,"stem":128,"icon":114},"MJML","\u002Fhu\u002Fmail\u002Fmjml","hu\u002F13.mail\u002F3.mjml",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":44},"notify","i-lucide-bell","\u002Fhu\u002Fnotify","hu\u002F14.notify",[135,138,142],{"title":52,"path":136,"stem":137,"icon":131},"\u002Fhu\u002Fnotify\u002Foverview","hu\u002F14.notify\u002F1.overview",{"title":139,"path":140,"stem":141,"icon":131},"Database csatorna","\u002Fhu\u002Fnotify\u002Fdatabase","hu\u002F14.notify\u002F2.database",{"title":143,"path":144,"stem":145,"icon":131},"Broadcast csatorna","\u002Fhu\u002Fnotify\u002Fbroadcast","hu\u002F14.notify\u002F3.broadcast",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":44},"storage","i-lucide-hard-drive","\u002Fhu\u002Fstorage","hu\u002F15.storage",[152,155,159,163,168],{"title":52,"path":153,"stem":154,"icon":148},"\u002Fhu\u002Fstorage\u002Foverview","hu\u002F15.storage\u002F1.overview",{"title":156,"path":157,"stem":158},"Disk API","\u002Fhu\u002Fstorage\u002Fdisk-api","hu\u002F15.storage\u002F2.disk-api",{"title":160,"path":161,"stem":162,"icon":148},"Memória és helyi lemez","\u002Fhu\u002Fstorage\u002Flocal","hu\u002F15.storage\u002F3.local",{"title":164,"path":165,"stem":166,"icon":167},"S3","\u002Fhu\u002Fstorage\u002Fs3","hu\u002F15.storage\u002F4.s3","i-lucide-cloud",{"title":169,"path":170,"stem":171,"icon":172},"Tesztelés","\u002Fhu\u002Fstorage\u002Ftesting","hu\u002F15.storage\u002F5.testing","i-lucide-flask-conical",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"telemetry","i-lucide-activity","\u002Fhu\u002Ftelemetry","hu\u002F16.telemetry",[179,182,187,192],{"title":52,"path":180,"stem":181,"icon":175},"\u002Fhu\u002Ftelemetry\u002Foverview","hu\u002F16.telemetry\u002F1.overview",{"title":183,"path":184,"stem":185,"icon":186},"Logolás","\u002Fhu\u002Ftelemetry\u002Flogging","hu\u002F16.telemetry\u002F2.logging","i-lucide-scroll-text",{"title":188,"path":189,"stem":190,"icon":191},"OpenTelemetry","\u002Fhu\u002Ftelemetry\u002Fopentelemetry","hu\u002F16.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":193,"path":194,"stem":195,"icon":196},"Sentry","\u002Fhu\u002Ftelemetry\u002Fsentry","hu\u002F16.telemetry\u002F4.sentry","i-lucide-bug",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":44},"Referencia","i-lucide-book-open","\u002Fhu\u002Freference","hu\u002F17.reference",[203,208],{"title":204,"path":205,"stem":206,"icon":207},"Konfiguráció","\u002Fhu\u002Freference\u002Fconfiguration","hu\u002F17.reference\u002F1.configuration","i-lucide-settings",{"title":209,"path":210,"stem":211,"icon":212},"Külső függőségek","\u002Fhu\u002Freference\u002Fdependencies","hu\u002F17.reference\u002F2.dependencies","i-lucide-package",{"title":214,"icon":215,"path":216,"stem":217,"children":218,"page":44},"Koncepciók","i-lucide-lightbulb","\u002Fhu\u002Fconcepts","hu\u002F2.concepts",[219,223,228,232,237],{"title":220,"path":221,"stem":222,"icon":47},"Architektúra","\u002Fhu\u002Fconcepts\u002Farchitecture","hu\u002F2.concepts\u002F1.architecture",{"title":224,"path":225,"stem":226,"icon":227},"Hibamodell","\u002Fhu\u002Fconcepts\u002Ferror-model","hu\u002F2.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":204,"path":229,"stem":230,"icon":231},"\u002Fhu\u002Fconcepts\u002Fconfiguration","hu\u002F2.concepts\u002F3.configuration","i-lucide-settings-2",{"title":233,"path":234,"stem":235,"icon":236},"Codegen pipeline","\u002Fhu\u002Fconcepts\u002Fcodegen-pipeline","hu\u002F2.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":238,"path":239,"stem":240,"icon":241},"Design patternek","\u002Fhu\u002Fconcepts\u002Fdesign-patterns","hu\u002F2.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":243,"icon":244,"path":245,"stem":246,"children":247,"page":44},"A kit","i-lucide-box","\u002Fhu\u002Fkit","hu\u002F3.kit",[248,252,257,262,267,271,276],{"title":249,"path":250,"stem":251,"icon":244},"A kit áttekintése","\u002Fhu\u002Fkit\u002Foverview","hu\u002F3.kit\u002F1.overview",{"title":253,"path":254,"stem":255,"icon":256},"Alkalmazás-életciklus","\u002Fhu\u002Fkit\u002Fapp","hu\u002F3.kit\u002F2.app","i-lucide-power",{"title":258,"path":259,"stem":260,"icon":261},"Szerver","\u002Fhu\u002Fkit\u002Fserver","hu\u002F3.kit\u002F3.server","i-lucide-server",{"title":263,"path":264,"stem":265,"icon":266},"Worker","\u002Fhu\u002Fkit\u002Fworker","hu\u002F3.kit\u002F4.worker","i-lucide-cog",{"title":268,"path":269,"stem":270,"icon":70},"Realtime","\u002Fhu\u002Fkit\u002Frealtime","hu\u002F3.kit\u002F5.realtime",{"title":272,"path":273,"stem":274,"icon":275},"Migrációk","\u002Fhu\u002Fkit\u002Fmigrations","hu\u002F3.kit\u002F6.migrations","i-lucide-file-stack",{"title":277,"path":278,"stem":279,"icon":111},"Social login","\u002Fhu\u002Fkit\u002Fsocial-login","hu\u002F3.kit\u002F7.social-login",{"title":281,"icon":282,"path":283,"stem":284,"children":285,"page":44},"CLI referencia","i-lucide-terminal","\u002Fhu\u002Fcli","hu\u002F4.cli",[286,289,294,299,304,309,314,319,324,329,334,338,343,348,352],{"title":52,"path":287,"stem":288,"icon":282},"\u002Fhu\u002Fcli\u002Foverview","hu\u002F4.cli\u002F1.overview",{"title":290,"path":291,"stem":292,"icon":293},"add db","\u002Fhu\u002Fcli\u002Fadd-db","hu\u002F4.cli\u002F10.add-db","i-lucide-database-zap",{"title":295,"path":296,"stem":297,"icon":298},"add compose \u002F add docker","\u002Fhu\u002Fcli\u002Fadd-compose","hu\u002F4.cli\u002F11.add-compose","i-lucide-container",{"title":300,"path":301,"stem":302,"icon":303},"add mail","\u002Fhu\u002Fcli\u002Fadd-mail","hu\u002F4.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":305,"path":306,"stem":307,"icon":308},"add notification","\u002Fhu\u002Fcli\u002Fadd-notification","hu\u002F4.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":310,"path":311,"stem":312,"icon":313},"add realtime","\u002Fhu\u002Fcli\u002Fadd-realtime","hu\u002F4.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":315,"path":316,"stem":317,"icon":318},"add seeder","\u002Fhu\u002Fcli\u002Fadd-seeder","hu\u002F4.cli\u002F15.add-seeder","i-lucide-sprout",{"title":320,"path":321,"stem":322,"icon":323},"new project","\u002Fhu\u002Fcli\u002Fnew-project","hu\u002F4.cli\u002F2.new-project","i-lucide-folder-plus",{"title":325,"path":326,"stem":327,"icon":328},"new module","\u002Fhu\u002Fcli\u002Fnew-module","hu\u002F4.cli\u002F3.new-module","i-lucide-blocks",{"title":330,"path":331,"stem":332,"icon":333},"add surface","\u002Fhu\u002Fcli\u002Fadd-surface","hu\u002F4.cli\u002F4.add-surface","i-lucide-layers-2",{"title":335,"path":336,"stem":337,"icon":244},"add core","\u002Fhu\u002Fcli\u002Fadd-core","hu\u002F4.cli\u002F5.add-core",{"title":339,"path":340,"stem":341,"icon":342},"add handler","\u002Fhu\u002Fcli\u002Fadd-handler","hu\u002F4.cli\u002F6.add-handler","i-lucide-webhook",{"title":344,"path":345,"stem":346,"icon":347},"new migration","\u002Fhu\u002Fcli\u002Fnew-migration","hu\u002F4.cli\u002F7.new-migration","i-lucide-file-plus",{"title":349,"path":350,"stem":351,"icon":266},"worker generátorok","\u002Fhu\u002Fcli\u002Fworker-generators","hu\u002F4.cli\u002F8.worker-generators",{"title":353,"path":354,"stem":355,"icon":356},"upgrade templates","\u002Fhu\u002Fcli\u002Fupgrade-templates","hu\u002F4.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"title":358,"icon":227,"path":359,"stem":360,"children":361,"page":44},"errs","\u002Fhu\u002Ferrs","hu\u002F5.errs",[362,365,369],{"title":52,"path":363,"stem":364,"icon":227},"\u002Fhu\u002Ferrs\u002Foverview","hu\u002F5.errs\u002F1.overview",{"title":366,"path":367,"stem":368},"API","\u002Fhu\u002Ferrs\u002Fapi","hu\u002F5.errs\u002F2.api",{"title":370,"path":371,"stem":372,"icon":227},"Integráció","\u002Fhu\u002Ferrs\u002Fintegration","hu\u002F5.errs\u002F3.integration",{"title":374,"icon":231,"path":375,"stem":376,"children":377,"page":44},"envconf","\u002Fhu\u002Fenvconf","hu\u002F6.envconf",[378,381],{"title":52,"path":379,"stem":380,"icon":231},"\u002Fhu\u002Fenvconf\u002Foverview","hu\u002F6.envconf\u002F1.overview",{"title":382,"path":383,"stem":384},"Receptek","\u002Fhu\u002Fenvconf\u002Frecipes","hu\u002F6.envconf\u002F2.recipes",{"title":386,"icon":387,"path":388,"stem":389,"children":390,"page":44},"httperr","i-lucide-globe","\u002Fhu\u002Fhttperr","hu\u002F7.httperr",[391,394,399],{"title":52,"path":392,"stem":393,"icon":387},"\u002Fhu\u002Fhttperr\u002Foverview","hu\u002F7.httperr\u002F1.overview",{"title":395,"path":396,"stem":397,"icon":398},"Hibaválaszok","\u002Fhu\u002Fhttperr\u002Ferror-responses","hu\u002F7.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":400,"path":401,"stem":402,"icon":403},"Validáció","\u002Fhu\u002Fhttperr\u002Fvalidation","hu\u002F7.httperr\u002F3.validation","i-lucide-badge-check",{"title":405,"icon":406,"path":407,"stem":408,"children":409,"page":44},"dbx","i-lucide-database","\u002Fhu\u002Fdbx","hu\u002F8.dbx",[410,413,417,421,426],{"title":52,"path":411,"stem":412,"icon":406},"\u002Fhu\u002Fdbx\u002Foverview","hu\u002F8.dbx\u002F1.overview",{"title":414,"path":415,"stem":416,"icon":106},"pgx","\u002Fhu\u002Fdbx\u002Fpg","hu\u002F8.dbx\u002F2.pg",{"title":418,"path":419,"stem":420,"icon":47},"bun","\u002Fhu\u002Fdbx\u002Fbunx","hu\u002F8.dbx\u002F3.bunx",{"title":422,"path":423,"stem":424,"icon":425},"Tranzakciók","\u002Fhu\u002Fdbx\u002Ftransactions","hu\u002F8.dbx\u002F4.transactions","i-lucide-git-merge",{"title":427,"path":428,"stem":429,"icon":318},"Seederek","\u002Fhu\u002Fdbx\u002Fseed","hu\u002F8.dbx\u002F5.seed",{"title":431,"icon":55,"path":432,"stem":433,"children":434,"page":44},"paginate","\u002Fhu\u002Fpaginate","hu\u002F9.paginate",[435,438],{"title":52,"path":436,"stem":437,"icon":55},"\u002Fhu\u002Fpaginate\u002Foverview","hu\u002F9.paginate\u002F1.overview",{"title":439,"path":440,"stem":441,"icon":19},"Cursor-lapozás","\u002Fhu\u002Fpaginate\u002Fcursor","hu\u002F9.paginate\u002F2.cursor",{"id":443,"title":72,"body":444,"description":1578,"extension":1579,"links":1580,"meta":1581,"navigation":1582,"path":73,"seo":1583,"stem":74,"__hash__":1584},"docs_hu\u002Fhu\u002F11.events\u002F2.outbox.md",{"type":445,"value":446,"toc":1566},"minimark",[447,456,485,503,508,523,545,552,556,641,653,657,730,759,768,824,835,945,949,1073,1100,1103,1131,1136,1139,1161,1168,1172,1191,1366,1384,1387,1401,1495,1499,1535,1539,1562],[448,449,450,451,455],"p",{},"Importáld az ",[452,453,454],"code",{},"outbox"," alcsomagot, hogy a dispatchered tranzakciós kézbesítési garanciát kapjon:",[457,458,463],"pre",{"className":459,"code":460,"language":461,"meta":462,"style":462},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import \"github.com\u002Fgp-system\u002Fevents\u002Foutbox\"\n","go","",[452,464,465],{"__ignoreMap":462},[466,467,470,474,478,482],"span",{"class":468,"line":469},"line",1,[466,471,473],{"class":472},"s7zQu","import",[466,475,477],{"class":476},"sMK4o"," \"",[466,479,481],{"class":480},"sBMFI","github.com\u002Fgp-system\u002Fevents\u002Foutbox",[466,483,484],{"class":476},"\"\n",[448,486,487,488,491,492,497,498,502],{},"Az ",[452,489,490],{},"events\u002Foutbox"," a ",[493,494,496],"a",{"href":495},"\u002Fhu\u002Fevents\u002Foverview#dispatch","dispatch"," kézbesítési garanciája: az eventet nem közvetlenül Valkeybe adja, hanem egy Postgres-táblába írja ",[499,500,501],"strong",{},"a hívó tranzakciójában",", és egy relay továbbítja a commitált sorokat a queue-ba. A generált projektben ez az alapértelmezett dispatcher: nem opcionális extra, hanem a kiindulópont.",[504,505,507],"h2",{"id":506},"a-dual-write-probléma","A dual-write probléma",[448,509,510,511,514,515,518,519,522],{},"Vedd a shop ",[452,512,513],{},"PlaceOrder","-ét: a rendelés insertje és az ",[452,516,517],{},"orderPlaced"," event ",[499,520,521],{},"együtt vagy sehogy"," kell megtörténjen. Két írás két rendszerbe (Postgres + Valkey) viszont nem tud atomikus lenni:",[524,525,526,534],"ul",{},[527,528,529,530,533],"li",{},"Ha az eventet a commit ",[499,531,532],{},"előtt"," enqueue-lod, és a tranzakció rollbackel, a worker egy meg-nem-történt rendelésről küld visszaigazolót.",[527,535,536,537,540,541,544],{},"Ha a commit ",[499,538,539],{},"után"," enqueue-lod, és a folyamat a kettő közt hal le (deploy, OOM, node-hiba), a rendelés megvan, de az event ",[499,542,543],{},"elveszett",": a vevő soha nem kap e-mailt, és semmi nem jelzi, hogy baj van.",[448,546,547,548,551],{},"Önmagában egy commit-utáni hook nem zárja be ezt a rést: a rollback-esetet lekezelheti, de egy commit és a hook lefutása közti crash még mindig elveszítheti az eventet. A kitben ez a minta gyárilag jön: az outbox az eventet ",[499,549,550],{},"ugyanabba az adatbázisba, ugyanabban a tranzakcióban"," írja, mint az üzleti változást, egyetlen commit, ami vagy mindent perzisztál, vagy semmit.",[504,553,555],{"id":554},"hogyan-működik","Hogyan működik",[557,558,560,565,582,586,589,593,604,608,626,630],"steps",{"level":559},"4",[561,562,564],"h4",{"id":563},"a-dispatch-a-tranzakcióban-ír","A dispatch a tranzakcióban ír",[448,566,567,568,491,570,573,574,577,578,581],{},"A ",[452,569,513],{},[452,571,572],{},"WithinTransaction","-ön belül hívja a ",[452,575,576],{},"Dispatch","-et; az outbox-dispatcher egy sort insertel az ",[452,579,580],{},"outbox_events"," táblába, ugyanazon a tranzakción át, mint a rendelés és a készlet írása.",[561,583,585],{"id":584},"egyetlen-commit","Egyetlen commit",[448,587,588],{},"A tranzakció commitál: rendelés + készletcsökkentés + outbox-sor atomikusan. Rollbacknél az event-sor is eltűnik: fantomevent nincs.",[561,590,592],{"id":591},"a-relay-lefoglalja-a-commitált-sorokat","A relay lefoglalja a commitált sorokat",[448,594,595,596,599,600,603],{},"A worker-ben futó relay ",[452,597,598],{},"OUTBOX_POLL_INTERVAL","-onként pollozza a publikálatlan sorokat, ",[452,601,602],{},"FOR UPDATE SKIP LOCKED","-dal, így N worker-replika soha nem verseng ugyanazokon a sorokon.",[561,605,607],{"id":606},"enqueue-determinisztikus-taskid-vel","Enqueue determinisztikus TaskID-vel",[448,609,610,611,614,615,618,619,625],{},"Minden sort Valkeybe enqueue-l, asynq ",[452,612,613],{},"TaskID","-nek az outbox ",[452,616,617],{},"event_id","-t használva. Ha egy korábbi kör az enqueue után, de a megjelölés előtt halt le, az ismételt enqueue ",[493,620,622],{"href":621},"\u002Fhu\u002Fqueue\u002Foverview#client",[452,623,624],{},"ErrDuplicate",": a relay ezt sikernek veszi, és csak a megjelölést pótolja.",[561,627,629],{"id":628},"megjelölés-és-takarítás","Megjelölés és takarítás",[448,631,632,633,636,637,640],{},"A beadott sorok ",[452,634,635],{},"published_at","-et kapnak, és a foglaló tranzakció commitál. A publikált sorokat egy takarító ciklus ",[452,638,639],{},"OUTBOX_RETENTION"," után törli.",[448,642,643,644,648,649,652],{},"Innen az asynq veszi át: fan-out a listenerekre, retry, archiválás, lásd ",[493,645,647],{"href":646},"\u002Fhu\u002Fevents\u002Foverview#fan-out-hogyan-lesz-egy-eventb%C5%91l-n-task","események",". A lánc végig ",[499,650,651],{},"legalább-egyszeres",", ezért a listener-idempotencia itt is előfeltétel.",[504,654,656],{"id":655},"store-és-dispatcher","Store és dispatcher",[457,658,660],{"className":459,"code":659,"language":461,"meta":462,"style":462},"store := outbox.NewStore(pg.NewDB(pool)) \u002F\u002F pg.DBTX-et fogad\ndispatcher := outbox.NewDispatcher(store) \u002F\u002F events.Dispatcher\n",[452,661,662,704],{"__ignoreMap":462},[466,663,664,668,671,674,677,681,684,687,689,692,694,697,700],{"class":468,"line":469},[466,665,667],{"class":666},"sTEyZ","store ",[466,669,670],{"class":476},":=",[466,672,673],{"class":666}," outbox",[466,675,676],{"class":476},".",[466,678,680],{"class":679},"s2Zo4","NewStore",[466,682,683],{"class":476},"(",[466,685,686],{"class":666},"pg",[466,688,676],{"class":476},[466,690,691],{"class":679},"NewDB",[466,693,683],{"class":476},[466,695,696],{"class":666},"pool",[466,698,699],{"class":476},"))",[466,701,703],{"class":702},"sHwdD"," \u002F\u002F pg.DBTX-et fogad\n",[466,705,707,710,712,714,716,719,721,724,727],{"class":468,"line":706},2,[466,708,709],{"class":666},"dispatcher ",[466,711,670],{"class":476},[466,713,673],{"class":666},[466,715,676],{"class":476},[466,717,718],{"class":679},"NewDispatcher",[466,720,683],{"class":476},[466,722,723],{"class":666},"store",[466,725,726],{"class":476},")",[466,728,729],{"class":702}," \u002F\u002F events.Dispatcher\n",[448,731,567,732,735,736,739,740,742,743,491,748,751,752,754,755,758],{},[452,733,734],{},"Store"," egyetlen metódus (",[452,737,738],{},"Insert(ctx, env)","), és a ",[452,741,680],{}," a kit pgx-executorára épül: mivel a ",[493,744,745],{"href":415},[452,746,747],{},"pg.DB",[452,749,750],{},"ctx","-ben hordozott tranzakcióhoz csatlakozik, a ",[452,753,572],{},"-ön belüli insert ",[499,756,757],{},"automatikusan a hívó tranzakciójában"," fut: a service-nek semmit nem kell tudnia az outboxról. Tranzakción kívül hívva sima insert, az event így is kézbesítődik, csak az atomicitás-garancia nem értelmezett.",[448,760,567,761,491,764,767],{},[493,762,763],{"href":419},"bun-t használó projektek",[452,765,766],{},"events\u002Foutbox\u002Fbunx"," adaptert kötik be, ami a bun-tranzakcióhoz csatlakozik:",[457,769,771],{"className":459,"code":770,"language":461,"meta":462,"style":462},"import outboxbunx \"github.com\u002Fgp-system\u002Fevents\u002Foutbox\u002Fbunx\"\n\ndispatcher := outbox.NewDispatcher(outboxbunx.NewStore(bunDB))\n",[452,772,773,788,794],{"__ignoreMap":462},[466,774,775,777,780,783,786],{"class":468,"line":469},[466,776,473],{"class":472},[466,778,779],{"class":666}," outboxbunx ",[466,781,782],{"class":476},"\"",[466,784,785],{"class":480},"github.com\u002Fgp-system\u002Fevents\u002Foutbox\u002Fbunx",[466,787,484],{"class":476},[466,789,790],{"class":468,"line":706},[466,791,793],{"emptyLinePlaceholder":792},true,"\n",[466,795,797,799,801,803,805,807,809,812,814,816,818,821],{"class":468,"line":796},3,[466,798,709],{"class":666},[466,800,670],{"class":476},[466,802,673],{"class":666},[466,804,676],{"class":476},[466,806,718],{"class":679},[466,808,683],{"class":476},[466,810,811],{"class":666},"outboxbunx",[466,813,676],{"class":476},[466,815,680],{"class":679},[466,817,683],{"class":476},[466,819,820],{"class":666},"bunDB",[466,822,823],{"class":476},"))\n",[448,825,826,827,830,831,834],{},"A generált ",[452,828,829],{},"main.go","-kban ez a bekötés készen van (az első ",[452,832,833],{},"add event"," drótozza be); a shop HTTP-belépési pontjában így néz ki:",[457,836,839],{"className":459,"code":837,"filename":838,"language":461,"meta":462,"style":462},"deps := shop.Dependencies{\n    DB:         pg.NewDB(pool),\n    Transactor: pg.NewTransactor(pool),\n    Dispatcher: outbox.NewDispatcher(outbox.NewStore(pg.NewDB(pool))),\n}\n","cmd\u002Fshop\u002Fmain.go (részlet)",[452,840,841,859,881,902,939],{"__ignoreMap":462},[466,842,843,846,848,851,853,856],{"class":468,"line":469},[466,844,845],{"class":666},"deps ",[466,847,670],{"class":476},[466,849,850],{"class":480}," shop",[466,852,676],{"class":476},[466,854,855],{"class":480},"Dependencies",[466,857,858],{"class":476},"{\n",[466,860,861,864,867,870,872,874,876,878],{"class":468,"line":706},[466,862,863],{"class":666},"    DB",[466,865,866],{"class":476},":",[466,868,869],{"class":666},"         pg",[466,871,676],{"class":476},[466,873,691],{"class":679},[466,875,683],{"class":476},[466,877,696],{"class":666},[466,879,880],{"class":476},"),\n",[466,882,883,886,888,891,893,896,898,900],{"class":468,"line":796},[466,884,885],{"class":666},"    Transactor",[466,887,866],{"class":476},[466,889,890],{"class":666}," pg",[466,892,676],{"class":476},[466,894,895],{"class":679},"NewTransactor",[466,897,683],{"class":476},[466,899,696],{"class":666},[466,901,880],{"class":476},[466,903,905,908,910,912,914,916,918,920,922,924,926,928,930,932,934,936],{"class":468,"line":904},4,[466,906,907],{"class":666},"    Dispatcher",[466,909,866],{"class":476},[466,911,673],{"class":666},[466,913,676],{"class":476},[466,915,718],{"class":679},[466,917,683],{"class":476},[466,919,454],{"class":666},[466,921,676],{"class":476},[466,923,680],{"class":679},[466,925,683],{"class":476},[466,927,686],{"class":666},[466,929,676],{"class":476},[466,931,691],{"class":679},[466,933,683],{"class":476},[466,935,696],{"class":666},[466,937,938],{"class":476},"))),\n",[466,940,942],{"class":468,"line":941},5,[466,943,944],{"class":476},"}\n",[504,946,948],{"id":947},"a-relay","A relay",[457,950,952],{"className":459,"code":951,"language":461,"meta":462,"style":462},"relay := outbox.MustNewRelay(ctx, cfg.Outbox, pool, cfg.Worker.Valkey)\n\nerr := worker.Run(ctx, cfg.Worker, register,\n    worker.WithOutboxRelay(relay), \u002F\u002F a worker futtatja és állítja le\n    \u002F\u002F ...\n)\n",[452,953,954,1003,1007,1042,1063,1068],{"__ignoreMap":462},[466,955,956,959,961,963,965,968,970,972,975,978,980,982,984,987,989,991,993,995,997,1000],{"class":468,"line":469},[466,957,958],{"class":666},"relay ",[466,960,670],{"class":476},[466,962,673],{"class":666},[466,964,676],{"class":476},[466,966,967],{"class":679},"MustNewRelay",[466,969,683],{"class":476},[466,971,750],{"class":666},[466,973,974],{"class":476},",",[466,976,977],{"class":666}," cfg",[466,979,676],{"class":476},[466,981,72],{"class":666},[466,983,974],{"class":476},[466,985,986],{"class":666}," pool",[466,988,974],{"class":476},[466,990,977],{"class":666},[466,992,676],{"class":476},[466,994,263],{"class":666},[466,996,676],{"class":476},[466,998,999],{"class":666},"Valkey",[466,1001,1002],{"class":476},")\n",[466,1004,1005],{"class":468,"line":706},[466,1006,793],{"emptyLinePlaceholder":792},[466,1008,1009,1012,1014,1017,1019,1022,1024,1026,1028,1030,1032,1034,1036,1039],{"class":468,"line":796},[466,1010,1011],{"class":666},"err ",[466,1013,670],{"class":476},[466,1015,1016],{"class":666}," worker",[466,1018,676],{"class":476},[466,1020,1021],{"class":679},"Run",[466,1023,683],{"class":476},[466,1025,750],{"class":666},[466,1027,974],{"class":476},[466,1029,977],{"class":666},[466,1031,676],{"class":476},[466,1033,263],{"class":666},[466,1035,974],{"class":476},[466,1037,1038],{"class":666}," register",[466,1040,1041],{"class":476},",\n",[466,1043,1044,1047,1049,1052,1054,1057,1060],{"class":468,"line":904},[466,1045,1046],{"class":666},"    worker",[466,1048,676],{"class":476},[466,1050,1051],{"class":679},"WithOutboxRelay",[466,1053,683],{"class":476},[466,1055,1056],{"class":666},"relay",[466,1058,1059],{"class":476},"),",[466,1061,1062],{"class":702}," \u002F\u002F a worker futtatja és állítja le\n",[466,1064,1065],{"class":468,"line":941},[466,1066,1067],{"class":702},"    \u002F\u002F ...\n",[466,1069,1071],{"class":468,"line":1070},6,[466,1072,1002],{"class":476},[448,1074,567,1075,1078,1079,1081,1082,1088,1089,1092,1093,1099],{},[452,1076,1077],{},"NewRelay"," \u002F ",[452,1080,967],{}," saját ",[493,1083,1084,1087],{"href":621},[452,1085,1086],{},"queue.Client","-et"," nyit (PING-gel ellenőrizve), és a ",[452,1090,1091],{},"Run(ctx)"," a context lezárásáig polloz. Kézzel jellemzően egyiket sem hívod: a generált worker a ",[493,1094,1096],{"href":1095},"\u002Fhu\u002Fkit\u002Fworker#opci%C3%B3k",[452,1097,1098],{},"worker.WithOutboxRelay","-val adja át, és a worker életciklusa indítja\u002Fállítja le.",[448,1101,1102],{},"Amit a poll-ciklusról érdemes tudni:",[524,1104,1105,1119,1125],{},[527,1106,1107,1110,1111,1114,1115,1118],{},[499,1108,1109],{},"Tele batch → azonnali újra-poll."," Ha egy kör ",[452,1112,1113],{},"OUTBOX_BATCH_SIZE","-nyi sort dolgozott fel, nem alszik, hanem azonnal újra polloz: a burst gyorsan leürül, a ",[452,1116,1117],{},"POLL_INTERVAL"," csak az üresjárati késleltetés.",[527,1120,1121,1124],{},[499,1122,1123],{},"Hibánál exponenciális backoff."," Egy hibázó kör (pl. Valkey-kiesés) duplázódó várakozással próbálkozik újra, 30 másodperces plafonig, majd az első sikeres kör visszaáll a normál ütemre.",[527,1126,1127,1130],{},[499,1128,1129],{},"Részleges siker nem vész el."," Ha a batch közepén hibázik az enqueue, a már beadott sorok megjelölődnek: a hiba nem játssza újra az egész batch-et.",[1132,1133,1135],"h3",{"id":1134},"skálázhatóság-n-replika-dupla-kézbesítés-nélkül","Skálázhatóság: N replika, dupla-kézbesítés nélkül",[448,1137,1138],{},"A relay minden worker-replikában fut, koordináció nélkül. Két mechanizmus teszi ezt biztonságossá:",[1140,1141,1142,1148],"ol",{},[527,1143,1144,1145,1147],{},"a ",[452,1146,602],{}," miatt két replika soha nem foglalja le ugyanazt a sort;",[527,1149,1150,1151,1153,1154,1156,1157,1160],{},"a determinisztikus ",[452,1152,613],{}," (= ",[452,1155,617],{},") miatt a crash-ablakban kétszer beadott task a Valkeyben deduplikálódik: a ",[452,1158,1159],{},"OUTBOX_TASK_RETENTION"," az az időablak, ameddig a dedupe él.",[448,1162,1163,1164,676],{},"Ezért skálázod a workert nyugodt szívvel vízszintesen, lásd ",[493,1165,1167],{"href":1166},"\u002Fhu\u002Fkit\u002Fworker#sk%C3%A1l%C3%A1z%C3%A1s","worker → skálázás",[504,1169,1171],{"id":1170},"a-tábla-és-a-migráció","A tábla és a migráció",[448,1173,487,1174,1176,1177,491,1179,1182,1183,1186,1187,1190],{},[452,1175,580],{}," goose-migrációként érkezik: a ",[452,1178,320],{},[452,1180,1181],{},"migrations\u002F20200101000100_outbox.sql","-be írja, az ",[452,1184,1185],{},"add worker"," pedig ugyanezt a migrációt írja meg a worker-réteg bekötésének részeként; a séma forrása a csomagban az ",[452,1188,1189],{},"outbox.MigrationSQL",". A lényege:",[457,1192,1196],{"className":1193,"code":1194,"language":1195,"meta":462,"style":462},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","CREATE TABLE outbox_events (\n    id           bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,\n    event_id     uuid        NOT NULL UNIQUE,\n    event_name   text        NOT NULL,\n    payload      jsonb       NOT NULL,\n    metadata     jsonb       NOT NULL DEFAULT '{}'::jsonb,\n    created_at   timestamptz NOT NULL DEFAULT now(),\n    published_at timestamptz\n);\nCREATE INDEX outbox_events_unpublished_idx ON outbox_events (id) WHERE published_at IS NULL;\n","sql",[452,1197,1198,1213,1239,1252,1265,1274,1297,1319,1328,1334],{"__ignoreMap":462},[466,1199,1200,1204,1207,1210],{"class":468,"line":469},[466,1201,1203],{"class":1202},"sbssI","CREATE",[466,1205,1206],{"class":1202}," TABLE",[466,1208,1209],{"class":679}," outbox_events",[466,1211,1212],{"class":666}," (\n",[466,1214,1215,1218,1222,1225,1228,1231,1234,1237],{"class":468,"line":706},[466,1216,1217],{"class":666},"    id           ",[466,1219,1221],{"class":1220},"spNyl","bigint",[466,1223,1224],{"class":1202}," GENERATED",[466,1226,1227],{"class":1202}," ALWAYS",[466,1229,1230],{"class":1202}," AS",[466,1232,1233],{"class":1202}," IDENTITY",[466,1235,1236],{"class":1220}," PRIMARY KEY",[466,1238,1041],{"class":666},[466,1240,1241,1244,1247,1250],{"class":468,"line":796},[466,1242,1243],{"class":666},"    event_id     uuid        ",[466,1245,1246],{"class":1202},"NOT NULL",[466,1248,1249],{"class":1202}," UNIQUE",[466,1251,1041],{"class":666},[466,1253,1254,1257,1260,1263],{"class":468,"line":904},[466,1255,1256],{"class":666},"    event_name   ",[466,1258,1259],{"class":1220},"text",[466,1261,1262],{"class":1202},"        NOT NULL",[466,1264,1041],{"class":666},[466,1266,1267,1270,1272],{"class":468,"line":941},[466,1268,1269],{"class":666},"    payload      jsonb       ",[466,1271,1246],{"class":1202},[466,1273,1041],{"class":666},[466,1275,1276,1279,1281,1284,1287,1291,1294],{"class":468,"line":1070},[466,1277,1278],{"class":666},"    metadata     jsonb       ",[466,1280,1246],{"class":1202},[466,1282,1283],{"class":1220}," DEFAULT",[466,1285,1286],{"class":476}," '",[466,1288,1290],{"class":1289},"sfazB","{}",[466,1292,1293],{"class":476},"'",[466,1295,1296],{"class":666},"::jsonb,\n",[466,1298,1300,1303,1306,1309,1311,1314,1317],{"class":468,"line":1299},7,[466,1301,1302],{"class":666},"    created_at   ",[466,1304,1305],{"class":1220},"timestamptz",[466,1307,1308],{"class":1202}," NOT NULL",[466,1310,1283],{"class":1220},[466,1312,1313],{"class":1202}," now",[466,1315,1316],{"class":476},"()",[466,1318,1041],{"class":666},[466,1320,1322,1325],{"class":468,"line":1321},8,[466,1323,1324],{"class":666},"    published_at ",[466,1326,1327],{"class":1220},"timestamptz\n",[466,1329,1331],{"class":468,"line":1330},9,[466,1332,1333],{"class":666},");\n",[466,1335,1337,1339,1342,1345,1348,1351,1354,1357,1360,1363],{"class":468,"line":1336},10,[466,1338,1203],{"class":1202},[466,1340,1341],{"class":1202}," INDEX",[466,1343,1344],{"class":679}," outbox_events_unpublished_idx",[466,1346,1347],{"class":1202}," ON",[466,1349,1350],{"class":666}," outbox_events (id) ",[466,1352,1353],{"class":1202},"WHERE",[466,1355,1356],{"class":666}," published_at ",[466,1358,1359],{"class":1202},"IS",[466,1361,1362],{"class":1202}," NULL",[466,1364,1365],{"class":666},";\n",[448,1367,567,1368,491,1371,1375,1376,1379,1380,1383],{},[452,1369,1370],{},"metadata",[493,1372,1374],{"href":1373},"\u002Fhu\u002Fqueue\u002Ftasks#a-bor%C3%ADt%C3%A9k-envelope","boríték"," trace-kontextusát hordozza, így a trace az outboxon át is folytonos; a parciális index a pollt tartja gyorsnak akkor is, ha a tábla történelmileg nagyra nő. Worker indítása előtt futtasd le: ",[452,1377,1378],{},"go run .\u002Fcmd\u002Fmigrate up"," (lásd ",[493,1381,1382],{"href":273},"migrációk",").",[504,1385,204],{"id":1386},"konfiguráció",[448,1388,487,1389,1392,1393,1396,1397,1400],{},[452,1390,1391],{},"outbox.Config","-ot a projekt configja ",[452,1394,1395],{},"OUTBOX_"," prefixszel komponálja (a generált ",[452,1398,1399],{},"config.go","-ban készen van):",[1402,1403,1404,1420],"table",{},[1405,1406,1407],"thead",{},[1408,1409,1410,1414,1417],"tr",{},[1411,1412,1413],"th",{},"Változó",[1411,1415,1416],{},"Default",[1411,1418,1419],{},"Jelentés",[1421,1422,1423,1438,1452,1466,1481],"tbody",{},[1408,1424,1425,1430,1435],{},[1426,1427,1428],"td",{},[452,1429,598],{},[1426,1431,1432],{},[452,1433,1434],{},"1s",[1426,1436,1437],{},"ennyit alszik a relay, ha nem tele batch-et kapott",[1408,1439,1440,1444,1449],{},[1426,1441,1442],{},[452,1443,1113],{},[1426,1445,1446],{},[452,1447,1448],{},"100",[1426,1450,1451],{},"egy poll legfeljebb ennyi sort foglal le és publikál",[1408,1453,1454,1458,1463],{},[1426,1455,1456],{},[452,1457,639],{},[1426,1459,1460],{},[452,1461,1462],{},"168h",[1426,1464,1465],{},"a publikált sorok ennyi ideig maradnak meg törlés előtt",[1408,1467,1468,1473,1478],{},[1426,1469,1470],{},[452,1471,1472],{},"OUTBOX_CLEANUP_INTERVAL",[1426,1474,1475],{},[452,1476,1477],{},"1h",[1426,1479,1480],{},"ilyen gyakran fut a publikált sorok takarítása",[1408,1482,1483,1487,1492],{},[1426,1484,1485],{},[452,1486,1159],{},[1426,1488,1489],{},[452,1490,1491],{},"24h",[1426,1493,1494],{},"a publikált taskok asynq-retenciója, egyben a TaskID-dedupe ablaka",[504,1496,1498],{"id":1497},"a-kittel","A kittel",[448,1500,1501,1502,1504,1505,1512,1513,1516,1517,1519,1520,1522,1523,1527,1528,1531,1532,1534],{},"A kiten kívül a migráció lefuttatása és a relay indítása a te felelősséged: az ",[452,1503,1189],{},"-t azzal a migrációs eszközzel alkalmazod, amit a projekted amúgy is használ (a kit saját választása a ",[493,1506,1507,1508,1511],{"href":273},"goose, a ",[452,1509,1510],{},"cmd\u002Fmigrate","-en át","), az ",[452,1514,1515],{},"outbox.Relay","-t pedig magad indítod, a saját asynq szervered mellett. Egy generált projektben a ",[452,1518,320],{},"\u002F",[452,1521,1185],{}," megírja a migrációs fájlt, a ",[493,1524,1526],{"href":1525},"\u002Fhu\u002Fkit\u002Fworker#a-gener%C3%A1lt-cmdworker","worker chassis"," pedig végig a relay életciklusát birtokolja: neked csak az ",[452,1529,1530],{},"outbox.MustNewRelay","-t kell hívnod, és átadnod a ",[452,1533,1098],{},"-nek.",[504,1536,1538],{"id":1537},"használt-patternek","Használt patternek",[448,1540,1541,1542,1545,1546,1549,1550,1552,1553,1555,1556,676],{},"Ez az oldal a ",[493,1543,238],{"href":1544},"\u002Fhu\u002Fconcepts\u002Fdesign-patterns#tranzakci%C3%B3s-outbox"," katalógus ",[499,1547,1548],{},"Tranzakciós outbox"," bejegyzésének teljes kifejtése: a ",[452,1551,602],{}," batch-foglalás és a dual-write probléma itt, kódrészlettel és a shop ",[452,1554,513],{},"-példájával. Kanonikus külső leírás: ",[493,1557,1561],{"href":1558,"rel":1559},"https:\u002F\u002Fmicroservices.io\u002Fpatterns\u002Fdata\u002Ftransactional-outbox.html",[1560],"nofollow","microservices.io: Transactional outbox",[1563,1564,1565],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":462,"searchDepth":706,"depth":706,"links":1567},[1568,1569,1570,1571,1574,1575,1576,1577],{"id":506,"depth":706,"text":507},{"id":554,"depth":706,"text":555},{"id":655,"depth":706,"text":656},{"id":947,"depth":706,"text":948,"children":1572},[1573],{"id":1134,"depth":796,"text":1135},{"id":1170,"depth":706,"text":1171},{"id":1386,"depth":706,"text":204},{"id":1497,"depth":706,"text":1498},{"id":1537,"depth":706,"text":1538},"A tranzakciós outbox minta, az üzleti írás és az event atomikusan, kézbesítési garanciával.","md",null,{},{"icon":75},{"title":72,"description":1578},"brxTJIJd_GPN-JLMJ-8VUR86ZWkPUSggbvA6a9uoNe8",[1586,1588],{"title":67,"path":68,"stem":69,"description":1587,"icon":70,"children":-1},"Eventek és listenerek asynq felett, minden listener önálló, saját retry-keretű task.",{"title":77,"path":78,"stem":79,"description":1589,"icon":80,"children":-1},"Task scheduling kódban, cron-eventek és jobok, replika-biztosan, Valkey-lease leader-electionnel.",1785445883103]