[{"data":1,"prerenderedAt":1462},["ShallowReactive",2],{"navigation_docs_hu":3,"-hu-framework-app":449,"-hu-framework-app-surround":1457},[4,45,120,158,174,204,234,260,272,288,308,327,340,357,374,387,399,426],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Kezdő lépések","i-lucide-rocket","\u002Fhu\u002Fgetting-started","hu\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"Bevezetés","\u002Fhu\u002Fgetting-started\u002Fintroduction","hu\u002F01.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Telepítés","\u002Fhu\u002Fgetting-started\u002Finstallation","hu\u002F01.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Az első modulod","\u002Fhu\u002Fgetting-started\u002Ffirst-module","hu\u002F01.getting-started\u002F3.first-module","i-lucide-package-plus",{"title":26,"path":27,"stem":28,"icon":29},"Projektstruktúra","\u002Fhu\u002Fgetting-started\u002Fproject-structure","hu\u002F01.getting-started\u002F4.project-structure","i-lucide-folder-tree",{"title":31,"path":32,"stem":33,"icon":34},"A shop mintaalkalmazás","\u002Fhu\u002Fgetting-started\u002Fsample-app","hu\u002F01.getting-started\u002F5.sample-app","i-lucide-shopping-cart",{"title":36,"path":37,"stem":38,"icon":39},"Laravelből érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-laravel","hu\u002F01.getting-started\u002F6.coming-from-laravel","i-lucide-arrow-right-left",{"title":41,"path":42,"stem":43,"icon":39},"Symfonyból érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-symfony","hu\u002F01.getting-started\u002F7.coming-from-symfony",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"CLI referencia","i-lucide-terminal","\u002Fhu\u002Fcli","hu\u002F02.cli",[51,55,60,65,70,75,80,85,90,95,100,105,110,115],{"title":52,"path":53,"stem":54,"icon":47},"Áttekintés","\u002Fhu\u002Fcli\u002Foverview","hu\u002F02.cli\u002F1.overview",{"title":56,"path":57,"stem":58,"icon":59},"add compose \u002F add docker","\u002Fhu\u002Fcli\u002Fadd-compose","hu\u002F02.cli\u002F10.add-compose","i-lucide-container",{"title":61,"path":62,"stem":63,"icon":64},"add mail","\u002Fhu\u002Fcli\u002Fadd-mail","hu\u002F02.cli\u002F11.add-mail","i-lucide-mail-plus",{"title":66,"path":67,"stem":68,"icon":69},"add notification","\u002Fhu\u002Fcli\u002Fadd-notification","hu\u002F02.cli\u002F12.add-notification","i-lucide-bell-plus",{"title":71,"path":72,"stem":73,"icon":74},"add realtime","\u002Fhu\u002Fcli\u002Fadd-realtime","hu\u002F02.cli\u002F13.add-realtime","i-lucide-radio-tower",{"title":76,"path":77,"stem":78,"icon":79},"add seeder","\u002Fhu\u002Fcli\u002Fadd-seeder","hu\u002F02.cli\u002F14.add-seeder","i-lucide-sprout",{"title":81,"path":82,"stem":83,"icon":84},"new project","\u002Fhu\u002Fcli\u002Fnew-project","hu\u002F02.cli\u002F2.new-project","i-lucide-folder-plus",{"title":86,"path":87,"stem":88,"icon":89},"new module","\u002Fhu\u002Fcli\u002Fnew-module","hu\u002F02.cli\u002F3.new-module","i-lucide-blocks",{"title":91,"path":92,"stem":93,"icon":94},"add surface","\u002Fhu\u002Fcli\u002Fadd-surface","hu\u002F02.cli\u002F4.add-surface","i-lucide-layers-2",{"title":96,"path":97,"stem":98,"icon":99},"add domain","\u002Fhu\u002Fcli\u002Fadd-domain","hu\u002F02.cli\u002F5.add-domain","i-lucide-box",{"title":101,"path":102,"stem":103,"icon":104},"add handler","\u002Fhu\u002Fcli\u002Fadd-handler","hu\u002F02.cli\u002F6.add-handler","i-lucide-webhook",{"title":106,"path":107,"stem":108,"icon":109},"new migration","\u002Fhu\u002Fcli\u002Fnew-migration","hu\u002F02.cli\u002F7.new-migration","i-lucide-file-plus",{"title":111,"path":112,"stem":113,"icon":114},"worker generátorok","\u002Fhu\u002Fcli\u002Fworker-generators","hu\u002F02.cli\u002F8.worker-generators","i-lucide-cog",{"title":116,"path":117,"stem":118,"icon":119},"add db","\u002Fhu\u002Fcli\u002Fadd-db","hu\u002F02.cli\u002F9.add-db","i-lucide-database-zap",{"title":121,"icon":99,"path":122,"stem":123,"children":124,"page":44},"A framework","\u002Fhu\u002Fframework","hu\u002F03.framework",[125,129,134,139,143,148,153],{"title":126,"path":127,"stem":128,"icon":99},"A framework áttekintése","\u002Fhu\u002Fframework\u002Foverview","hu\u002F03.framework\u002F1.overview",{"title":130,"path":131,"stem":132,"icon":133},"Alkalmazás-életciklus","\u002Fhu\u002Fframework\u002Fapp","hu\u002F03.framework\u002F2.app","i-lucide-power",{"title":135,"path":136,"stem":137,"icon":138},"Szerver","\u002Fhu\u002Fframework\u002Fserver","hu\u002F03.framework\u002F3.server","i-lucide-server",{"title":140,"path":141,"stem":142,"icon":114},"Worker","\u002Fhu\u002Fframework\u002Fworker","hu\u002F03.framework\u002F4.worker",{"title":144,"path":145,"stem":146,"icon":147},"Realtime","\u002Fhu\u002Fframework\u002Frealtime","hu\u002F03.framework\u002F5.realtime","i-lucide-radio",{"title":149,"path":150,"stem":151,"icon":152},"Migrációk","\u002Fhu\u002Fframework\u002Fmigrations","hu\u002F03.framework\u002F6.migrations","i-lucide-file-stack",{"title":154,"path":155,"stem":156,"icon":157},"Social login","\u002Fhu\u002Fframework\u002Fsocial-login","hu\u002F03.framework\u002F7.social-login","i-lucide-log-in",{"title":159,"icon":160,"path":161,"stem":162,"children":163,"page":44},"Referencia","i-lucide-book-open","\u002Fhu\u002Freference","hu\u002F04.reference",[164,169],{"title":165,"path":166,"stem":167,"icon":168},"Konfiguráció","\u002Fhu\u002Freference\u002Fconfiguration","hu\u002F04.reference\u002F1.configuration","i-lucide-settings",{"title":170,"path":171,"stem":172,"icon":173},"Külső függőségek","\u002Fhu\u002Freference\u002Fdependencies","hu\u002F04.reference\u002F2.dependencies","i-lucide-package",{"title":175,"icon":176,"path":177,"stem":178,"children":179,"page":44},"Koncepciók","i-lucide-lightbulb","\u002Fhu\u002Fconcepts","hu\u002F05.concepts",[180,185,190,194,199],{"title":181,"path":182,"stem":183,"icon":184},"Architektúra","\u002Fhu\u002Fconcepts\u002Farchitecture","hu\u002F05.concepts\u002F1.architecture","i-lucide-layers",{"title":186,"path":187,"stem":188,"icon":189},"Hibamodell","\u002Fhu\u002Fconcepts\u002Ferror-model","hu\u002F05.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":165,"path":191,"stem":192,"icon":193},"\u002Fhu\u002Fconcepts\u002Fconfiguration","hu\u002F05.concepts\u002F3.configuration","i-lucide-settings-2",{"title":195,"path":196,"stem":197,"icon":198},"Codegen pipeline","\u002Fhu\u002Fconcepts\u002Fcodegen-pipeline","hu\u002F05.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":200,"path":201,"stem":202,"icon":203},"Design patternek","\u002Fhu\u002Fconcepts\u002Fdesign-patterns","hu\u002F05.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":205,"icon":206,"path":207,"stem":208,"children":209,"page":44},"auth","i-lucide-shield-check","\u002Fhu\u002Fauth","hu\u002F06.auth",[210,215,220,225,230],{"title":211,"path":212,"stem":213,"icon":214},"Autentikáció","\u002Fhu\u002Fauth\u002Foverview","hu\u002F06.auth\u002F1.overview","i-lucide-key-round",{"title":216,"path":217,"stem":218,"icon":219},"RBAC","\u002Fhu\u002Fauth\u002Frbac","hu\u002F06.auth\u002F2.rbac","i-lucide-users",{"title":221,"path":222,"stem":223,"icon":224},"Policy-k","\u002Fhu\u002Fauth\u002Fpolicy","hu\u002F06.auth\u002F3.policy","i-lucide-gavel",{"title":226,"path":227,"stem":228,"icon":229},"Az auth önálló használata","\u002Fhu\u002Fauth\u002Fstandalone","hu\u002F06.auth\u002F4.standalone","i-lucide-plug",{"title":231,"path":232,"stem":233,"icon":157},"Social login goth-tal, önállóan","\u002Fhu\u002Fauth\u002Fsocial-standalone","hu\u002F06.auth\u002F5.social-standalone",{"title":235,"icon":236,"path":237,"stem":238,"children":239,"page":44},"dbx","i-lucide-database","\u002Fhu\u002Fdbx","hu\u002F07.dbx",[240,243,247,251,256],{"title":52,"path":241,"stem":242,"icon":236},"\u002Fhu\u002Fdbx\u002Foverview","hu\u002F07.dbx\u002F1.overview",{"title":244,"path":245,"stem":246,"icon":229},"pgx","\u002Fhu\u002Fdbx\u002Fpg","hu\u002F07.dbx\u002F2.pg",{"title":248,"path":249,"stem":250,"icon":184},"bun","\u002Fhu\u002Fdbx\u002Fbunx","hu\u002F07.dbx\u002F3.bunx",{"title":252,"path":253,"stem":254,"icon":255},"Tranzakciók","\u002Fhu\u002Fdbx\u002Ftransactions","hu\u002F07.dbx\u002F4.transactions","i-lucide-git-merge",{"title":257,"path":258,"stem":259,"icon":79},"Seederek","\u002Fhu\u002Fdbx\u002Fseed","hu\u002F07.dbx\u002F5.seed",{"title":261,"icon":193,"path":262,"stem":263,"children":264,"page":44},"envconf","\u002Fhu\u002Fenvconf","hu\u002F08.envconf",[265,268],{"title":52,"path":266,"stem":267,"icon":193},"\u002Fhu\u002Fenvconf\u002Foverview","hu\u002F08.envconf\u002F1.overview",{"title":269,"path":270,"stem":271,"icon":193},"Receptek","\u002Fhu\u002Fenvconf\u002Frecipes","hu\u002F08.envconf\u002F2.recipes",{"title":273,"icon":189,"path":274,"stem":275,"children":276,"page":44},"errs","\u002Fhu\u002Ferrs","hu\u002F09.errs",[277,280,284],{"title":52,"path":278,"stem":279,"icon":189},"\u002Fhu\u002Ferrs\u002Foverview","hu\u002F09.errs\u002F1.overview",{"title":281,"path":282,"stem":283,"icon":189},"API","\u002Fhu\u002Ferrs\u002Fapi","hu\u002F09.errs\u002F2.api",{"title":285,"path":286,"stem":287,"icon":189},"Integráció","\u002Fhu\u002Ferrs\u002Fintegration","hu\u002F09.errs\u002F3.integration",{"title":289,"icon":290,"path":291,"stem":292,"children":293,"page":44},"events","i-lucide-workflow","\u002Fhu\u002Fevents","hu\u002F10.events",[294,298,303],{"title":295,"path":296,"stem":297,"icon":147},"Események","\u002Fhu\u002Fevents\u002Foverview","hu\u002F10.events\u002F1.overview",{"title":299,"path":300,"stem":301,"icon":302},"Outbox","\u002Fhu\u002Fevents\u002Foutbox","hu\u002F10.events\u002F2.outbox","i-lucide-inbox",{"title":304,"path":305,"stem":306,"icon":307},"Ütemezés","\u002Fhu\u002Fevents\u002Fscheduler","hu\u002F10.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":309,"icon":310,"path":311,"stem":312,"children":313,"page":44},"httperr","i-lucide-globe","\u002Fhu\u002Fhttperr","hu\u002F11.httperr",[314,317,322],{"title":52,"path":315,"stem":316,"icon":310},"\u002Fhu\u002Fhttperr\u002Foverview","hu\u002F11.httperr\u002F1.overview",{"title":318,"path":319,"stem":320,"icon":321},"Hibaválaszok","\u002Fhu\u002Fhttperr\u002Ferror-responses","hu\u002F11.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":323,"path":324,"stem":325,"icon":326},"Validáció","\u002Fhu\u002Fhttperr\u002Fvalidation","hu\u002F11.httperr\u002F3.validation","i-lucide-badge-check",{"title":328,"icon":329,"path":330,"stem":331,"children":332,"page":44},"logx","i-lucide-scroll-text","\u002Fhu\u002Flogx","hu\u002F12.logx",[333,336],{"title":52,"path":334,"stem":335,"icon":329},"\u002Fhu\u002Flogx\u002Foverview","hu\u002F12.logx\u002F1.overview",{"title":337,"path":338,"stem":339,"icon":47},"Monolog-formázó","\u002Fhu\u002Flogx\u002Fmonolog","hu\u002F12.logx\u002F2.monolog",{"title":341,"icon":342,"path":343,"stem":344,"children":345,"page":44},"mail","i-lucide-mail","\u002Fhu\u002Fmail","hu\u002F13.mail",[346,349,353],{"title":52,"path":347,"stem":348,"icon":342},"\u002Fhu\u002Fmail\u002Foverview","hu\u002F13.mail\u002F1.overview",{"title":350,"path":351,"stem":352,"icon":342},"SMTP","\u002Fhu\u002Fmail\u002Fsmtp","hu\u002F13.mail\u002F2.smtp",{"title":354,"path":355,"stem":356,"icon":342},"MJML","\u002Fhu\u002Fmail\u002Fmjml","hu\u002F13.mail\u002F3.mjml",{"title":358,"icon":359,"path":360,"stem":361,"children":362,"page":44},"notify","i-lucide-bell","\u002Fhu\u002Fnotify","hu\u002F14.notify",[363,366,370],{"title":52,"path":364,"stem":365,"icon":359},"\u002Fhu\u002Fnotify\u002Foverview","hu\u002F14.notify\u002F1.overview",{"title":367,"path":368,"stem":369,"icon":359},"Database csatorna","\u002Fhu\u002Fnotify\u002Fdatabase","hu\u002F14.notify\u002F2.database",{"title":371,"path":372,"stem":373,"icon":359},"Broadcast csatorna","\u002Fhu\u002Fnotify\u002Fbroadcast","hu\u002F14.notify\u002F3.broadcast",{"title":375,"icon":376,"path":377,"stem":378,"children":379,"page":44},"paginate","i-lucide-list-ordered","\u002Fhu\u002Fpaginate","hu\u002F15.paginate",[380,383],{"title":52,"path":381,"stem":382,"icon":376},"\u002Fhu\u002Fpaginate\u002Foverview","hu\u002F15.paginate\u002F1.overview",{"title":384,"path":385,"stem":386,"icon":39},"Cursor-lapozás","\u002Fhu\u002Fpaginate\u002Fcursor","hu\u002F15.paginate\u002F2.cursor",{"title":388,"icon":184,"path":389,"stem":390,"children":391,"page":44},"queue","\u002Fhu\u002Fqueue","hu\u002F16.queue",[392,395],{"title":52,"path":393,"stem":394,"icon":376},"\u002Fhu\u002Fqueue\u002Foverview","hu\u002F16.queue\u002F1.overview",{"title":396,"path":397,"stem":398,"icon":184},"Taskok","\u002Fhu\u002Fqueue\u002Ftasks","hu\u002F16.queue\u002F2.tasks",{"title":400,"icon":401,"path":402,"stem":403,"children":404,"page":44},"storage","i-lucide-hard-drive","\u002Fhu\u002Fstorage","hu\u002F17.storage",[405,408,412,416,421],{"title":52,"path":406,"stem":407,"icon":401},"\u002Fhu\u002Fstorage\u002Foverview","hu\u002F17.storage\u002F1.overview",{"title":409,"path":410,"stem":411,"icon":401},"Disk API","\u002Fhu\u002Fstorage\u002Fdisk-api","hu\u002F17.storage\u002F2.disk-api",{"title":413,"path":414,"stem":415,"icon":401},"Memória és helyi lemez","\u002Fhu\u002Fstorage\u002Flocal","hu\u002F17.storage\u002F3.local",{"title":417,"path":418,"stem":419,"icon":420},"S3","\u002Fhu\u002Fstorage\u002Fs3","hu\u002F17.storage\u002F4.s3","i-lucide-cloud",{"title":422,"path":423,"stem":424,"icon":425},"Tesztelés","\u002Fhu\u002Fstorage\u002Ftesting","hu\u002F17.storage\u002F5.testing","i-lucide-flask-conical",{"title":427,"icon":428,"path":429,"stem":430,"children":431,"page":44},"telemetry","i-lucide-activity","\u002Fhu\u002Ftelemetry","hu\u002F18.telemetry",[432,435,439,444],{"title":52,"path":433,"stem":434,"icon":428},"\u002Fhu\u002Ftelemetry\u002Foverview","hu\u002F18.telemetry\u002F1.overview",{"title":436,"path":437,"stem":438,"icon":329},"Logolás","\u002Fhu\u002Ftelemetry\u002Flogging","hu\u002F18.telemetry\u002F2.logging",{"title":440,"path":441,"stem":442,"icon":443},"OpenTelemetry","\u002Fhu\u002Ftelemetry\u002Fopentelemetry","hu\u002F18.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":445,"path":446,"stem":447,"icon":448},"Sentry","\u002Fhu\u002Ftelemetry\u002Fsentry","hu\u002F18.telemetry\u002F4.sentry","i-lucide-bug",{"id":450,"title":130,"body":451,"description":1450,"extension":1451,"links":1452,"meta":1453,"navigation":1454,"path":131,"seo":1455,"stem":132,"__hash__":1456},"docs_hu\u002Fhu\u002F03.framework\u002F2.app.md",{"type":452,"value":453,"toc":1441},"minimark",[454,472,481,486,492,740,747,854,859,870,877,881,884,953,997,1009,1013,1023,1129,1153,1159,1163,1174,1341,1369,1383,1387,1424,1437],[455,456,457,458,462,463,467,468,471],"p",{},"PHP-ban a folyamat életciklusa nem a te problémád volt: a php-fpm elindította a workert, lefuttatta a kérést, és ha deployoltál, a supervisor gondoskodott a cseréről. Go-ban a binárisod ",[459,460,461],"strong",{},"maga a szerver",": neki kell figyelnie a ",[464,465,466],"code",{},"SIGTERM","-et, kivárnia az in-flight kéréseket, lezárnia a connection poolt és kiflusholnia a telemetriát, mielőtt kilép. Ez tipikusan az a ~60 sor boilerplate, amit minden service ",[464,469,470],{},"main.go","-jába bemásolnak, és amit mindig kicsit másképp rontanak el.",[455,473,474,475,480],{},"A framework ezt egyszer írja meg, az ",[459,476,477],{},[464,478,479],{},"app"," csomagban, és ettől a téma megint nem-téma: a generált projektekben a graceful shutdown egyszerűen ott van, és most láthatod is, mi történik.",[482,483,485],"h2",{"id":484},"apprun-és-a-params","app.Run és a Params",[455,487,488,489,491],{},"Az ",[464,490,479],{}," csomag engine-agnosztikus: se HTTP-t, se más transzportot nem ismer. Egyetlen belépési pontja van:",[493,494,499],"pre",{"className":495,"code":496,"language":497,"meta":498,"style":498},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Closer egy nevesített cleanup-függvény, graceful shutdownkor fut.\ntype Closer struct {\n    Name string\n    Fn   func(context.Context) error\n}\n\n\u002F\u002F Params egy processzfutást ír le.\ntype Params struct {\n    ListenAddr      string                          \u002F\u002F csak a startup-loghoz\n    ShutdownTimeout time.Duration                   \u002F\u002F az in-flight drain kerete\n    Serve           func() error                    \u002F\u002F blokkoló listen; goroutine-ban fut\n    Shutdown        func(context.Context) error     \u002F\u002F nincs új kérés, in-flight drain\n    Closers         []Closer                        \u002F\u002F rendezett cleanup-lista\n    Flush           func(context.Context) error     \u002F\u002F telemetria-flush, legutolsóként\n}\n\nfunc Run(ctx context.Context, p Params) error\n","go","",[464,500,501,510,527,538,562,568,575,581,593,605,622,637,658,673,694,699,704],{"__ignoreMap":498},[502,503,506],"span",{"class":504,"line":505},"line",1,[502,507,509],{"class":508},"sHwdD","\u002F\u002F Closer egy nevesített cleanup-függvény, graceful shutdownkor fut.\n",[502,511,513,517,521,524],{"class":504,"line":512},2,[502,514,516],{"class":515},"sMK4o","type",[502,518,520],{"class":519},"sBMFI"," Closer",[502,522,523],{"class":515}," struct",[502,525,526],{"class":515}," {\n",[502,528,530,534],{"class":504,"line":529},3,[502,531,533],{"class":532},"sTEyZ","    Name ",[502,535,537],{"class":536},"spNyl","string\n",[502,539,541,544,547,550,553,556,559],{"class":504,"line":540},4,[502,542,543],{"class":532},"    Fn   ",[502,545,546],{"class":515},"func(",[502,548,549],{"class":519},"context",[502,551,552],{"class":515},".",[502,554,555],{"class":519},"Context",[502,557,558],{"class":515},")",[502,560,561],{"class":536}," error\n",[502,563,565],{"class":504,"line":564},5,[502,566,567],{"class":515},"}\n",[502,569,571],{"class":504,"line":570},6,[502,572,574],{"emptyLinePlaceholder":573},true,"\n",[502,576,578],{"class":504,"line":577},7,[502,579,580],{"class":508},"\u002F\u002F Params egy processzfutást ír le.\n",[502,582,584,586,589,591],{"class":504,"line":583},8,[502,585,516],{"class":515},[502,587,588],{"class":519}," Params",[502,590,523],{"class":515},[502,592,526],{"class":515},[502,594,596,599,602],{"class":504,"line":595},9,[502,597,598],{"class":532},"    ListenAddr      ",[502,600,601],{"class":536},"string",[502,603,604],{"class":508},"                          \u002F\u002F csak a startup-loghoz\n",[502,606,608,611,614,616,619],{"class":504,"line":607},10,[502,609,610],{"class":532},"    ShutdownTimeout ",[502,612,613],{"class":519},"time",[502,615,552],{"class":515},[502,617,618],{"class":519},"Duration",[502,620,621],{"class":508},"                   \u002F\u002F az in-flight drain kerete\n",[502,623,625,628,631,634],{"class":504,"line":624},11,[502,626,627],{"class":532},"    Serve           ",[502,629,630],{"class":515},"func()",[502,632,633],{"class":536}," error",[502,635,636],{"class":508},"                    \u002F\u002F blokkoló listen; goroutine-ban fut\n",[502,638,640,643,645,647,649,651,653,655],{"class":504,"line":639},12,[502,641,642],{"class":532},"    Shutdown        ",[502,644,546],{"class":515},[502,646,549],{"class":519},[502,648,552],{"class":515},[502,650,555],{"class":519},[502,652,558],{"class":515},[502,654,633],{"class":536},[502,656,657],{"class":508},"     \u002F\u002F nincs új kérés, in-flight drain\n",[502,659,661,664,667,670],{"class":504,"line":660},13,[502,662,663],{"class":532},"    Closers         ",[502,665,666],{"class":515},"[]",[502,668,669],{"class":519},"Closer",[502,671,672],{"class":508},"                        \u002F\u002F rendezett cleanup-lista\n",[502,674,676,679,681,683,685,687,689,691],{"class":504,"line":675},14,[502,677,678],{"class":532},"    Flush           ",[502,680,546],{"class":515},[502,682,549],{"class":519},[502,684,552],{"class":515},[502,686,555],{"class":519},[502,688,558],{"class":515},[502,690,633],{"class":536},[502,692,693],{"class":508},"     \u002F\u002F telemetria-flush, legutolsóként\n",[502,695,697],{"class":504,"line":696},15,[502,698,567],{"class":515},[502,700,702],{"class":504,"line":701},16,[502,703,574],{"emptyLinePlaceholder":573},[502,705,707,710,714,717,721,724,726,728,731,734,736,738],{"class":504,"line":706},17,[502,708,709],{"class":515},"func",[502,711,713],{"class":712},"s2Zo4"," Run",[502,715,716],{"class":515},"(",[502,718,720],{"class":719},"sHdIc","ctx",[502,722,723],{"class":519}," context",[502,725,552],{"class":515},[502,727,555],{"class":519},[502,729,730],{"class":515},",",[502,732,733],{"class":719}," p",[502,735,588],{"class":519},[502,737,558],{"class":515},[502,739,561],{"class":536},[455,741,742,743,746],{},"A ",[464,744,745],{},"Run"," blokkol, amíg a processz le nem áll, és a következő gépezetet hajtja:",[748,749,750,773,789,813,831,843],"ol",{},[751,752,753,758,759,762,763,765,766,768,769,772],"li",{},[459,754,755],{},[464,756,757],{},"signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)",": a ",[464,760,761],{},"SIGINT","\u002F",[464,764,466],{}," a contextet cancelezi. Mivel a szülő ",[464,767,720],{},"-ből származik, a ",[459,770,771],{},"szülő context cancelje is shutdownt vált ki",": tesztben így állítasz le egy futó service-t signal nélkül.",[751,774,775,781,782,784,785,788],{},[459,776,777,780],{},[464,778,779],{},"Serve"," goroutine-ban indul."," Ha magától hibával tér vissza (pl. foglalt a port), a ",[464,783,745],{}," ",[464,786,787],{},"app: listen:"," hibával lép ki, de a closerek és a flush ilyenkor is lefutnak.",[751,790,791,758,794,796,797,804,805,808,809,812],{},[459,792,793],{},"Signalra",[464,795,745],{}," visszaállítja az alapértelmezett signal-kezelést (ezért ",[459,798,799,800,803],{},"egy második ",[464,801,802],{},"Ctrl-C"," azonnal, kegyelem nélkül öli a processzt","), majd meghívja a ",[464,806,807],{},"Shutdown","-t egy ",[464,810,811],{},"ShutdownTimeout","-os contexttel. Itt drainelnek az in-flight kérések.",[751,814,815,818,819,823,824,826,827,830],{},[459,816,817],{},"Cleanup saját kerettel",": a closerek és a flush egy ",[820,821,822],"em",{},"friss",", szintén ",[464,825,811],{},"-os contextet kapnak. Ha a HTTP-drain felélte a teljes keretet, a cleanup akkor sem nulla idővel indul: a pool-lezárás és a telemetria-export nem esik áldozatul egy lassú kérésnek. (Mindkét shutdown-context ",[464,828,829],{},"context.WithoutCancel","-lel válik le a szülőről: egy már cancelezett szülő nem vágja rövidre a rendezett leállást.)",[751,832,833,836,837,552],{},[459,834,835],{},"Closerek LIFO sorrendben",", majd ",[459,838,839,840],{},"legvégül a ",[464,841,842],{},"Flush",[751,844,845,846,849,850,853],{},"Tiszta leállásnál ",[464,847,848],{},"nil"," a visszatérési érték; a részhibák ",[464,851,852],{},"errors.Join","-nal gyűlnek, tehát egy hibázó closer nem nyeli el a többiét.",[855,856,858],"h3",{"id":857},"miért-lifo-és-miért-utolsó-a-flush","Miért LIFO, és miért utolsó a flush?",[455,860,861,862,865,866,869],{},"A closerek ",[459,863,864],{},"fordított regisztrációs sorrendben"," futnak, mert a függőségek így záródnak helyes irányban: amit előbb nyitottál (pl. a pgx pool), arra még szüksége lehet annak, amit később építettél rá (pl. egy rá támaszkodó consumer). Amit utoljára nyitottál, azt zárod először, pontosan ahogy a ",[464,867,868],{},"defer"," működik egy függvényen belül.",[455,871,872,873,876],{},"A telemetria-flush pedig azért a legutolsó, mert ",[459,874,875],{},"a closerek maguk is bocsátanak ki telemetriát",": egy pool-lezárás loga, egy cleanup közben nyitott span csak akkor jut el az OTLP-endpointig vagy a Sentrybe, ha az exporterek még élnek. Ha a flush a closerek előtt futna, a leállás utolsó másodpercei vakfoltba esnének.",[482,878,880],{"id":879},"apptelemetry","app.Telemetry",[455,882,883],{},"A másik dolog, amit minden chassis megtesz, mielőtt bármi más elindulna, a telemetria bootstrapja, és ez a recept ugyanebben a csomagban él:",[493,885,887],{"className":495,"code":886,"language":497,"meta":498,"style":498},"func Telemetry(ctx context.Context, tcfg telemetry.Config, lcfg logx.Config) (func(context.Context) error, error)\n",[464,888,889],{"__ignoreMap":498},[502,890,891,893,896,898,900,902,904,906,908,911,914,916,919,921,924,927,929,931,933,936,938,940,942,944,946,948,950],{"class":504,"line":505},[502,892,709],{"class":515},[502,894,895],{"class":712}," Telemetry",[502,897,716],{"class":515},[502,899,720],{"class":719},[502,901,723],{"class":519},[502,903,552],{"class":515},[502,905,555],{"class":519},[502,907,730],{"class":515},[502,909,910],{"class":719}," tcfg",[502,912,913],{"class":519}," telemetry",[502,915,552],{"class":515},[502,917,918],{"class":519},"Config",[502,920,730],{"class":515},[502,922,923],{"class":719}," lcfg",[502,925,926],{"class":519}," logx",[502,928,552],{"class":515},[502,930,918],{"class":519},[502,932,558],{"class":515},[502,934,935],{"class":515}," (func(",[502,937,549],{"class":519},[502,939,552],{"class":515},[502,941,555],{"class":519},[502,943,558],{"class":515},[502,945,633],{"class":536},[502,947,730],{"class":515},[502,949,633],{"class":536},[502,951,952],{"class":515},")\n",[455,954,742,955,958,959,962,963,966,967,970,971,977,978,983,984,762,987,990,991,993,994,552],{},[464,956,957],{},"Telemetry"," validálja az ",[464,960,961],{},"lcfg","-t, dev módban vagy ",[464,964,965],{},"LOG_STDOUT"," esetén felépít egy konzol ",[464,968,969],{},"slog.Handler","-t a ",[972,973,974],"a",{"href":334},[464,975,976],{},"logx.ConsoleHandler","-ral, és az eredményt átadja a ",[972,979,980],{"href":433},[464,981,982],{},"telemetry.Setup","-nak ",[464,985,986],{},"WithLogHandler",[464,988,989],{},"WithLogLevel"," révén. Ugyanazt a shutdown-függvényt adja vissza, amit a ",[464,992,982],{},", ez lesz majd a ",[464,995,996],{},"Params.Flush",[455,998,742,999,1001,1002,1004,1005,1008],{},[464,1000,957],{},"-nek nincs függősége a ",[464,1003,745],{},"-tól vagy a ",[464,1006,1007],{},"Params","-tól: egy sima függvény, amit egy nem-chassis binárisból (CLI, egyszeri migráció) is hívhatsz, hogy ugyanazt a logx\u002Ftelemetry kompozíciót kapd meg, amit a chassis, HTTP, asynq vagy centrifuge behúzása nélkül.",[482,1010,1012],{"id":1011},"ki-ül-rajta","Ki ül rajta?",[455,1014,1015,1016,1019,1020,1022],{},"Mindhárom chassis ugyanezt az ",[464,1017,1018],{},"app.Run","-t tölti ki, csak a ",[464,1021,1007],{}," tartalma más:",[1024,1025,1026,1050],"table",{},[1027,1028,1029],"thead",{},[1030,1031,1032,1035,1040,1045],"tr",{},[1033,1034,1007],"th",{},[1033,1036,1037],{},[464,1038,1039],{},"server.Run",[1033,1041,1042],{},[464,1043,1044],{},"worker.Run",[1033,1046,1047],{},[464,1048,1049],{},"realtime.Run",[1051,1052,1053,1071,1091,1113],"tbody",{},[1030,1054,1055,1060,1065,1068],{},[1056,1057,1058],"td",{},[464,1059,779],{},[1056,1061,1062],{},[464,1063,1064],{},"srv.ListenAndServe",[1056,1066,1067],{},"asynq szerver + outbox relay + ütemező",[1056,1069,1070],{},"a kapcsolatokat fogadó centrifuge node",[1030,1072,1073,1077,1082,1085],{},[1056,1074,1075],{},[464,1076,807],{},[1056,1078,1079],{},[464,1080,1081],{},"srv.Shutdown",[1056,1083,1084],{},"loopok leállítása, in-flight taskok drainelése",[1056,1086,1087,1090],{},[464,1088,1089],{},"node.Shutdown",", tartott kapcsolatok drainelése",[1030,1092,1093,1098,1105,1109],{},[1056,1094,1095],{},[464,1096,1097],{},"Closers",[1056,1099,1100,1101,1104],{},"a ",[464,1102,1103],{},"WithCloser"," opciók",[1056,1106,1100,1107,1104],{},[464,1108,1103],{},[1056,1110,1100,1111,1104],{},[464,1112,1103],{},[1030,1114,1115,1119,1124,1127],{},[1056,1116,1117],{},[464,1118,842],{},[1056,1120,1121,1123],{},[464,1122,880],{}," shutdown-függvénye",[1056,1125,1126],{},"ugyanaz",[1056,1128,1126],{},[455,1130,1131,1132,1134,1135,1137,1138,1141,1142,1145,1146,1149,1150,1152],{},"Mindhárom az ",[464,1133,880],{},"-vel indít, és a visszakapott shutdown-függvényt adja át ",[464,1136,842],{},"-ként, így a \"Sentry és OTel flush a legvégén\" garancia bináris-típustól függetlenül azonos. A workernél az in-flight drain mást jelent: a ",[464,1139,1140],{},"WORKER_SHUTDOWN_TIMEOUT"," alatt be nem fejezett taskokat az asynq visszateszi a sorba, és később újra kézbesíti (",[972,1143,1144],{"href":141},"at-least-once","); a ",[464,1147,1148],{},"realtime","-nál pedig azt, hogy minden tartott WebSocket-kapcsolat reconnect-jogosult close-kódot kap, mielőtt a processz kilép (",[972,1151,144],{"href":145},").",[455,1154,1155,1156,1158],{},"Ha egy saját, negyedik chassis-t építenél (pl. egy gRPC-szervert), ugyanígy az ",[464,1157,1018],{},"-ra teheted: a csomagnak nincs HTTP-függősége.",[482,1160,1162],{"id":1161},"a-shop-maingo-ja","A shop main.go-ja",[455,1164,1165,1166,1169,1170,1173],{},"A gyakorlatban az életciklushoz egyetlen ponton nyúlsz hozzá: closert regisztrálsz mindenre, amit a ",[464,1167,1168],{},"main","-ben nyitottál. A ",[972,1171,1172],{"href":32},"shop mintaalkalmazás"," belépési pontjában ez a pgx pool:",[493,1175,1178],{"className":495,"code":1176,"filename":1177,"language":497,"meta":498,"style":498},"pool := pg.MustNewPool(ctx, cfg.DB)\n\nerr := server.Run(ctx, cfg.Server, func(r chi.Router) error {\n    \u002F\u002F ... modulregisztráció ...\n    return nil\n}, server.WithCloser(\"pgxpool\", func(context.Context) error {\n    pool.Close()\n    return nil\n}))\n","cmd\u002Fshop\u002Fmain.go",[464,1179,1180,1212,1216,1265,1270,1279,1317,1330,1336],{"__ignoreMap":498},[502,1181,1182,1185,1188,1191,1193,1196,1198,1200,1202,1205,1207,1210],{"class":504,"line":505},[502,1183,1184],{"class":532},"pool ",[502,1186,1187],{"class":515},":=",[502,1189,1190],{"class":532}," pg",[502,1192,552],{"class":515},[502,1194,1195],{"class":712},"MustNewPool",[502,1197,716],{"class":515},[502,1199,720],{"class":532},[502,1201,730],{"class":515},[502,1203,1204],{"class":532}," cfg",[502,1206,552],{"class":515},[502,1208,1209],{"class":532},"DB",[502,1211,952],{"class":515},[502,1213,1214],{"class":504,"line":512},[502,1215,574],{"emptyLinePlaceholder":573},[502,1217,1218,1221,1223,1226,1228,1230,1232,1234,1236,1238,1240,1243,1245,1248,1251,1254,1256,1259,1261,1263],{"class":504,"line":529},[502,1219,1220],{"class":532},"err ",[502,1222,1187],{"class":515},[502,1224,1225],{"class":532}," server",[502,1227,552],{"class":515},[502,1229,745],{"class":712},[502,1231,716],{"class":515},[502,1233,720],{"class":532},[502,1235,730],{"class":515},[502,1237,1204],{"class":532},[502,1239,552],{"class":515},[502,1241,1242],{"class":532},"Server",[502,1244,730],{"class":515},[502,1246,1247],{"class":515}," func(",[502,1249,1250],{"class":719},"r",[502,1252,1253],{"class":519}," chi",[502,1255,552],{"class":515},[502,1257,1258],{"class":519},"Router",[502,1260,558],{"class":515},[502,1262,633],{"class":536},[502,1264,526],{"class":515},[502,1266,1267],{"class":504,"line":540},[502,1268,1269],{"class":508},"    \u002F\u002F ... modulregisztráció ...\n",[502,1271,1272,1276],{"class":504,"line":564},[502,1273,1275],{"class":1274},"s7zQu","    return",[502,1277,1278],{"class":515}," nil\n",[502,1280,1281,1284,1286,1288,1290,1292,1295,1299,1301,1303,1305,1307,1309,1311,1313,1315],{"class":504,"line":570},[502,1282,1283],{"class":515},"},",[502,1285,1225],{"class":532},[502,1287,552],{"class":515},[502,1289,1103],{"class":712},[502,1291,716],{"class":515},[502,1293,1294],{"class":515},"\"",[502,1296,1298],{"class":1297},"sfazB","pgxpool",[502,1300,1294],{"class":515},[502,1302,730],{"class":515},[502,1304,1247],{"class":515},[502,1306,549],{"class":519},[502,1308,552],{"class":515},[502,1310,555],{"class":519},[502,1312,558],{"class":515},[502,1314,633],{"class":536},[502,1316,526],{"class":515},[502,1318,1319,1322,1324,1327],{"class":504,"line":577},[502,1320,1321],{"class":532},"    pool",[502,1323,552],{"class":515},[502,1325,1326],{"class":712},"Close",[502,1328,1329],{"class":515},"()\n",[502,1331,1332,1334],{"class":504,"line":583},[502,1333,1275],{"class":1274},[502,1335,1278],{"class":515},[502,1337,1338],{"class":504,"line":595},[502,1339,1340],{"class":515},"}))\n",[455,1342,1343,1344,1346,1347,1350,1351,1354,1355,1357,1358,1360,1361,1364,1365,1368],{},"Egy ",[464,1345,466],{}," érkezésekor tehát a sorrend: a shop nem fogad több kérést → a folyamatban lévő ",[464,1348,1349],{},"PlaceOrder"," még lefut (a tranzakciójával és az ",[972,1352,1353],{"href":300},"outbox-írásával"," együtt) → a ",[464,1356,1298],{}," closer lezárja a poolt → a telemetria kiflusholja a kérés spanjeit. Kubernetes alatt ez pontosan az a viselkedés, amit egy rolling deploy elvár: a ",[464,1359,811],{},"-ot (",[464,1362,1363],{},"SHUTDOWN_TIMEOUT",", default 10s) érdemes a pod ",[464,1366,1367],{},"terminationGracePeriodSeconds","-énél rövidebbre hangolni.",[1370,1371,1372,1373,1376,1377,784,1379,1382],"note",{},"A closer neve (",[464,1374,1375],{},"\"pgxpool\"",") nem dísz: hibázó closernél a ",[464,1378,745],{},[464,1380,1381],{},"app: closer \"pgxpool\": ..."," formában adja vissza a hibát, így a logból azonnal látszik, melyik cleanup bukott el.",[482,1384,1386],{"id":1385},"mit-jelent-ez-a-mindennapokban","Mit jelent ez a mindennapokban",[1388,1389,1390,1404,1415],"ul",{},[751,1391,1392,1395,1396,1398,1399,1398,1401,1403],{},[459,1393,1394],{},"Nem írsz signal-kezelést."," Soha. A ",[464,1397,1039],{}," \u002F ",[464,1400,1044],{},[464,1402,1049],{}," hívása maga az életciklus.",[751,1405,1406,1411,1412,1414],{},[459,1407,742,1408,1410],{},[464,1409,1168],{},"-ben nyitott erőforrásokhoz closer jár",": a generátorok a pgx poolét maguktól bekötik, a sajátjaidat (pl. egy Valkey-klienst) te adod hozzá ",[464,1413,1103],{},"-rel, a nyitás sorrendjében.",[751,1416,1417,1423],{},[459,1418,1419,1420,1422],{},"A dupla ",[464,1421,802],{}," menekülőútvonal marad",": ha fejlesztés közben beragadna egy drain, a második signal azonnal kilő.",[455,1425,1426,1427,1430,1431,1433,1434,1436],{},"A HTTP-oldali lépéssort (telemetria → router-építés → regisztráció → listen → shutdown) a ",[972,1428,1429],{"href":136},"szerver"," oldal mutatja be; a worker-oldali drain részleteit a ",[972,1432,140],{"href":141}," oldal; a kapcsolat-drainelés részleteit a ",[972,1435,144],{"href":145}," oldal.",[1438,1439,1440],"style",{},"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 .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 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}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 .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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":498,"searchDepth":512,"depth":512,"links":1442},[1443,1446,1447,1448,1449],{"id":484,"depth":512,"text":485,"children":1444},[1445],{"id":857,"depth":529,"text":858},{"id":879,"depth":512,"text":880},{"id":1011,"depth":512,"text":1012},{"id":1161,"depth":512,"text":1162},{"id":1385,"depth":512,"text":1386},"Az app csomag: signal-vezérelt graceful shutdown, amin minden gpsystem bináris ül.","md",null,{},{"icon":133},{"title":130,"description":1450},"uo-9uMUedDzFXCDAUKF81v-RWtKtQK_aPi-8nIHeo2c",[1458,1460],{"title":126,"path":127,"stem":128,"description":1459,"icon":99,"children":-1},"Mi maradt a vékony gpsystem frameworkben, és hogyan komponálja az önálló modulokat.",{"title":135,"path":136,"stem":137,"description":1461,"icon":138,"children":-1},"A chi-alapú HTTP-chassis: Config (timeoutok, CORS, body limit), a közös életciklus, és hogy mit köt be a server.Run.",1787346793575]