[{"data":1,"prerenderedAt":2276},["ShallowReactive",2],{"navigation_docs_hu":3,"-hu-events-overview":442,"-hu-events-overview-surround":2271},[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":67,"body":444,"description":2264,"extension":2265,"links":2266,"meta":2267,"navigation":2268,"path":68,"seo":2269,"stem":69,"__hash__":2270},"docs_hu\u002Fhu\u002F11.events\u002F1.overview.md",{"type":445,"value":446,"toc":2252},"minimark",[447,458,509,534,550,554,581,636,640,655,777,797,811,815,838,1185,1191,1278,1285,1289,1307,1314,1371,1375,1390,1556,1559,1873,1886,1889,1947,1985,1989,2017,2020,2024,2035,2110,2113,2145,2149,2185,2189,2229,2233,2248],[448,449,450,451,454,455,457],"p",{},"Az eventek dispatcheléséhez és a rájuk feliratkozáshoz add hozzá az ",[452,453,61],"code",{},"-et a ",[452,456,46],{}," mellé:",[459,460,465],"pre",{"className":461,"code":462,"language":463,"meta":464,"style":464},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import (\n    \"github.com\u002Fgp-system\u002Fevents\"\n    \"github.com\u002Fgp-system\u002Fqueue\"\n)\n","go","",[452,466,467,480,493,503],{"__ignoreMap":464},[468,469,472,476],"span",{"class":470,"line":471},"line",1,[468,473,475],{"class":474},"s7zQu","import",[468,477,479],{"class":478},"sMK4o"," (\n",[468,481,483,486,490],{"class":470,"line":482},2,[468,484,485],{"class":478},"    \"",[468,487,489],{"class":488},"sBMFI","github.com\u002Fgp-system\u002Fevents",[468,491,492],{"class":478},"\"\n",[468,494,496,498,501],{"class":470,"line":495},3,[468,497,485],{"class":478},[468,499,500],{"class":488},"github.com\u002Fgp-system\u002Fqueue",[468,502,492],{"class":478},[468,504,506],{"class":470,"line":505},4,[468,507,508],{"class":478},")\n",[448,510,511,512,514,515,520,521,525,526,529,530,533],{},"Az ",[452,513,61],{}," egy önálló event- és listener-modul, a ",[516,517,518],"a",{"href":53},[452,519,46],{}," csomagra épülve: minden listener eleve queue-zott, alapból aszinkron módon fut. Az alkalmazáskód ",[522,523,524],"strong",{},"eldob"," egy eventet, a listenerek típus szerint feliratkoznak, és minden listener ",[522,527,528],{},"önálló asynq taskként"," fut, saját retry-kerettel: egy event N listener-taskra terül szét, és egy hibázó listener újrapróbálkozása soha nem futtatja újra a többit. Bármilyen Go programban működik, kit nélkül is: egy sima ",[452,531,532],{},"net\u002Fhttp"," service, egy CLI-eszköz vagy egy Lambda ugyanígy tud eventet eldobni és listenereket regisztrálni, csak ez a modul és egy Valkey kell hozzá.",[448,535,536,537,540,541,544,545,549],{},"A kézbesítés végig ",[522,538,539],{},"legalább-egyszeres"," (outbox → relay → asynq → listener), ezért két szabály tartja össze az egészet: állapotváltó folyamatban ",[516,542,543],{"href":73},"outboxon"," át dobd el az eventet, a listenereidet pedig írd ",[516,546,548],{"href":547},"#idempotencia","idempotensre",".",[551,552,25],"h2",{"id":553},"telepítés",[459,555,559],{"className":556,"code":557,"language":558,"meta":464,"style":464},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com\u002Fgp-system\u002Fevents@v0.1.0   # a kit is ezt a taget használja\n# vagy: go get github.com\u002Fgp-system\u002Fevents@latest\n","sh",[452,560,561,576],{"__ignoreMap":464},[468,562,563,565,569,572],{"class":470,"line":471},[468,564,463],{"class":488},[468,566,568],{"class":567},"sfazB"," get",[468,570,571],{"class":567}," github.com\u002Fgp-system\u002Fevents@v0.1.0",[468,573,575],{"class":574},"sHwdD","   # a kit is ezt a taget használja\n",[468,577,578],{"class":470,"line":482},[468,579,580],{"class":574},"# vagy: go get github.com\u002Fgp-system\u002Fevents@latest\n",[448,582,511,583,585,586,591,592,597,598,603,604,607,608,611,612,615,616,621,622,607,625,628,629,632,633,635],{},[452,584,61],{}," közvetlenül behúzza a ",[516,587,588],{"href":363},[452,589,590],{},"gp-system\u002Ferrs","-t és a ",[516,593,594],{"href":53},[452,595,596],{},"gp-system\u002Fqueue","-t; a tranzakciós ",[516,599,600],{"href":73},[452,601,602],{},"events\u002Foutbox"," alcsomaghoz ezen felül kell a ",[452,605,606],{},"gp-system\u002Fdbx",", a ",[452,609,610],{},"jackc\u002Fpgx\u002Fv5",", és ha a bun-alapú store-t használod, az ",[452,613,614],{},"uptrace\u002Fbun"," is; az ",[516,617,618],{"href":78},[452,619,620],{},"events\u002Fscheduler"," alcsomagnak a gyökér-modulon túl semmi extra nem kell. A ",[452,623,624],{},"hibiken\u002Fasynq",[452,626,627],{},"redis\u002Fgo-redis\u002Fv9"," és a ",[452,630,631],{},"google\u002Fuuid"," a ",[452,634,46],{},"-n keresztül tranzitívan érkezik. Ehhez semmihez nem kell a kit: importáld azt az alcsomagot, ami kell, és semmi mást.",[551,637,639],{"id":638},"event-definiálása","Event definiálása",[448,641,642,643,646,647,650,651,654],{},"Az event egy sima struct stabil ",[452,644,645],{},"EventName()","-mel. A shop ",[452,648,649],{},"orderPlaced"," eventjét az ",[452,652,653],{},"add event shop orderPlaced"," generálta, a payload-mezőket te adod hozzá:",[459,656,659],{"className":461,"code":657,"filename":658,"language":463,"meta":464,"style":464},"package events\n\ntype OrderPlaced struct {\n    OrderID string `json:\"orderId\"`\n    Email   string `json:\"email\"`\n}\n\nfunc (OrderPlaced) EventName() string { return \"shop.orderPlaced\" }\n","internal\u002Fmodules\u002Fshop\u002Fevents\u002Forder_placed.go",[452,660,661,669,675,689,708,723,729,734],{"__ignoreMap":464},[468,662,663,666],{"class":470,"line":471},[468,664,665],{"class":478},"package",[468,667,668],{"class":488}," events\n",[468,670,671],{"class":470,"line":482},[468,672,674],{"emptyLinePlaceholder":673},true,"\n",[468,676,677,680,683,686],{"class":470,"line":495},[468,678,679],{"class":478},"type",[468,681,682],{"class":488}," OrderPlaced",[468,684,685],{"class":478}," struct",[468,687,688],{"class":478}," {\n",[468,690,691,695,699,702,705],{"class":470,"line":505},[468,692,694],{"class":693},"sTEyZ","    OrderID ",[468,696,698],{"class":697},"spNyl","string",[468,700,701],{"class":478}," `",[468,703,704],{"class":567},"json:\"orderId\"",[468,706,707],{"class":478},"`\n",[468,709,711,714,716,718,721],{"class":470,"line":710},5,[468,712,713],{"class":693},"    Email   ",[468,715,698],{"class":697},[468,717,701],{"class":478},[468,719,720],{"class":567},"json:\"email\"",[468,722,707],{"class":478},[468,724,726],{"class":470,"line":725},6,[468,727,728],{"class":478},"}\n",[468,730,732],{"class":470,"line":731},7,[468,733,674],{"emptyLinePlaceholder":673},[468,735,737,740,743,746,749,753,756,759,762,765,768,771,774],{"class":470,"line":736},8,[468,738,739],{"class":478},"func",[468,741,742],{"class":478}," (",[468,744,745],{"class":488},"OrderPlaced",[468,747,748],{"class":478},")",[468,750,752],{"class":751},"s2Zo4"," EventName",[468,754,755],{"class":478},"()",[468,757,758],{"class":697}," string",[468,760,761],{"class":478}," {",[468,763,764],{"class":474}," return",[468,766,767],{"class":478}," \"",[468,769,770],{"class":567},"shop.orderPlaced",[468,772,773],{"class":478},"\"",[468,775,776],{"class":478}," }\n",[448,778,779,780,783,784,787,788,792,793,796],{},"A generátor névkonvenciója ",[452,781,782],{},"\u003Cmodul>.\u003CeventNév>"," camelCase-ben, ebből lesz a ",[452,785,786],{},"event:shop.orderPlaced"," ",[516,789,791],{"href":790},"\u002Fhu\u002Fqueue\u002Ftasks#task-t%C3%ADpusok","task-típus"," is. A név ",[522,794,795],{},"perzisztálódik"," (az outbox-táblában és a Valkeyben), ezért tartsd stabilan a deployok közt; ha átnevezed, a már bent lévő taskok az új deploy alatt nem találnak handlert.",[798,799,511,800,802,803,806,807,810],"warning",{},[452,801,645],{},"-nek a típus ",[522,804,805],{},"zero value-ján"," is működnie kell: érték típust regisztrálj, ne pointert. A ",[452,808,809],{},"Listen"," a zero value-ból olvassa ki a nevet, és startupkor azonnal panikol, ha az üres vagy a hívás elszáll, így a hibás regisztráció nem jut el prodig.",[551,812,814],{"id":813},"dispatch","Dispatch",[448,816,817,818,821,822,825,826,829,830,833,834,837],{},"A ",[452,819,820],{},"Dispatcher"," a modul ",[452,823,824],{},"Dependencies","-ébe injektálódik (az első ",[452,827,828],{},"add event"," drótozza be mindkét belépési pontba). A shop rendelési szabálya (a modul ",[452,831,832],{},"core\u002F"," csomagjában) a tranzakción ",[522,835,836],{},"belül"," dobja el az eventet:",[459,839,842],{"className":461,"code":840,"filename":841,"language":463,"meta":464,"style":464},"func (s *Service) PlaceOrder(ctx context.Context, in PlaceOrderInput) (Order, error) {\n    var order Order\n    err := s.tx.WithinTransaction(ctx, func(ctx context.Context) error {\n        var err error\n        if order, err = s.orders.Insert(ctx, in); err != nil {\n            return err\n        }\n        if err = s.stock.Decrement(ctx, in.Items); err != nil {\n            return err\n        }\n        return s.dispatcher.Dispatch(ctx, events.OrderPlaced{\n            OrderID: order.ID,\n            Email:   order.Email,\n        })\n    })\n    return order, err\n}\n","internal\u002Fmodules\u002Fshop\u002Fcore\u002Fcore.go",[452,843,844,904,915,959,970,1018,1026,1031,1074,1081,1086,1119,1138,1156,1162,1168,1180],{"__ignoreMap":464},[468,845,846,848,850,854,857,860,862,865,868,871,874,876,879,882,885,888,890,892,895,897,900,902],{"class":470,"line":471},[468,847,739],{"class":478},[468,849,742],{"class":478},[468,851,853],{"class":852},"sHdIc","s ",[468,855,856],{"class":478},"*",[468,858,859],{"class":488},"Service",[468,861,748],{"class":478},[468,863,864],{"class":751}," PlaceOrder",[468,866,867],{"class":478},"(",[468,869,870],{"class":852},"ctx",[468,872,873],{"class":488}," context",[468,875,549],{"class":478},[468,877,878],{"class":488},"Context",[468,880,881],{"class":478},",",[468,883,884],{"class":852}," in",[468,886,887],{"class":488}," PlaceOrderInput",[468,889,748],{"class":478},[468,891,742],{"class":478},[468,893,894],{"class":488},"Order",[468,896,881],{"class":478},[468,898,899],{"class":697}," error",[468,901,748],{"class":478},[468,903,688],{"class":478},[468,905,906,909,912],{"class":470,"line":482},[468,907,908],{"class":478},"    var",[468,910,911],{"class":693}," order ",[468,913,914],{"class":488},"Order\n",[468,916,917,920,923,926,928,931,933,936,938,940,942,945,947,949,951,953,955,957],{"class":470,"line":495},[468,918,919],{"class":693},"    err ",[468,921,922],{"class":478},":=",[468,924,925],{"class":693}," s",[468,927,549],{"class":478},[468,929,930],{"class":693},"tx",[468,932,549],{"class":478},[468,934,935],{"class":751},"WithinTransaction",[468,937,867],{"class":478},[468,939,870],{"class":693},[468,941,881],{"class":478},[468,943,944],{"class":478}," func(",[468,946,870],{"class":852},[468,948,873],{"class":488},[468,950,549],{"class":478},[468,952,878],{"class":488},[468,954,748],{"class":478},[468,956,899],{"class":697},[468,958,688],{"class":478},[468,960,961,964,967],{"class":470,"line":505},[468,962,963],{"class":478},"        var",[468,965,966],{"class":693}," err ",[468,968,969],{"class":697},"error\n",[468,971,972,975,978,980,982,985,987,989,992,994,997,999,1001,1003,1005,1008,1010,1013,1016],{"class":470,"line":710},[468,973,974],{"class":474},"        if",[468,976,977],{"class":693}," order",[468,979,881],{"class":478},[468,981,966],{"class":693},[468,983,984],{"class":478},"=",[468,986,925],{"class":693},[468,988,549],{"class":478},[468,990,991],{"class":693},"orders",[468,993,549],{"class":478},[468,995,996],{"class":751},"Insert",[468,998,867],{"class":478},[468,1000,870],{"class":693},[468,1002,881],{"class":478},[468,1004,884],{"class":693},[468,1006,1007],{"class":478},");",[468,1009,966],{"class":693},[468,1011,1012],{"class":478},"!=",[468,1014,1015],{"class":478}," nil",[468,1017,688],{"class":478},[468,1019,1020,1023],{"class":470,"line":725},[468,1021,1022],{"class":474},"            return",[468,1024,1025],{"class":693}," err\n",[468,1027,1028],{"class":470,"line":731},[468,1029,1030],{"class":478},"        }\n",[468,1032,1033,1035,1037,1039,1041,1043,1046,1048,1051,1053,1055,1057,1059,1061,1064,1066,1068,1070,1072],{"class":470,"line":736},[468,1034,974],{"class":474},[468,1036,966],{"class":693},[468,1038,984],{"class":478},[468,1040,925],{"class":693},[468,1042,549],{"class":478},[468,1044,1045],{"class":693},"stock",[468,1047,549],{"class":478},[468,1049,1050],{"class":751},"Decrement",[468,1052,867],{"class":478},[468,1054,870],{"class":693},[468,1056,881],{"class":478},[468,1058,884],{"class":693},[468,1060,549],{"class":478},[468,1062,1063],{"class":693},"Items",[468,1065,1007],{"class":478},[468,1067,966],{"class":693},[468,1069,1012],{"class":478},[468,1071,1015],{"class":478},[468,1073,688],{"class":478},[468,1075,1077,1079],{"class":470,"line":1076},9,[468,1078,1022],{"class":474},[468,1080,1025],{"class":693},[468,1082,1084],{"class":470,"line":1083},10,[468,1085,1030],{"class":478},[468,1087,1089,1092,1094,1096,1099,1101,1103,1105,1107,1109,1112,1114,1116],{"class":470,"line":1088},11,[468,1090,1091],{"class":474},"        return",[468,1093,925],{"class":693},[468,1095,549],{"class":478},[468,1097,1098],{"class":693},"dispatcher",[468,1100,549],{"class":478},[468,1102,814],{"class":751},[468,1104,867],{"class":478},[468,1106,870],{"class":693},[468,1108,881],{"class":478},[468,1110,1111],{"class":488}," events",[468,1113,549],{"class":478},[468,1115,745],{"class":488},[468,1117,1118],{"class":478},"{\n",[468,1120,1122,1125,1128,1130,1132,1135],{"class":470,"line":1121},12,[468,1123,1124],{"class":693},"            OrderID",[468,1126,1127],{"class":478},":",[468,1129,977],{"class":693},[468,1131,549],{"class":478},[468,1133,1134],{"class":693},"ID",[468,1136,1137],{"class":478},",\n",[468,1139,1141,1144,1146,1149,1151,1154],{"class":470,"line":1140},13,[468,1142,1143],{"class":693},"            Email",[468,1145,1127],{"class":478},[468,1147,1148],{"class":693},"   order",[468,1150,549],{"class":478},[468,1152,1153],{"class":693},"Email",[468,1155,1137],{"class":478},[468,1157,1159],{"class":470,"line":1158},14,[468,1160,1161],{"class":478},"        })\n",[468,1163,1165],{"class":470,"line":1164},15,[468,1166,1167],{"class":478},"    })\n",[468,1169,1171,1174,1176,1178],{"class":470,"line":1170},16,[468,1172,1173],{"class":474},"    return",[468,1175,977],{"class":693},[468,1177,881],{"class":478},[468,1179,1025],{"class":693},[468,1181,1183],{"class":470,"line":1182},17,[468,1184,728],{"class":478},[448,1186,511,1187,1190],{},[452,1188,1189],{},"events.Dispatcher"," interfészt három implementáció elégíti ki:",[1192,1193,1194,1210],"table",{},[1195,1196,1197],"thead",{},[1198,1199,1200,1204,1207],"tr",{},[1201,1202,1203],"th",{},"Konstruktor",[1201,1205,1206],{},"Viselkedés",[1201,1208,1209],{},"Mikor",[1211,1212,1213,1241,1261],"tbody",{},[1198,1214,1215,1223,1234],{},[1216,1217,1218],"td",{},[516,1219,1220],{"href":73},[452,1221,1222],{},"outbox.NewDispatcher(store)",[1216,1224,1225,1226,1229,1230,1233],{},"az eventet az ",[452,1227,1228],{},"outbox_events"," táblába írja ",[522,1231,1232],{},"a hívó tranzakciójában","; egy relay továbbítja Valkeybe",[1216,1235,1236,1237,1240],{},"állapotváltó folyamatok, ",[522,1238,1239],{},"a generált alapértelmezés",", a shop is ezt használja",[1198,1242,1243,1248,1258],{},[1216,1244,1245],{},[452,1246,1247],{},"events.NewDispatcher(client)",[1216,1249,1250,1251,1257],{},"közvetlenül Valkeybe enqueue-l (",[516,1252,1254],{"href":1253},"\u002Fhu\u002Fqueue\u002Foverview#client",[452,1255,1256],{},"queue.Client","-en át)",[1216,1259,1260],{},"fire-and-forget: ha a folyamat a DB-commit és az enqueue közt hal le, az event elvész, ott jó, ahol ez elfogadható",[1198,1262,1263,1268,1275],{},[1216,1264,1265],{},[452,1266,1267],{},"events.NewSyncDispatcher(reg)",[1216,1269,1270,1271,1274],{},"inline futtatja a regisztrált listenereket, a hívó goroutine-jában és tranzakciójában; a listener-hibákat ",[452,1272,1273],{},"errors.Join","-nal adja vissza",[1216,1276,1277],{},"unit tesztek és lokális tooling",[448,1279,1280,1281,1284],{},"Hogy miért az outbox az alapértelmezés, és mi a baj a közvetlen enqueue-val állapotváltásnál, azt az ",[516,1282,1283],{"href":73},"outbox oldal"," fejti ki.",[551,1286,1288],{"id":1287},"a-boríték-és-a-kézbesítési-metaadat","A boríték és a kézbesítési metaadat",[448,1290,1291,1292,1295,1296,1303,1304,1306],{},"Dispatchkor az ",[452,1293,1294],{},"events.NewEnvelope(ctx, ev)"," épít egy ",[516,1297,1299,1302],{"href":1298},"\u002Fhu\u002Fqueue\u002Ftasks#a-bor%C3%ADt%C3%A9k-envelope",[452,1300,1301],{},"queue.Envelope","-ot",": friss UUID (",[452,1305,1134],{},"), az event neve, a JSON-payload, a context trace-kontextusa és az időbélyeg. Bármelyik dispatchert használod, a listener ugyanazt a borítékot kapja.",[448,1308,1309,1310,1313],{},"A worker a listener hívása előtt a borítékból kézbesítési metaadatot tesz a contextre: a listener az ",[452,1311,1312],{},"events.MetaFromContext(ctx)","-szel olvassa:",[1192,1315,1316,1326],{},[1195,1317,1318],{},[1198,1319,1320,1323],{},[1201,1321,1322],{},"Mező",[1201,1324,1325],{},"Jelentés",[1211,1327,1328,1341,1351,1361],{},[1198,1329,1330,1334],{},[1216,1331,1332],{},[452,1333,1134],{},[1216,1335,1336,1337,1340],{},"a boríték id-ja, ",[522,1338,1339],{},"stabil idempotencia-kulcs"," a retryk és az event összes listenere közt",[1198,1342,1343,1348],{},[1216,1344,1345],{},[452,1346,1347],{},"Name",[1216,1349,1350],{},"az event neve",[1198,1352,1353,1358],{},[1216,1354,1355],{},[452,1356,1357],{},"OccurredAt",[1216,1359,1360],{},"mikor dobták el az eventet",[1198,1362,1363,1368],{},[1216,1364,1365],{},[452,1366,1367],{},"Attempt",[1216,1369,1370],{},"hányadik kísérlet ez (0 az első kézbesítéskor)",[551,1372,1374],{"id":1373},"listenerek","Listenerek",[448,1376,1377,1378,1381,1382,1385,1386,1389],{},"A listenereket a generikus ",[452,1379,1380],{},"events.Listen[T]"," regisztrálja: az event típusát a handler szignatúrája adja, kézi típus-assertion nincs. Az ",[452,1383,1384],{},"add listener shop orderPlaced sendOrderConfirmation --queue mail"," két dolgot generál. A regisztrációs sort a modul ",[452,1387,1388],{},"listeners\u002Fregister.go","-jába:",[459,1391,1394],{"className":461,"code":1392,"filename":1393,"language":463,"meta":464,"style":464},"package listeners\n\nimport (\n    \"github.com\u002Facme\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\"\n\n    \"github.com\u002Fgp-system\u002Fevents\"\n    \"github.com\u002Fgp-system\u002Fqueue\"\n    \u002F\u002F gpsystem:worker-imports\n)\n\nfunc Register(reg *events.Registry, deps shop.Dependencies) {\n    events.Listen(reg, \"sendOrderConfirmation\", sendOrderConfirmation(deps), queue.OnQueue(\"mail\"))\n    \u002F\u002F gpsystem:listeners\n}\n","internal\u002Fmodules\u002Fshop\u002Flisteners\u002Fregister.go",[452,1395,1396,1403,1407,1413,1422,1426,1434,1442,1447,1451,1455,1493,1547,1552],{"__ignoreMap":464},[468,1397,1398,1400],{"class":470,"line":471},[468,1399,665],{"class":478},[468,1401,1402],{"class":488}," listeners\n",[468,1404,1405],{"class":470,"line":482},[468,1406,674],{"emptyLinePlaceholder":673},[468,1408,1409,1411],{"class":470,"line":495},[468,1410,475],{"class":474},[468,1412,479],{"class":478},[468,1414,1415,1417,1420],{"class":470,"line":505},[468,1416,485],{"class":478},[468,1418,1419],{"class":488},"github.com\u002Facme\u002Fshop\u002Finternal\u002Fmodules\u002Fshop",[468,1421,492],{"class":478},[468,1423,1424],{"class":470,"line":710},[468,1425,674],{"emptyLinePlaceholder":673},[468,1427,1428,1430,1432],{"class":470,"line":725},[468,1429,485],{"class":478},[468,1431,489],{"class":488},[468,1433,492],{"class":478},[468,1435,1436,1438,1440],{"class":470,"line":731},[468,1437,485],{"class":478},[468,1439,500],{"class":488},[468,1441,492],{"class":478},[468,1443,1444],{"class":470,"line":736},[468,1445,1446],{"class":574},"    \u002F\u002F gpsystem:worker-imports\n",[468,1448,1449],{"class":470,"line":1076},[468,1450,508],{"class":478},[468,1452,1453],{"class":470,"line":1083},[468,1454,674],{"emptyLinePlaceholder":673},[468,1456,1457,1459,1462,1464,1467,1470,1472,1474,1477,1479,1482,1485,1487,1489,1491],{"class":470,"line":1088},[468,1458,739],{"class":478},[468,1460,1461],{"class":751}," Register",[468,1463,867],{"class":478},[468,1465,1466],{"class":852},"reg",[468,1468,1469],{"class":478}," *",[468,1471,61],{"class":488},[468,1473,549],{"class":478},[468,1475,1476],{"class":488},"Registry",[468,1478,881],{"class":478},[468,1480,1481],{"class":852}," deps",[468,1483,1484],{"class":488}," shop",[468,1486,549],{"class":478},[468,1488,824],{"class":488},[468,1490,748],{"class":478},[468,1492,688],{"class":478},[468,1494,1495,1498,1500,1502,1504,1506,1508,1510,1513,1515,1517,1520,1522,1525,1528,1531,1533,1536,1538,1540,1542,1544],{"class":470,"line":1121},[468,1496,1497],{"class":693},"    events",[468,1499,549],{"class":478},[468,1501,809],{"class":751},[468,1503,867],{"class":478},[468,1505,1466],{"class":693},[468,1507,881],{"class":478},[468,1509,767],{"class":478},[468,1511,1512],{"class":567},"sendOrderConfirmation",[468,1514,773],{"class":478},[468,1516,881],{"class":478},[468,1518,1519],{"class":751}," sendOrderConfirmation",[468,1521,867],{"class":478},[468,1523,1524],{"class":693},"deps",[468,1526,1527],{"class":478},"),",[468,1529,1530],{"class":693}," queue",[468,1532,549],{"class":478},[468,1534,1535],{"class":751},"OnQueue",[468,1537,867],{"class":478},[468,1539,773],{"class":478},[468,1541,113],{"class":567},[468,1543,773],{"class":478},[468,1545,1546],{"class":478},"))\n",[468,1548,1549],{"class":470,"line":1140},[468,1550,1551],{"class":574},"    \u002F\u002F gpsystem:listeners\n",[468,1553,1554],{"class":470,"line":1158},[468,1555,728],{"class":478},[448,1557,1558],{},"És a listener-stubot külön fájlba: a törzs a tiéd, itt a shop kitöltött változata:",[459,1560,1563],{"className":461,"code":1561,"filename":1562,"language":463,"meta":464,"style":464},"package listeners\n\nimport (\n    \"context\"\n\n    \"github.com\u002Fgp-system\u002Fmail\"\n    \"github.com\u002Fgp-system\u002Fmail\u002Fmjml\"\n\n    \"github.com\u002Facme\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\"\n    shopevents \"github.com\u002Facme\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\u002Fevents\"\n)\n\nfunc sendOrderConfirmation(deps shop.Dependencies) func(context.Context, shopevents.OrderPlaced) error {\n    return func(ctx context.Context, ev shopevents.OrderPlaced) error {\n        msg := mail.NewMessage().\n            WithTo(ev.Email).\n            WithSubject(\"Rendelésed visszaigazolása\").\n            WithBody(mjml.Template(templates, \"templates\u002Forder_confirmation.mjml.tmpl\",\n                map[string]any{\"OrderID\": ev.OrderID}))\n        return deps.Mailer.Send(ctx, msg)\n    }\n}\n","internal\u002Fmodules\u002Fshop\u002Flisteners\u002Fsend_order_confirmation.go",[452,1564,1565,1571,1575,1581,1590,1594,1603,1612,1616,1624,1636,1640,1644,1685,1716,1734,1751,1767,1799,1834,1862,1868],{"__ignoreMap":464},[468,1566,1567,1569],{"class":470,"line":471},[468,1568,665],{"class":478},[468,1570,1402],{"class":488},[468,1572,1573],{"class":470,"line":482},[468,1574,674],{"emptyLinePlaceholder":673},[468,1576,1577,1579],{"class":470,"line":495},[468,1578,475],{"class":474},[468,1580,479],{"class":478},[468,1582,1583,1585,1588],{"class":470,"line":505},[468,1584,485],{"class":478},[468,1586,1587],{"class":488},"context",[468,1589,492],{"class":478},[468,1591,1592],{"class":470,"line":710},[468,1593,674],{"emptyLinePlaceholder":673},[468,1595,1596,1598,1601],{"class":470,"line":725},[468,1597,485],{"class":478},[468,1599,1600],{"class":488},"github.com\u002Fgp-system\u002Fmail",[468,1602,492],{"class":478},[468,1604,1605,1607,1610],{"class":470,"line":731},[468,1606,485],{"class":478},[468,1608,1609],{"class":488},"github.com\u002Fgp-system\u002Fmail\u002Fmjml",[468,1611,492],{"class":478},[468,1613,1614],{"class":470,"line":736},[468,1615,674],{"emptyLinePlaceholder":673},[468,1617,1618,1620,1622],{"class":470,"line":1076},[468,1619,485],{"class":478},[468,1621,1419],{"class":488},[468,1623,492],{"class":478},[468,1625,1626,1629,1631,1634],{"class":470,"line":1083},[468,1627,1628],{"class":693},"    shopevents ",[468,1630,773],{"class":478},[468,1632,1633],{"class":488},"github.com\u002Facme\u002Fshop\u002Finternal\u002Fmodules\u002Fshop\u002Fevents",[468,1635,492],{"class":478},[468,1637,1638],{"class":470,"line":1088},[468,1639,508],{"class":478},[468,1641,1642],{"class":470,"line":1121},[468,1643,674],{"emptyLinePlaceholder":673},[468,1645,1646,1648,1650,1652,1654,1656,1658,1660,1662,1664,1666,1668,1670,1672,1675,1677,1679,1681,1683],{"class":470,"line":1140},[468,1647,739],{"class":478},[468,1649,1519],{"class":751},[468,1651,867],{"class":478},[468,1653,1524],{"class":852},[468,1655,1484],{"class":488},[468,1657,549],{"class":478},[468,1659,824],{"class":488},[468,1661,748],{"class":478},[468,1663,944],{"class":478},[468,1665,1587],{"class":488},[468,1667,549],{"class":478},[468,1669,878],{"class":488},[468,1671,881],{"class":478},[468,1673,1674],{"class":488}," shopevents",[468,1676,549],{"class":478},[468,1678,745],{"class":488},[468,1680,748],{"class":478},[468,1682,899],{"class":697},[468,1684,688],{"class":478},[468,1686,1687,1689,1691,1693,1695,1697,1699,1701,1704,1706,1708,1710,1712,1714],{"class":470,"line":1158},[468,1688,1173],{"class":474},[468,1690,944],{"class":478},[468,1692,870],{"class":852},[468,1694,873],{"class":488},[468,1696,549],{"class":478},[468,1698,878],{"class":488},[468,1700,881],{"class":478},[468,1702,1703],{"class":852}," ev",[468,1705,1674],{"class":488},[468,1707,549],{"class":478},[468,1709,745],{"class":488},[468,1711,748],{"class":478},[468,1713,899],{"class":697},[468,1715,688],{"class":478},[468,1717,1718,1721,1723,1726,1728,1731],{"class":470,"line":1164},[468,1719,1720],{"class":693},"        msg ",[468,1722,922],{"class":478},[468,1724,1725],{"class":693}," mail",[468,1727,549],{"class":478},[468,1729,1730],{"class":751},"NewMessage",[468,1732,1733],{"class":478},"().\n",[468,1735,1736,1739,1741,1744,1746,1748],{"class":470,"line":1170},[468,1737,1738],{"class":751},"            WithTo",[468,1740,867],{"class":478},[468,1742,1743],{"class":693},"ev",[468,1745,549],{"class":478},[468,1747,1153],{"class":693},[468,1749,1750],{"class":478},").\n",[468,1752,1753,1756,1758,1760,1763,1765],{"class":470,"line":1182},[468,1754,1755],{"class":751},"            WithSubject",[468,1757,867],{"class":478},[468,1759,773],{"class":478},[468,1761,1762],{"class":567},"Rendelésed visszaigazolása",[468,1764,773],{"class":478},[468,1766,1750],{"class":478},[468,1768,1770,1773,1775,1778,1780,1783,1785,1788,1790,1792,1795,1797],{"class":470,"line":1769},18,[468,1771,1772],{"class":751},"            WithBody",[468,1774,867],{"class":478},[468,1776,1777],{"class":693},"mjml",[468,1779,549],{"class":478},[468,1781,1782],{"class":751},"Template",[468,1784,867],{"class":478},[468,1786,1787],{"class":693},"templates",[468,1789,881],{"class":478},[468,1791,767],{"class":478},[468,1793,1794],{"class":567},"templates\u002Forder_confirmation.mjml.tmpl",[468,1796,773],{"class":478},[468,1798,1137],{"class":478},[468,1800,1802,1805,1807,1810,1813,1816,1818,1821,1823,1825,1827,1829,1831],{"class":470,"line":1801},19,[468,1803,1804],{"class":478},"                map[",[468,1806,698],{"class":697},[468,1808,1809],{"class":478},"]",[468,1811,1812],{"class":488},"any",[468,1814,1815],{"class":478},"{",[468,1817,773],{"class":478},[468,1819,1820],{"class":567},"OrderID",[468,1822,773],{"class":478},[468,1824,1127],{"class":478},[468,1826,1703],{"class":693},[468,1828,549],{"class":478},[468,1830,1820],{"class":693},[468,1832,1833],{"class":478},"}))\n",[468,1835,1837,1839,1841,1843,1846,1848,1851,1853,1855,1857,1860],{"class":470,"line":1836},20,[468,1838,1091],{"class":474},[468,1840,1481],{"class":693},[468,1842,549],{"class":478},[468,1844,1845],{"class":693},"Mailer",[468,1847,549],{"class":478},[468,1849,1850],{"class":751},"Send",[468,1852,867],{"class":478},[468,1854,870],{"class":693},[468,1856,881],{"class":478},[468,1858,1859],{"class":693}," msg",[468,1861,508],{"class":478},[468,1863,1865],{"class":470,"line":1864},21,[468,1866,1867],{"class":478},"    }\n",[468,1869,1871],{"class":470,"line":1870},22,[468,1872,728],{"class":478},[448,1874,1875,1876,1878,1879,1881,1882,1885],{},"(A ",[452,1877,113],{},"\u002F",[452,1880,1777],{}," API-hoz lásd az ",[516,1883,1884],{"href":119},"E-mail oldalt",".)",[448,1887,1888],{},"Amit a regisztrációról tudni kell:",[1890,1891,1892,1906,1937],"ul",{},[1893,1894,817,1895,1898,1899,1901,1902,1905],"li",{},[522,1896,1897],{},"név"," (a ",[452,1900,809],{}," 2. argumentuma) eventenként egyedi; ebből lesz a ",[452,1903,1904],{},"listener:shop.orderPlaced:sendOrderConfirmation"," task-típus, ami a worker logjaiban és az Asynqmonban is látszik. Ugyanarra a (event, név) párra kétszer regisztrálni startup-panik.",[1893,1907,1908,1909,1916,1917,1920,1921,1923,1924,1928,1929,1932,1933,1936],{},"A további argumentumok ",[522,1910,1911,1912],{},"listenerenkénti ",[516,1913,1915],{"href":1914},"\u002Fhu\u002Fqueue\u002Ftasks#enqueue-opci%C3%B3k","enqueue-opciók",": ",[452,1918,1919],{},"queue.OnQueue"," a queue-hoz (a shop levelei a ",[452,1922,113],{}," queue-ba mennek, hogy a ",[516,1925,1927],{"href":1926},"\u002Fhu\u002Fkit\u002Fworker#queue-priorit%C3%A1sok","worker súlyozhassa"," őket), ",[452,1930,1931],{},"queue.MaxRetry",", ",[452,1934,1935],{},"queue.Timeout"," a retry-kerethez.",[1893,1938,1939,1940,1943,1944,1946],{},"Másik modul eventjére a ",[452,1941,1942],{},"add listener \u003Cmodul> \u003Cproducer>.\u003Cevent> \u003Cnév>"," formával iratkozol fel: az event típusát a producer ",[452,1945,61],{}," csomagjából importálod.",[448,1948,817,1949,1951,1952,1955,1956,1959,1960,1963,1964,1968,1969,1972,1973,1976,1977,1980,1981,1984],{},[452,1950,1476],{}," ezen felül ",[452,1953,1954],{},"EventNames() []string","-et, ",[452,1957,1958],{},"FanoutTask(env queue.Envelope) ([]FanoutTask, error)","-t és ",[452,1961,1962],{},"Handler(taskType string) (func(context.Context, queue.Envelope) error, bool)","-t is ad: ezekkel bontja ki a ",[516,1965,1967],{"href":1966},"\u002Fhu\u002Fkit\u002Fworker#mi-dolgozza-fel-a-taskokat","worker chassis"," az ",[452,1970,1971],{},"event:"," taskot listener-taskokra, és irányítja a ",[452,1974,1975],{},"listener:"," taskot a megfelelő függvényhez. Ezekhez csak akkor nyúlj közvetlenül, ha a kit ",[452,1978,1979],{},"worker"," csomagja nélkül drótozol be egy fogyasztót; a kittel a ",[452,1982,1983],{},"worker.Run"," mindezt elvégzi helyetted.",[551,1986,1988],{"id":1987},"fan-out-hogyan-lesz-egy-eventből-n-task","Fan-out: hogyan lesz egy eventből N task",[448,1990,1991,1992,1994,1995,787,1998,2001,2002,2005,2006,2009,2010,2016],{},"A worker az ",[452,1993,786],{}," taskot kibontja, és ",[522,1996,1997],{},"listenerenként egy",[452,1999,2000],{},"listener:..."," taskot enqueue-l. Minden listener-task determinisztikus ",[452,2003,2004],{},"TaskID","-t kap (",[452,2007,2008],{},"\u003Cboríték-id>:\u003Clistener-név>","), így ha a fan-out félbeszakad és újrafut, a már beadott taskok ",[516,2011,2012,2015],{"href":1253},[452,2013,2014],{},"ErrDuplicate","-ként"," no-opok: a fan-out maga is idempotens.",[448,2018,2019],{},"Innentől minden listener a saját életét éli: külön queue-ban lehet, külön retry-keretet fogyaszt, és a hibája csak őt futtatja újra. Ez az alapból-mindig-aszinkron viselkedés (nem egy szinkron event-loop) a csomag meghatározó tulajdonsága, és az ára az idempotencia-követelmény.",[551,2021,2023],{"id":2022},"idempotencia","Idempotencia",[448,2025,2026,2027,2030,2031,2034],{},"Legalább-egyszeres kézbesítés mellett egy listener ",[522,2028,2029],{},"többször is lefuthat ugyanarra az eventre"," (retry, worker-crash a feldolgozás közben, relay-újraküldés). A ",[452,2032,2033],{},"Meta.ID"," erre a stabil kulcs: ugyanannál a dispatchnél minden kísérletben ugyanaz.",[459,2036,2038],{"className":461,"code":2037,"language":463,"meta":464,"style":464},"meta, _ := events.MetaFromContext(ctx)\n\u002F\u002F pl. egyedi kulcs a \"megtörtént már?\" táblában, vagy a mail-szolgáltató\n\u002F\u002F idempotency kulcsa:\nreturn deps.Mailer.SendOnce(ctx, meta.ID, msg)\n",[452,2039,2040,2065,2070,2075],{"__ignoreMap":464},[468,2041,2042,2045,2047,2050,2052,2054,2056,2059,2061,2063],{"class":470,"line":471},[468,2043,2044],{"class":693},"meta",[468,2046,881],{"class":478},[468,2048,2049],{"class":693}," _ ",[468,2051,922],{"class":478},[468,2053,1111],{"class":693},[468,2055,549],{"class":478},[468,2057,2058],{"class":751},"MetaFromContext",[468,2060,867],{"class":478},[468,2062,870],{"class":693},[468,2064,508],{"class":478},[468,2066,2067],{"class":470,"line":482},[468,2068,2069],{"class":574},"\u002F\u002F pl. egyedi kulcs a \"megtörtént már?\" táblában, vagy a mail-szolgáltató\n",[468,2071,2072],{"class":470,"line":495},[468,2073,2074],{"class":574},"\u002F\u002F idempotency kulcsa:\n",[468,2076,2077,2080,2082,2084,2086,2088,2091,2093,2095,2097,2100,2102,2104,2106,2108],{"class":470,"line":505},[468,2078,2079],{"class":474},"return",[468,2081,1481],{"class":693},[468,2083,549],{"class":478},[468,2085,1845],{"class":693},[468,2087,549],{"class":478},[468,2089,2090],{"class":751},"SendOnce",[468,2092,867],{"class":478},[468,2094,870],{"class":693},[468,2096,881],{"class":478},[468,2098,2099],{"class":693}," meta",[468,2101,549],{"class":478},[468,2103,1134],{"class":693},[468,2105,881],{"class":478},[468,2107,1859],{"class":693},[468,2109,508],{"class":478},[448,2111,2112],{},"Praktikus minták:",[1890,2114,2115,2125,2135],{},[1893,2116,2117,2120,2121,2124],{},[522,2118,2119],{},"Természetes kulcs",": ha a mellékhatás DB-írás, ",[452,2122,2123],{},"INSERT ... ON CONFLICT DO NOTHING"," az event id-ra (vagy az üzleti kulcsra).",[1893,2126,2127,2130,2131,2134],{},[522,2128,2129],{},"Külső API",": add át a ",[452,2132,2133],{},"meta.ID","-t idempotency-key headerként, ha a szolgáltató támogatja.",[1893,2136,2137,2140,2141,2144],{},[522,2138,2139],{},"Olvasás + feltétel",": a \"már elküldtük?\" ellenőrzés és a küldés közt maradó versenyt csak kulcs-alapú megoldás zárja be, a puszta ",[452,2142,2143],{},"SELECT","-tel ne elégedj meg.",[551,2146,2148],{"id":2147},"hol-futnak-a-listenerek","Hol futnak a listenerek",[448,2150,2151,2152,2155,2156,2159,2160,2163,2164,2167,2168,2171,2172,2175,2176,1932,2178,2181,2182,549],{},"A listenerek a ",[516,2153,2154],{"href":264},"worker binárisban"," futnak: a modulonkénti ",[452,2157,2158],{},"listeners"," alcsomagok ",[452,2161,2162],{},"Register"," függvényeit a generált ",[452,2165,2166],{},"cmd\u002Fworker\u002Fmain.go"," komponálja egyetlen ",[452,2169,2170],{},"events.Registry","-be. Ütemezett event-tüzeléshez (cron szerint dispatchelt eventek) lásd az ",[516,2173,2174],{"href":78},"ütemezőt","; a generátorparancsok (",[452,2177,828],{},[452,2179,2180],{},"add listener",") részleteihez a ",[516,2183,2184],{"href":350},"CLI worker-generátorokat",[551,2186,2188],{"id":2187},"a-kittel","A kittel",[448,2190,817,2191,2193,2194,2196,2197,2199,2200,2202,2203,2206,2207,1878,2209,2212,2213,2215,2216,2202,2220,2224,2225,2228],{},[452,2192,320],{}," a kezdetektől bedrótozza az ",[452,2195,61],{},"-et: az ",[452,2198,828],{},", az ",[452,2201,2180],{}," és az ",[452,2204,2205],{},"add job"," generálja a fenti ",[452,2208,1476],{},[452,2210,2211],{},"Schedule","-kompozíciót, és a ",[516,2214,1967],{"href":264}," az, ami ténylegesen futtatja (a saját asynq szervere mellett az ",[516,2217,2219],{"href":2218},"\u002Fhu\u002Fevents\u002Foutbox#a-relay","outbox relay-t",[516,2221,2223],{"href":2222},"\u002Fhu\u002Fevents\u002Fscheduler#replika-biztons%C3%A1g-a-leader-election","ütemező-futtatót"," is). Ehhez semmi nem szükséges a kitből: kit nélkül saját asynq szervert építesz, és a ",[452,2226,2227],{},"reg.Handler(taskType)","-pel regisztrálod a rád tartozó task-típusokat.",[551,2230,2232],{"id":2231},"használt-patternek","Használt patternek",[448,2234,2235,742,2238,2240,2241,2243,2244,549],{},[522,2236,2237],{},"Legalább-egyszeres kézbesítés + idempotens listener-szerződés",[452,2239,2033],{}," mint dedup-kulcs, determinisztikus ",[452,2242,2004],{}," a fan-outban): lásd a ",[516,2245,2247],{"href":2246},"\u002Fhu\u002Fconcepts\u002Fdesign-patterns#legal%C3%A1bb-egyszeres-k%C3%A9zbes%C3%ADt%C3%A9s--idempotens-listener","Design patterneket",[2249,2250,2251],"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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":464,"searchDepth":482,"depth":482,"links":2253},[2254,2255,2256,2257,2258,2259,2260,2261,2262,2263],{"id":553,"depth":482,"text":25},{"id":638,"depth":482,"text":639},{"id":813,"depth":482,"text":814},{"id":1287,"depth":482,"text":1288},{"id":1373,"depth":482,"text":1374},{"id":1987,"depth":482,"text":1988},{"id":2022,"depth":482,"text":2023},{"id":2147,"depth":482,"text":2148},{"id":2187,"depth":482,"text":2188},{"id":2231,"depth":482,"text":2232},"Eventek és listenerek asynq felett, minden listener önálló, saját retry-keretű task.","md",null,{},{"icon":70},{"title":67,"description":2264},"JixHmcXorDIstd3XQruKe1XLuRM8QTThn6iYzTDZCBw",[2272,2274],{"title":57,"path":58,"stem":59,"description":2273,"icon":47,"children":-1},"Enqueue-opciók, az event-boríték, OTel trace-propagáció a queue-n át, és a task-típus-elnevezési konvenciók.",{"title":72,"path":73,"stem":74,"description":2275,"icon":75,"children":-1},"A tranzakciós outbox minta, az üzleti írás és az event atomikusan, kézbesítési garanciával.",1785445881691]