[{"data":1,"prerenderedAt":5190},["ShallowReactive",2],{"search-index":3,"article:\u002Fyazilar\u002Fayni-metrik-farkli-sayi":2846,"article-navigation":3189},[4,394,1104,1591,2341],{"id":5,"title":6,"body":7,"category":378,"cover":379,"date":380,"demo":381,"description":382,"draft":381,"extension":383,"featured":384,"meta":385,"navigation":384,"path":386,"readingTime":387,"seo":388,"stem":389,"tags":390,"updated":380,"__hash__":393},"blog\u002Fyazilar\u002Fteknoloji-ve-ai-kararlari.md","Teknoloji ve AI Kararlarını Projeye Bağlamak",{"type":8,"value":9,"toc":364},"minimark",[10,19,22,27,30,46,49,53,56,82,85,100,104,107,167,170,174,181,184,191,195,198,230,234,260,274,278,284,287,290,317,320,324,327,344,347,351,354,357],[11,12,13,14,18],"p",{},"Yeni bir teknolojiyi denemek heyecan verici bir karar gibi görünüyor. Pratikte bir maliyet kararı: seçtiğin araç, o projeyi bundan sonra kimin nasıl sürdüreceğini de belirliyor. Yapay zekâ için de aynı şey geçerli — asıl soru \"kullanayım mı\" değil, ",[15,16,17],"strong",{},"hangi adımda kullanayım",".",[11,20,21],{},"Bu yazı, bu iki soruyu ayrı ayrı değil, aynı karar hattının parçaları olarak ele alıyor.",[23,24,26],"h2",{"id":25},"önce-problem-sonra-araç","Önce problem, sonra araç",[11,28,29],{},"Bir teknoloji tartışması genellikle araçtan başlıyor: \"şunu mu kullansak, bunu mu?\" Bu soru neredeyse her zaman erken. Cevaplanabilmesi için önce şunların netleşmesi gerekiyor:",[31,32,33,37,40,43],"ul",{},[34,35,36],"li",{},"Bu sistem hangi işi yapacak ve kim kullanacak?",[34,38,39],{},"Veri nereden geliyor, nereye gidiyor?",[34,41,42],{},"Hangi kısım gerçekten değişken, hangi kısım yıllarca aynı kalacak?",[34,44,45],{},"Yanlış giderse ne olur — bir rapor mu bozulur, bir ödeme mi kaybolur?",[11,47,48],{},"Son madde belirleyici. Bir dashboard'un yanlış sayı göstermesiyle bir ödemenin iki kez işlenmesi aynı ağırlıkta değil. Aracın ne kadar \"yeni\" olabileceğini de büyük ölçüde bu belirliyor.",[23,50,52],{"id":51},"yeni-bir-aracın-gerçek-maliyeti-öğrenmek-değil","Yeni bir aracın gerçek maliyeti öğrenmek değil",[11,54,55],{},"Yeni bir framework ya da kütüphane seçerken en çok konuşulan şey öğrenme eğrisi oluyor. Halbuki öğrenmek bir kerelik bir maliyet. Asıl maliyet sonrasında geliyor:",[31,57,58,64,70,76],{},[34,59,60,63],{},[15,61,62],{},"Bakım:"," Bu aracın kırıcı sürüm geçişlerini kim takip edecek?",[34,65,66,69],{},[15,67,68],{},"Devralınabilirlik:"," Yarın başka biri bu projeye baktığında ne kadar sürede anlar?",[34,71,72,75],{},[15,73,74],{},"Kaynak derinliği:"," Sıra dışı bir hatayla karşılaştığında arayıp bulabileceğin bir cevap var mı, yoksa kaynak koda mı bakacaksın?",[34,77,78,81],{},[15,79,80],{},"Sağlayıcı bağımlılığı:"," Aracın arkasındaki servis sözleşmesini değiştirirse elinde ne kalıyor?",[11,83,84],{},"Bu sorular \"yeni olan kötüdür\" demiyor. Sadece yeniliğin bedava olmadığını söylüyor. Bedeli ödemeye değecek bir karşılık varsa yeni araç doğru seçim.",[86,87,90,97],"callout",{"title":88,"type":89},"Bir yenilik bütçesi tut","tip",[11,91,92,93,96],{},"Her projede sınırlı sayıda \"yeni ve kanıtlanmamış\" tercih taşıyabilirsin. Bunu bir bütçe gibi düşünmek işe yarıyor: bütçeyi projenin ",[15,94,95],{},"ayırt edici"," kısmına harca, sıradan kısmına değil.",[11,98,99],{},"Kimlik doğrulama, dosya yükleme ve tablo listeleme gibi çözülmüş problemlerde bilinen aracı seç. Bütçeyi, projenin gerçekten farklı olduğu yere sakla.",[23,101,103],{"id":102},"karar-tablosu","Karar tablosu",[11,105,106],{},"Pratikte kendime sorduğum ayrım kabaca şu:",[108,109,110,123],"table",{},[111,112,113],"thead",{},[114,115,116,120],"tr",{},[117,118,119],"th",{},"Durum",[117,121,122],{},"Yönelim",[124,125,126,135,143,151,159],"tbody",{},[114,127,128,132],{},[129,130,131],"td",{},"Problem çözülmüş ve sıradan",[129,133,134],{},"Bilinen, olgun araç",[114,136,137,140],{},[129,138,139],{},"Problem projenin ayırt edici kısmı",[129,141,142],{},"Yeni araç değerlendirilebilir",[114,144,145,148],{},[129,146,147],{},"Hata maliyeti finansal veya yasal",[129,149,150],{},"Olgun araç, geniş kaynak",[114,152,153,156],{},[129,154,155],{},"Kısa ömürlü, atılabilir iş",[129,157,158],{},"Deneme için uygun",[114,160,161,164],{},[129,162,163],{},"Uzun ömürlü, devredilecek sistem",[129,165,166],{},"Devralınabilirlik öncelikli",[11,168,169],{},"Tablo bir kural değil, bir başlangıç noktası. Ama \"bu aracı neden seçtim\" sorusuna sonradan verilecek cevabı hazırlıyor — ve bir kararı savunabilmek, çoğu zaman doğru olmasının ön koşulu.",[23,171,173],{"id":172},"yapay-zekâ-bu-hattın-neresinde","Yapay zekâ bu hattın neresinde",[11,175,176,177,180],{},"Çalışma biçimimi dört adımda düşünüyorum: ",[15,178,179],{},"problemi anla → mimariyi kur → hızlandır → kontrol et ve yayınla."," Yapay zekâ bu hattın üçüncü adımında duruyor. Birinci ve ikinciyi devralmıyor.",[11,182,183],{},"Bunun sebebi AI'ın mimari öneremeyeceği değil. Önerebiliyor, üstelik makul öneriler de çıkıyor. Sebep şu: mimari kararın doğruluğu, çoğunlukla kodda görünmeyen bilgilere bağlı. Hangi ekip bakacak, hangi kısım gelecek çeyrekte değişecek, hangi kural mevzuattan geliyor, geçen sene hangi yaklaşım denenip bırakıldı. Bu bilgiler istemde yoksa, cevap teknik olarak doğru ama bağlam olarak yanlış oluyor.",[11,185,186,187,190],{},"Bir örnek: analiz ekranları olan bir sistemde \"iki ekran aynı metrik için farklı sayı gösteriyor\" problemine hızlıca bir düzeltme yazdırmak mümkün. Ama sorun genellikle hesaplamada değil, ",[15,188,189],{},"kapsamın tanımında"," oluyor — iki ekran farklı kümeyi değerlendiriyordur. Bunu görebilmek için ekranların ortak bir filtre sözleşmesine bağlanması gerektiğini bilmek gerekiyor. O karar verildikten sonra AI'ın hızlandıracağı çok iş var; ama kararın kendisi verilmeden yazılan kod, yanlış yerde iyileştirme yapıyor.",[23,192,194],{"id":193},"aiı-hangi-işlerde-kullanıyorum","AI'ı hangi işlerde kullanıyorum",[11,196,197],{},"Somut olarak üretkenlik kazandığı yerler:",[31,199,200,206,212,218,224],{},[34,201,202,205],{},[15,203,204],{},"Araştırma ve alternatif çıkarma."," Bir problemin kaç farklı yaklaşımı olduğunu hızlıca görmek, her birinin takasını konuşmak.",[34,207,208,211],{},[15,209,210],{},"Bilinen bir kalıbı yazmak."," Şekli belli olan doğrulama, dönüştürme, tekrar eden CRUD katmanları.",[34,213,214,217],{},[15,215,216],{},"Kendi koduma ikinci bir göz."," \"Bu fonksiyonda gözden kaçırdığım sınır durumu var mı?\" sorusu, tek başına çalışırken en çok işe yarayan kullanım.",[34,219,220,223],{},[15,221,222],{},"Test ve dokümantasyon taslağı."," Taslak; son hâli değil.",[34,225,226,229],{},[15,227,228],{},"Yabancı bir kod tabanını okumak."," Devraldığın bir projede hangi dosyanın ne yaptığını çıkarmak.",[23,231,233],{"id":232},"aia-bırakmadığım-şeyler","AI'a bırakmadığım şeyler",[31,235,236,242,248,254],{},[34,237,238,241],{},[15,239,240],{},"Mimari kararlar."," Yukarıdaki sebeple.",[34,243,244,247],{},[15,245,246],{},"Güvenlik sınırları."," Gizli değerlerin nerede duracağı, kimin neye erişeceği, bir endpoint'in neyi kabul edeceği. Bunlar gözden geçirilecek değil, baştan tasarlanacak konular.",[34,249,250,253],{},[15,251,252],{},"Doğrulanmamış teknik iddialar."," Bir kütüphanenin belirli bir sürümde nasıl davrandığı, bir sağlayıcının API sözleşmesi, bir platformun varsayılanı. Bunları kendi sürümünle ve kendi hesabınla sınamadan yazıya da koda da geçirmiyorum.",[34,255,256,259],{},[15,257,258],{},"Üretim verisine dokunan son adım."," Migrasyon, toplu güncelleme, gerçek para veya gerçek kişisel veriyle çalışan akışlar.",[86,261,264,271],{"title":262,"type":263},"En pahalı hata türü: makul görünen yanlış","warning",[11,265,266,267,270],{},"Yapay zekânın ürettiği kodda asıl risk, açıkça bozuk çıktı değil — o zaten hemen fark ediliyor. Risk, ",[15,268,269],{},"çalışan ama yanlış varsayıma dayanan"," kod. Doğru görünür, testten geçer, aylar sonra bir kenar durumda ortaya çıkar.",[11,272,273],{},"Bu yüzden kabul kriterim \"çalışıyor mu\" değil, \"neden böyle yazıldığını açıklayabiliyor muyum\". Açıklayamıyorsam henüz benim kodum değildir.",[23,275,277],{"id":276},"kararı-projeye-bağlamak","Kararı projeye bağlamak",[11,279,280,281],{},"Teknoloji seçimiyle AI kullanımı aslında aynı soruyu soruyor: ",[15,282,283],{},"bu kararın sahibi kim?",[11,285,286],{},"Bir aracı \"popüler olduğu için\" seçmekle, bir kodu \"AI öyle yazdığı için\" bırakmak arasında yapısal bir fark yok. İkisinde de karar dışarıya devredilmiş oluyor. Sorun çıktığında ise açıklama sende aranıyor.",[11,288,289],{},"Pratikte bunu şöyle işletiyorum:",[291,292,293,299,305,311],"ol",{},[34,294,295,298],{},[15,296,297],{},"Problemi ve sınırlarını yazıyorum."," Ne yapacak, ne yapmayacak, yanlış giderse ne olur.",[34,300,301,304],{},[15,302,303],{},"Mimariyi kendim kuruyorum."," Veri modeli, sınırlar, hangi kısım nereye ait.",[34,306,307,310],{},[15,308,309],{},"Hızlandırma adımında AI'dan yararlanıyorum."," Alternatifler, taslaklar, ikinci göz.",[34,312,313,316],{},[15,314,315],{},"Çıktıyı kendi ölçütlerimle denetliyorum."," Testler geçiyor mu, sınır durumları karşılanıyor mu, altı ay sonra ben bunu okuyabilir miyim.",[11,318,319],{},"Dördüncü adım geçilmeden hiçbir şey yayına çıkmıyor.",[23,321,323],{"id":322},"yayına-almadan-önce-sorduklarım","Yayına almadan önce sorduklarım",[11,325,326],{},"Yeni bir araç ya da hızlandırılmış bir çıktı üretime girmeden önce:",[31,328,329,332,335,338,341],{},[34,330,331],{},"Bu kararı bir başkasına gerekçesiyle anlatabiliyor muyum?",[34,333,334],{},"Araç yarın bakımsız kalırsa elimde çalışan bir plan var mı?",[34,336,337],{},"Kodun yaptığı işi satır satır takip edebiliyor muyum?",[34,339,340],{},"Hata durumunda ne olacağı tanımlı mı — sessizce mi geçiyor, yoksa görünür bir yerde mi duruyor?",[34,342,343],{},"Gizli bir değer yanlış tarafa mı düştü?",[11,345,346],{},"Bu soruların hiçbiri araç karşıtı değil. Hepsi aynı şeyi soruyor: karar bende mi kaldı?",[23,348,350],{"id":349},"kapanış","Kapanış",[11,352,353],{},"Güncel teknolojiyi takip etmek, her yeniyi kullanmak demek değil; hangi problemin artık daha iyi bir çözümü olduğunu bilmek demek. Yapay zekâyı kullanmak da her şeyi ona yazdırmak değil; hangi adımda gerçekten hızlandırdığını bilmek demek.",[11,355,356],{},"İkisinde de belirleyici olan araç değil, aracı seçerken sorulan soru. Daha iyi çözümler, doğru soruları sormakla başlıyor.",[86,358,361],{"title":359,"type":360},"Kapsam notu","info",[11,362,363],{},"Buradaki yaklaşım kendi çalışma biçimimi anlatır; ölçülmüş bir verimlilik iddiası ya da genel geçer bir kural değildir. Belirli araç ve sağlayıcı davranışları zamanla değişiyor — kendi projende uygularken güncel dokümantasyonla ve kendi sürümünle doğrula.",{"title":365,"searchDepth":366,"depth":367,"links":368},"",2,3,[369,370,371,372,373,374,375,376,377],{"id":25,"depth":366,"text":26},{"id":51,"depth":366,"text":52},{"id":102,"depth":366,"text":103},{"id":172,"depth":366,"text":173},{"id":193,"depth":366,"text":194},{"id":232,"depth":366,"text":233},{"id":276,"depth":366,"text":277},{"id":322,"depth":366,"text":323},{"id":349,"depth":366,"text":350},"Mimari","\u002Fimages\u002Fblog\u002Fkarar.svg","2026-09-09",false,"Yeni bir aracı ne zaman seçmeli, yapay zekâyı hangi adımda kullanmalı ve bu kararları projenin gerçek ihtiyacına nasıl bağlamalı.","md",true,{},"\u002Fyazilar\u002Fteknoloji-ve-ai-kararlari",10,{"title":6,"description":382},"yazilar\u002Fteknoloji-ve-ai-kararlari",[391,378,392],"AI","Teknoloji Seçimi","7kSI0_9qdl659dQ__tlhEG-5KdkoJnp8Av1XrY5-7Qw",{"id":395,"title":396,"body":397,"category":1092,"cover":1093,"date":1094,"demo":381,"description":1095,"draft":381,"extension":383,"featured":384,"meta":1096,"navigation":384,"path":1097,"readingTime":565,"seo":1098,"stem":1099,"tags":1100,"updated":380,"__hash__":1103},"blog\u002Fyazilar\u002Fnuxt-cloudflare-workers-yayinlama.md","Nuxt Uygulamasını Cloudflare Workers'da Yayınlamak",{"type":8,"value":398,"toc":1082},[399,402,405,409,412,471,489,493,496,600,618,622,625,711,718,724,731,735,738,826,832,836,843,923,941,950,954,960,963,986,997,1001,1004,1021,1032,1036,1039,1069,1072,1078],[11,400,401],{},"Nuxt uygulamasını edge ortamına taşımak yalnızca deploy hedefinin adını değiştirmek değil. Sunucu çıktısının Web API'leriyle uyumu, statik dosyaların nasıl sunulduğu ve secret'ların build ile runtime arasındaki yeri birlikte düşünülmeli.",[11,403,404],{},"Bu not, okuduğun sitenin Cloudflare Workers kurulumundan çıktı. Yapı küçük tutuldu: ayrı bir adaptör katmanı yerine Nitro'nun kendi Cloudflare preset'i ve resmi Wrangler aracı kullanılıyor.",[23,406,408],{"id":407},"sürümleri-sabitle","Sürümleri sabitle",[11,410,411],{},"Build ortamında sürpriz yaşamamak için Node ve paket yöneticisi sürümleri depoda tanımlı:",[413,414,418],"pre",{"className":415,"code":416,"language":417,"meta":365,"style":365},"language-json shiki shiki-themes github-dark","{\n  \"packageManager\": \"pnpm@11.19.0\",\n  \"engines\": { \"node\": \"24.x\" }\n}\n","json",[419,420,421,430,446,465],"code",{"__ignoreMap":365},[422,423,426],"span",{"class":424,"line":425},"line",1,[422,427,429],{"class":428},"s95oV","{\n",[422,431,432,436,439,443],{"class":424,"line":366},[422,433,435],{"class":434},"sDLfK","  \"packageManager\"",[422,437,438],{"class":428},": ",[422,440,442],{"class":441},"sU2Wk","\"pnpm@11.19.0\"",[422,444,445],{"class":428},",\n",[422,447,448,451,454,457,459,462],{"class":424,"line":367},[422,449,450],{"class":434},"  \"engines\"",[422,452,453],{"class":428},": { ",[422,455,456],{"class":434},"\"node\"",[422,458,438],{"class":428},[422,460,461],{"class":441},"\"24.x\"",[422,463,464],{"class":428}," }\n",[422,466,468],{"class":424,"line":467},4,[422,469,470],{"class":428},"}\n",[11,472,473,476,477,480,481,484,485,488],{},[419,474,475],{},".node-version"," dosyası da ",[419,478,479],{},"24"," değerini taşır. Cloudflare Workers Builds bu dosyayı okuyabilir; ",[419,482,483],{},"packageManager"," ise Corepack'in aynı pnpm sürümünü seçmesini sağlar. Kurulumda ",[419,486,487],{},"pnpm install --frozen-lockfile"," kullanmak, manifest ile kilit dosyası uyuşmadığında sessizce farklı bağımlılık çözülmesini engeller.",[23,490,492],{"id":491},"modern-worker-presetini-açıkça-seç","Modern Worker preset'ini açıkça seç",[11,494,495],{},"Nuxt'un sunucu katmanı Nitro tarafından hazırlanır. Bu projede hedef ES module tabanlı Cloudflare Worker'dır:",[413,497,501],{"className":498,"code":499,"language":500,"meta":365,"style":365},"language-ts shiki shiki-themes github-dark","export default defineNuxtConfig({\n  content: {\n    experimental: { sqliteConnector: \"native\" },\n    database: { type: \"d1\", bindingName: \"DB\" },\n  },\n  nitro: {\n    preset: \"cloudflare_module\",\n    prerender: { crawlLinks: true, failOnError: true },\n  },\n});\n","ts",[419,502,503,519,524,535,551,557,563,574,590,595],{"__ignoreMap":365},[422,504,505,509,512,516],{"class":424,"line":425},[422,506,508],{"class":507},"snl16","export",[422,510,511],{"class":507}," default",[422,513,515],{"class":514},"svObZ"," defineNuxtConfig",[422,517,518],{"class":428},"({\n",[422,520,521],{"class":424,"line":366},[422,522,523],{"class":428},"  content: {\n",[422,525,526,529,532],{"class":424,"line":367},[422,527,528],{"class":428},"    experimental: { sqliteConnector: ",[422,530,531],{"class":441},"\"native\"",[422,533,534],{"class":428}," },\n",[422,536,537,540,543,546,549],{"class":424,"line":467},[422,538,539],{"class":428},"    database: { type: ",[422,541,542],{"class":441},"\"d1\"",[422,544,545],{"class":428},", bindingName: ",[422,547,548],{"class":441},"\"DB\"",[422,550,534],{"class":428},[422,552,554],{"class":424,"line":553},5,[422,555,556],{"class":428},"  },\n",[422,558,560],{"class":424,"line":559},6,[422,561,562],{"class":428},"  nitro: {\n",[422,564,566,569,572],{"class":424,"line":565},7,[422,567,568],{"class":428},"    preset: ",[422,570,571],{"class":441},"\"cloudflare_module\"",[422,573,445],{"class":428},[422,575,577,580,583,586,588],{"class":424,"line":576},8,[422,578,579],{"class":428},"    prerender: { crawlLinks: ",[422,581,582],{"class":434},"true",[422,584,585],{"class":428},", failOnError: ",[422,587,582],{"class":434},[422,589,534],{"class":428},[422,591,593],{"class":424,"line":592},9,[422,594,556],{"class":428},[422,596,597],{"class":424,"line":387},[422,598,599],{"class":428},"});\n",[11,601,602,605,606,609,610,613,614,617],{},[419,603,604],{},"cloudflare_module",", Worker'ın beklediği ",[419,607,608],{},"fetch"," girişini üretir. Çıktının sunucu parçası ",[419,611,612],{},".output\u002Fserver\u002Findex.mjs",", tarayıcıya açık dosyaları ise ",[419,615,616],{},".output\u002Fpublic"," altında bulunur.",[23,619,621],{"id":620},"worker-kodu-ve-assetleri-birlikte-yayınla","Worker kodu ve asset'leri birlikte yayınla",[11,623,624],{},"Wrangler yapılandırmasının esas bölümü iki çıktı dizinini birbirine bağlar:",[413,626,628],{"className":415,"code":627,"language":417,"meta":365,"style":365},"{\n  \"name\": \"mehmet-macar\",\n  \"main\": \".output\u002Fserver\u002Findex.mjs\",\n  \"compatibility_flags\": [\"nodejs_compat\"],\n  \"assets\": {\n    \"binding\": \"ASSETS\",\n    \"directory\": \".output\u002Fpublic\"\n  }\n}\n",[419,629,630,634,646,658,672,680,692,702,707],{"__ignoreMap":365},[422,631,632],{"class":424,"line":425},[422,633,429],{"class":428},[422,635,636,639,641,644],{"class":424,"line":366},[422,637,638],{"class":434},"  \"name\"",[422,640,438],{"class":428},[422,642,643],{"class":441},"\"mehmet-macar\"",[422,645,445],{"class":428},[422,647,648,651,653,656],{"class":424,"line":367},[422,649,650],{"class":434},"  \"main\"",[422,652,438],{"class":428},[422,654,655],{"class":441},"\".output\u002Fserver\u002Findex.mjs\"",[422,657,445],{"class":428},[422,659,660,663,666,669],{"class":424,"line":467},[422,661,662],{"class":434},"  \"compatibility_flags\"",[422,664,665],{"class":428},": [",[422,667,668],{"class":441},"\"nodejs_compat\"",[422,670,671],{"class":428},"],\n",[422,673,674,677],{"class":424,"line":553},[422,675,676],{"class":434},"  \"assets\"",[422,678,679],{"class":428},": {\n",[422,681,682,685,687,690],{"class":424,"line":559},[422,683,684],{"class":434},"    \"binding\"",[422,686,438],{"class":428},[422,688,689],{"class":441},"\"ASSETS\"",[422,691,445],{"class":428},[422,693,694,697,699],{"class":424,"line":565},[422,695,696],{"class":434},"    \"directory\"",[422,698,438],{"class":428},[422,700,701],{"class":441},"\".output\u002Fpublic\"\n",[422,703,704],{"class":424,"line":576},[422,705,706],{"class":428},"  }\n",[422,708,709],{"class":424,"line":592},[422,710,470],{"class":428},[11,712,713,714,717],{},"Statik bir dosya eşleştiğinde Workers Assets bunu doğrudan sunar. ",[419,715,716],{},"\u002Fapi\u002Fcontact"," gibi bir asset'e karşılık gelmeyen istek Worker'a ulaşır. Böylece prerender edilmiş sayfalar ile server endpoint'i aynı deployment içinde kalır.",[11,719,720,723],{},[419,721,722],{},"nodejs_compat"," bayrağı, bağımlılıkların ihtiyaç duyduğu Node uyumluluk API'lerini Workers runtime'ında açar. Bu yine de klasik bir Node sunucusunda çalışıldığı anlamına gelmez; dosya sistemi veya uzun yaşayan process varsayımı yapılmamalıdır.",[11,725,726,727,730],{},"Nuxt Content'in Workers runtime'ında sorgu çalıştırabilmesi için ",[419,728,729],{},"DB"," adlı Cloudflare D1 binding'i de gerekir. Wrangler'ın kimliksiz resource provisioning özelliğiyle binding config'e yazılıp veritabanı ilk deploy sırasında oluşturulabilir; böylece hesap özelindeki database ID'yi repoya önceden koymak gerekmez.",[23,732,734],{"id":733},"prerenderı-yayın-öncesi-kontrol-olarak-kullan","Prerender'ı yayın öncesi kontrol olarak kullan",[11,736,737],{},"İçerik sayfaları build sırasında hazırlanır ve bağlantılar taranır:",[413,739,741],{"className":498,"code":740,"language":500,"meta":365,"style":365},"routeRules: {\n  \"\u002F\": { prerender: true },\n  \"\u002Fyazilar\u002F**\": { prerender: true },\n  \"\u002Fprojeler\u002F**\": { prerender: true },\n},\nnitro: {\n  prerender: { crawlLinks: true, failOnError: true },\n}\n",[419,742,743,750,762,773,784,789,796,822],{"__ignoreMap":365},[422,744,745,748],{"class":424,"line":425},[422,746,747],{"class":514},"routeRules",[422,749,679],{"class":428},[422,751,752,755,758,760],{"class":424,"line":366},[422,753,754],{"class":441},"  \"\u002F\"",[422,756,757],{"class":428},": { prerender: ",[422,759,582],{"class":434},[422,761,534],{"class":428},[422,763,764,767,769,771],{"class":424,"line":367},[422,765,766],{"class":441},"  \"\u002Fyazilar\u002F**\"",[422,768,757],{"class":428},[422,770,582],{"class":434},[422,772,534],{"class":428},[422,774,775,778,780,782],{"class":424,"line":467},[422,776,777],{"class":441},"  \"\u002Fprojeler\u002F**\"",[422,779,757],{"class":428},[422,781,582],{"class":434},[422,783,534],{"class":428},[422,785,786],{"class":424,"line":553},[422,787,788],{"class":428},"},\n",[422,790,791,794],{"class":424,"line":559},[422,792,793],{"class":514},"nitro",[422,795,679],{"class":428},[422,797,798,801,803,806,808,810,813,816,818,820],{"class":424,"line":565},[422,799,800],{"class":514},"  prerender",[422,802,453],{"class":428},[422,804,805],{"class":514},"crawlLinks",[422,807,438],{"class":428},[422,809,582],{"class":434},[422,811,812],{"class":428},", ",[422,814,815],{"class":514},"failOnError",[422,817,438],{"class":428},[422,819,582],{"class":434},[422,821,534],{"class":428},[422,823,824],{"class":424,"line":576},[422,825,470],{"class":428},[11,827,828,831],{},[419,829,830],{},"failOnError: true",", bozuk bir içerik route'unu ziyaretçiden önce CI build'inde görünür kılar. İletişim API'si ise prerender edilmez; her POST isteği Worker içinde çalışır.",[23,833,835],{"id":834},"build-değişkeni-ile-runtime-secretını-ayır","Build değişkeni ile runtime secret'ını ayır",[11,837,838,839,842],{},"Nuxt runtime config'te ",[419,840,841],{},"public"," altındaki değerler istemciye gidebilir, diğerleri yalnız sunucuda kalır:",[413,844,846],{"className":498,"code":845,"language":500,"meta":365,"style":365},"runtimeConfig: {\n  resendApiKey: \"\",\n  contactEmail: \"\",\n  contactFrom: \"\",\n  public: {\n    siteUrl: process.env.NUXT_PUBLIC_SITE_URL || \"http:\u002F\u002Flocalhost:3000\",\n  },\n}\n",[419,847,848,855,867,878,889,896,915,919],{"__ignoreMap":365},[422,849,850,853],{"class":424,"line":425},[422,851,852],{"class":514},"runtimeConfig",[422,854,679],{"class":428},[422,856,857,860,862,865],{"class":424,"line":366},[422,858,859],{"class":514},"  resendApiKey",[422,861,438],{"class":428},[422,863,864],{"class":441},"\"\"",[422,866,445],{"class":428},[422,868,869,872,874,876],{"class":424,"line":367},[422,870,871],{"class":514},"  contactEmail",[422,873,438],{"class":428},[422,875,864],{"class":441},[422,877,445],{"class":428},[422,879,880,883,885,887],{"class":424,"line":467},[422,881,882],{"class":514},"  contactFrom",[422,884,438],{"class":428},[422,886,864],{"class":441},[422,888,445],{"class":428},[422,890,891,894],{"class":424,"line":553},[422,892,893],{"class":514},"  public",[422,895,679],{"class":428},[422,897,898,901,904,907,910,913],{"class":424,"line":559},[422,899,900],{"class":514},"    siteUrl",[422,902,903],{"class":428},": process.env.",[422,905,906],{"class":434},"NUXT_PUBLIC_SITE_URL",[422,908,909],{"class":507}," ||",[422,911,912],{"class":441}," \"http:\u002F\u002Flocalhost:3000\"",[422,914,445],{"class":428},[422,916,917],{"class":424,"line":565},[422,918,556],{"class":428},[422,920,921],{"class":424,"line":576},[422,922,470],{"class":428},[11,924,925,926,812,929,932,933,936,937,940],{},"Runtime override isimleri sırasıyla ",[419,927,928],{},"NUXT_RESEND_API_KEY",[419,930,931],{},"NUXT_CONTACT_EMAIL"," ve ",[419,934,935],{},"NUXT_CONTACT_FROM"," olur. Resend anahtarının ",[419,938,939],{},"NUXT_PUBLIC_"," ile başlamaması kritik; aksi hâlde gizli değer istemci yapılandırmasına taşınabilir.",[11,942,943,945,946,949],{},[419,944,906],{}," ise gerçekten public'tir. Canonical, sitemap ve RSS prerender sırasında üretildiği için bu değer Cloudflare'ın build ortamında ",[419,947,948],{},"https:\u002F\u002Fmehmetmacar.com"," olarak tanımlanır. Aynı değer origin kontrolü için Worker runtime variable olarak da bulunur.",[23,951,953],{"id":952},"i̇letişim-formunu-edgede-güvenli-tut","İletişim formunu edge'de güvenli tut",[11,955,956,957,959],{},"Form tarayıcıdan doğrudan Resend'e gitmez. Ziyaretçi ",[419,958,716],{}," endpoint'ine JSON gönderir; Worker girdiyi doğruladıktan sonra Resend API'yi server-side çağırır.",[11,961,962],{},"Bu projedeki temel kontroller:",[31,964,965,968,971,974,977,983],{},[34,966,967],{},"Alan tipi, e-posta biçimi, boşluk ve uzunluk doğrulaması",[34,969,970],{},"JSON ve toplam istek boyutu sınırı",[34,972,973],{},"Honeypot alanı",[34,975,976],{},"Site origin kontrolü",[34,978,979,982],{},[419,980,981],{},"CF-Connecting-IP"," üzerinden temel, isolate içi rate limit",[34,984,985],{},"Sağlayıcı hatasını ve form içeriğini loglara taşımayan hata cevabı",[11,987,988,989,992,993,996],{},"Mailin ",[419,990,991],{},"Reply-To"," alanına ziyaretçinin adresi yazılır. Böylece gerçek alıcı kutusunda ",[15,994,995],{},"Yanıtla"," seçildiğinde yanıt formu dolduran kişiye gider.",[23,998,1000],{"id":999},"github-pushunu-deploymenta-dönüştür","GitHub push'unu deployment'a dönüştür",[11,1002,1003],{},"Workers Builds için işlem iki adımlıdır:",[413,1005,1009],{"className":1006,"code":1007,"language":1008,"meta":365,"style":365},"language-sh shiki shiki-themes github-dark","corepack pnpm build\ncorepack pnpm exec wrangler deploy\n","sh",[419,1010,1011,1016],{"__ignoreMap":365},[422,1012,1013],{"class":424,"line":425},[422,1014,1015],{},"corepack pnpm build\n",[422,1017,1018],{"class":424,"line":366},[422,1019,1020],{},"corepack pnpm exec wrangler deploy\n",[11,1022,1023,1024,1027,1028,1031],{},"İlk komut Nuxt\u002FNitro çıktısını üretir, ikincisi Worker ile asset'leri yükler. Production branch ",[419,1025,1026],{},"main"," olduğunda bu branch'e gelen push aktif deployment'ı günceller. Diğer branch'lerde ",[419,1029,1030],{},"wrangler versions upload"," kullanılırsa production'ı değiştirmeden preview version alınabilir.",[23,1033,1035],{"id":1034},"deploy-etmeden-bundleı-doğrula","Deploy etmeden bundle'ı doğrula",[11,1037,1038],{},"Gerçek hesapta değişiklik yapmadan önce üç kontrol yeterli bir taban sağlar:",[413,1040,1042],{"className":1006,"code":1041,"language":1008,"meta":365,"style":365},"pnpm lint\npnpm typecheck\npnpm test\npnpm build\npnpm exec wrangler deploy --dry-run\n",[419,1043,1044,1049,1054,1059,1064],{"__ignoreMap":365},[422,1045,1046],{"class":424,"line":425},[422,1047,1048],{},"pnpm lint\n",[422,1050,1051],{"class":424,"line":366},[422,1052,1053],{},"pnpm typecheck\n",[422,1055,1056],{"class":424,"line":367},[422,1057,1058],{},"pnpm test\n",[422,1060,1061],{"class":424,"line":467},[422,1062,1063],{},"pnpm build\n",[422,1065,1066],{"class":424,"line":553},[422,1067,1068],{},"pnpm exec wrangler deploy --dry-run\n",[11,1070,1071],{},"Dry-run, Wrangler'ın Worker girişini ve statik asset yapılandırmasını okuyabildiğini gösterir. Canlı dağıtımdan sonra doğrudan detay URL'leri, sitemap\u002FRSS\u002Frobots, 404 ve iletişim formu ayrıca sınanmalıdır. Build'in başarılı olması DNS, domain doğrulaması veya gerçek e-posta teslimini tek başına kanıtlamaz.",[86,1073,1075],{"title":1074,"type":360},"Platform ayarları zamanla değişir",[11,1076,1077],{},"Bu yapı Nuxt 4.5, Nitro 2.13 ve Wrangler 4 ile hazırlanmıştır. Compatibility date ve Wrangler sürümü güncellenirken Cloudflare'ın güncel framework rehberiyle yeniden karşılaştırılmalıdır.",[1079,1080,1081],"style",{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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 pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":365,"searchDepth":366,"depth":367,"links":1083},[1084,1085,1086,1087,1088,1089,1090,1091],{"id":407,"depth":366,"text":408},{"id":491,"depth":366,"text":492},{"id":620,"depth":366,"text":621},{"id":733,"depth":366,"text":734},{"id":834,"depth":366,"text":835},{"id":952,"depth":366,"text":953},{"id":999,"depth":366,"text":1000},{"id":1034,"depth":366,"text":1035},"Nuxt","\u002Fimages\u002Fblog\u002Fdeploy.svg","2026-09-05","Nitro preset, Workers Assets, Wrangler ve runtime secret'larıyla Nuxt 4 uygulamasını Cloudflare Workers'a hazırlarken önemli kararlar.",{},"\u002Fyazilar\u002Fnuxt-cloudflare-workers-yayinlama",{"title":396,"description":1095},"yazilar\u002Fnuxt-cloudflare-workers-yayinlama",[1092,1101,1102],"DevOps","Cloudflare","-5UWtZ5sVsNkp_2BonyAXDc_YGPfbgC0x2E4S37id10",{"id":1105,"title":1106,"body":1107,"category":1580,"cover":1581,"date":1582,"demo":381,"description":1583,"draft":381,"extension":383,"featured":384,"meta":1584,"navigation":384,"path":1585,"readingTime":592,"seo":1586,"stem":1587,"tags":1588,"updated":1582,"__hash__":1590},"blog\u002Fyazilar\u002Fayni-metrik-farkli-sayi.md","Aynı Metrik İki Ekranda Neden Farklı Çıkıyor?",{"type":8,"value":1108,"toc":1570},[1109,1116,1119,1123,1126,1146,1149,1155,1159,1165,1171,1177,1183,1187,1190,1196,1202,1209,1212,1454,1461,1465,1472,1475,1482,1485,1489,1492,1495,1499,1502,1510,1513,1520,1523,1527,1530,1547,1550,1552,1559,1562,1567],[11,1110,1111,1112,1115],{},"Bir dashboard'da en can sıkıcı hata türü budur: iki ekran aynı metriği gösteriyor, isimleri aynı, ama sayılar tutmuyor. Toplantıda birisi fark ediyor ve o andan itibaren ",[15,1113,1114],{},"ekranların hiçbirine güvenilmiyor"," — doğru olan da dahil.",[11,1117,1118],{},"İlk refleks hesaplamayı kontrol etmek oluyor. Neredeyse her seferinde yanlış yer.",[23,1120,1122],{"id":1121},"sorun-kapsamın-tanımında","Sorun kapsamın tanımında",[11,1124,1125],{},"Bir metrik üç şeyden oluşuyor ve isim bunların hiçbirini içermiyor:",[31,1127,1128,1134,1140],{},[34,1129,1130,1133],{},[15,1131,1132],{},"Küme:"," Hangi kayıtlar sayılıyor? Test kayıtları dahil mi? Silinmiş olanlar? Belirli bir alt kırılıma ait olanlar?",[34,1135,1136,1139],{},[15,1137,1138],{},"Zaman:"," Hangi tarih alanına göre filtreleniyor? Kaydın oluşturulma tarihi mi, güncellenme tarihi mi, ilgili olayın gerçekleştiği tarih mi?",[34,1141,1142,1145],{},[15,1143,1144],{},"Durum:"," Hangi aşamalar \"başarılı\" sayılıyor? Bu liste iki ekranda aynı mı?",[11,1147,1148],{},"İki ekran farklı sayı gösteriyorsa, bu üçünden en az biri farklıdır. Hesaplama formülü genellikle ikisinde de doğrudur; sadece farklı kümeler üzerinde doğrudur.",[86,1150,1152],{"title":1151,"type":89},"Önce farkı ölç, sonra açıkla",[11,1153,1154],{},"Hangi ekranın doğru olduğunu tartışmadan önce, aradaki kayıtları listele. Bir ekranda olup diğerinde olmayan kayıtları görmek, sorunun hangi eksende olduğunu genellikle tek bakışta gösteriyor: hepsi aynı tarih aralığının kenarındaysa zaman, hepsi aynı aşamadaysa durum, hepsi aynı kırılıma aitse küme.",[23,1156,1158],{"id":1157},"en-sık-karşılaşılan-üç-ayrışma","En sık karşılaşılan üç ayrışma",[11,1160,1161,1164],{},[15,1162,1163],{},"Farklı tarih alanı."," Bir ekran kaydın sisteme düştüğü tarihe, diğeri son güncellenme tarihine bakıyor. Ay sonunda güncellenen mayıs kaydı, birinde mayısta diğerinde haziranda görünüyor.",[11,1166,1167,1170],{},[15,1168,1169],{},"Farklı durum listesi."," \"Başarılı\" sayılan aşamalar bir ekranda üç, diğerinde iki tane. Bir aşama sonradan eklenmiş, ama sadece bir sorguya.",[11,1172,1173,1176],{},[15,1174,1175],{},"Sessiz filtre."," Bir ekranda kullanıcının önceden seçtiği bir daraltma açık kalmış. Sayı yanlış değil, sadece dar bir kümenin doğru sayısı.",[11,1178,1179,1180,18],{},"Üçünün de ortak yanı şu: hiçbiri hatalı kod değil. Hepsi ",[15,1181,1182],{},"eksik anlaşma",[23,1184,1186],{"id":1185},"anlık-durum-mu-o-tarihteki-durum-mu","Anlık durum mu, o tarihteki durum mu?",[11,1188,1189],{},"Bu, dönemsel raporlarda en çok yanılgı üreten ayrım ve genellikle hiç konuşulmuyor.",[11,1191,1192,1195],{},[15,1193,1194],{},"Anlık analiz"," kayıtların şu andaki durumuna bakıyor: \"Mayısta gelen kayıtların bugün kaçı tamamlanmış?\"",[11,1197,1198,1201],{},[15,1199,1200],{},"Seçili dönem analizi"," kayıtların geçmiş bir tarihteki durumunu yeniden kuruyor: \"Mayısta gelen kayıtlar, 15 Mayıs'ta hangi aşamadaydı?\"",[11,1203,1204,1205,1208],{},"İkisi de doğru sorular ama aynı soru değiller. Karıştırıldığında ortaya sistematik bir yanlış çıkıyor: geçmiş bir dönemi bugünün aşama dağılımıyla okumak, o dönemde ",[15,1206,1207],{},"henüz olgunlaşmamış"," kayıtları başarısız gibi gösteriyor. Yeni gelmiş bir kayıt doğal olarak ilk aşamada; ona bakıp \"bu ayın performansı düşük\" demek, sürecin kendisini değil geçen süreyi ölçmek oluyor.",[11,1210,1211],{},"Teknik olarak fark, tek bir tabloya bakmakla bir geçmiş tablosuna bakmak arasında:",[413,1213,1217],{"className":1214,"code":1215,"language":1216,"meta":365,"style":365},"language-sql shiki shiki-themes github-dark","-- Anlık: kaydın bugünkü aşaması\nSELECT stage, COUNT(*) FROM records\nWHERE created_at >= '2026-05-01' AND created_at \u003C '2026-06-01'\nGROUP BY stage;\n\n-- Seçili dönem: kaydın o tarihteki aşaması\nSELECT h.stage, COUNT(*)\nFROM records r\nJOIN stage_history h ON h.record_id = r.id\nWHERE r.created_at >= '2026-05-01' AND r.created_at \u003C '2026-06-01'\n  AND h.valid_from \u003C= '2026-05-15'\n  AND (h.valid_to IS NULL OR h.valid_to > '2026-05-15')\nGROUP BY h.stage;\n","sql",[419,1218,1219,1225,1251,1276,1284,1289,1294,1317,1324,1353,1382,1401,1440],{"__ignoreMap":365},[422,1220,1221],{"class":424,"line":425},[422,1222,1224],{"class":1223},"sAwPA","-- Anlık: kaydın bugünkü aşaması\n",[422,1226,1227,1230,1233,1236,1239,1242,1245,1248],{"class":424,"line":366},[422,1228,1229],{"class":507},"SELECT",[422,1231,1232],{"class":428}," stage, ",[422,1234,1235],{"class":434},"COUNT",[422,1237,1238],{"class":428},"(",[422,1240,1241],{"class":507},"*",[422,1243,1244],{"class":428},") ",[422,1246,1247],{"class":507},"FROM",[422,1249,1250],{"class":428}," records\n",[422,1252,1253,1256,1259,1262,1265,1268,1270,1273],{"class":424,"line":367},[422,1254,1255],{"class":507},"WHERE",[422,1257,1258],{"class":428}," created_at ",[422,1260,1261],{"class":507},">=",[422,1263,1264],{"class":441}," '2026-05-01'",[422,1266,1267],{"class":507}," AND",[422,1269,1258],{"class":428},[422,1271,1272],{"class":507},"\u003C",[422,1274,1275],{"class":441}," '2026-06-01'\n",[422,1277,1278,1281],{"class":424,"line":467},[422,1279,1280],{"class":507},"GROUP BY",[422,1282,1283],{"class":428}," stage;\n",[422,1285,1286],{"class":424,"line":553},[422,1287,1288],{"emptyLinePlaceholder":384},"\n",[422,1290,1291],{"class":424,"line":559},[422,1292,1293],{"class":1223},"-- Seçili dönem: kaydın o tarihteki aşaması\n",[422,1295,1296,1298,1301,1303,1306,1308,1310,1312,1314],{"class":424,"line":565},[422,1297,1229],{"class":507},[422,1299,1300],{"class":434}," h",[422,1302,18],{"class":428},[422,1304,1305],{"class":434},"stage",[422,1307,812],{"class":428},[422,1309,1235],{"class":434},[422,1311,1238],{"class":428},[422,1313,1241],{"class":507},[422,1315,1316],{"class":428},")\n",[422,1318,1319,1321],{"class":424,"line":576},[422,1320,1247],{"class":507},[422,1322,1323],{"class":428}," records r\n",[422,1325,1326,1329,1332,1335,1337,1339,1342,1345,1348,1350],{"class":424,"line":592},[422,1327,1328],{"class":507},"JOIN",[422,1330,1331],{"class":428}," stage_history h ",[422,1333,1334],{"class":507},"ON",[422,1336,1300],{"class":434},[422,1338,18],{"class":428},[422,1340,1341],{"class":434},"record_id",[422,1343,1344],{"class":507}," =",[422,1346,1347],{"class":434}," r",[422,1349,18],{"class":428},[422,1351,1352],{"class":434},"id\n",[422,1354,1355,1357,1359,1361,1364,1367,1369,1371,1373,1375,1377,1380],{"class":424,"line":387},[422,1356,1255],{"class":507},[422,1358,1347],{"class":434},[422,1360,18],{"class":428},[422,1362,1363],{"class":434},"created_at",[422,1365,1366],{"class":507}," >=",[422,1368,1264],{"class":441},[422,1370,1267],{"class":507},[422,1372,1347],{"class":434},[422,1374,18],{"class":428},[422,1376,1363],{"class":434},[422,1378,1379],{"class":507}," \u003C",[422,1381,1275],{"class":441},[422,1383,1385,1388,1390,1392,1395,1398],{"class":424,"line":1384},11,[422,1386,1387],{"class":507},"  AND",[422,1389,1300],{"class":434},[422,1391,18],{"class":428},[422,1393,1394],{"class":434},"valid_from",[422,1396,1397],{"class":507}," \u003C=",[422,1399,1400],{"class":441}," '2026-05-15'\n",[422,1402,1404,1406,1409,1412,1414,1417,1420,1423,1426,1428,1430,1432,1435,1438],{"class":424,"line":1403},12,[422,1405,1387],{"class":507},[422,1407,1408],{"class":428}," (",[422,1410,1411],{"class":434},"h",[422,1413,18],{"class":428},[422,1415,1416],{"class":434},"valid_to",[422,1418,1419],{"class":507}," IS",[422,1421,1422],{"class":507}," NULL",[422,1424,1425],{"class":507}," OR",[422,1427,1300],{"class":434},[422,1429,18],{"class":428},[422,1431,1416],{"class":434},[422,1433,1434],{"class":507}," >",[422,1436,1437],{"class":441}," '2026-05-15'",[422,1439,1316],{"class":428},[422,1441,1443,1445,1447,1449,1451],{"class":424,"line":1442},13,[422,1444,1280],{"class":507},[422,1446,1300],{"class":434},[422,1448,18],{"class":428},[422,1450,1305],{"class":434},[422,1452,1453],{"class":428},";\n",[11,1455,1456,1457,1460],{},"İkincisi ancak aşama değişikliklerinin geçmişini tutuyorsan mümkün. Bu yüzden karar mimariye ait: ",[15,1458,1459],{},"geçmişi tutmuyorsan, dönemsel analiz yapamıyorsun"," — sadece bugünün fotoğrafını geçmişe uygulayabiliyorsun ki bu da yanlış cevap veriyor.",[23,1462,1464],{"id":1463},"ortak-filtre-bir-sözleşmedir","Ortak filtre bir sözleşmedir",[11,1466,1467,1468,1471],{},"Çok kanallı lead yönlendirme ve analiz üzerine çalıştığım sistemde bu problem tekrar tekrar karşıma çıktı. Çözüm tek bir formülü düzeltmek değildi; ",[15,1469,1470],{},"filtreyi ekranlar arasında bir sözleşmeye dönüştürmek"," oldu.",[11,1473,1474],{},"Pratikte şu anlama geliyor: tarih aralığı, kırılım, sorumlu kişi, kaynak gibi seçimler her sekmede aynı anlamı taşıyor ve aynı kümeyi üretiyor. Bir ekran kendi başına ek bir daraltma yapmıyor. Aynı filtreyi kullanan her ekran, aynı kayıt kümesini değerlendiriyor.",[11,1476,1477,1478,1481],{},"Bunun bir sonucu var: filtre artık bir arayüz detayı değil, ",[15,1479,1480],{},"paylaşılan bir tanım",". Yeni bir ekran eklerken de aynı yapıya bağlanması gerekiyor; kendi sorgusunu yazması değil.",[11,1483,1484],{},"Aynı mantık metriğin kendisi için de geçerli. \"Başarılı sayılan aşamalar\" listesi tek bir yerde tanımlanıyor ve bütün sorgular oradan besleniyor. Yeni bir aşama eklendiğinde tek bir yer değişiyor — sekiz ayrı sorgu değil.",[23,1486,1488],{"id":1487},"detay-ekranı-filtreyi-devralmamalı","Detay ekranı filtreyi devralmamalı",[11,1490,1491],{},"Küçük ama önemli bir davranış: bir karttaki sayıya tıklayıp detay açtığında, o detayın kapsamı kartın kapsamıyla birebir aynı olmalı. Başka bir sekmede yapılmış daraltıcı bir seçimin sessizce taşınması, kullanıcının gördüğü sayıyla açtığı listenin uyuşmamasına yol açıyor.",[11,1493,1494],{},"Bu yüzden detay açılışında filtreyi bilinçli olarak varsayılana döndürmek, \"kullanıcının son seçimini hatırlamak\"tan daha doğru bir davranış oluyor. Kullanıcı tıkladığı sayının dökümünü görmek istiyor; başka bir yerde bıraktığı ayarın etkisini değil.",[23,1496,1498],{"id":1497},"paydayı-da-tanımla","Paydayı da tanımla",[11,1500,1501],{},"Oranlarda ikinci bir tuzak var: payı tanımlayıp paydayı unutmak.",[413,1503,1508],{"className":1504,"code":1506,"language":1507,"meta":365},[1505],"language-text","Dönüşüm (%) = (başarılı kayıt \u002F toplam kayıt) × 100\n","text",[419,1509,1506],{"__ignoreMap":365},[11,1511,1512],{},"Buradaki \"toplam\" ne? Gelen tüm kayıtlar mı, yoksa yalnızca ulaşılabilmiş olanlar mı? İkisi de anlamlı metrik üretiyor ama çok farklı sayılar veriyor ve ikisi de \"dönüşüm oranı\" diye adlandırılabiliyor.",[11,1514,1515,1516,1519],{},"Çözüm ikisini birden göstermek ve ",[15,1517,1518],{},"adlarını ayırmak",": \"gelen → başarılı\" ve \"ulaşılan → başarılı\". İki ayrı sütun, iki ayrı isim. Aynı isimle iki farklı payda kullanmak, en baştaki güven sorununu geri getiriyor.",[11,1521,1522],{},"Ayrıca payda sıfırken ne olacağı da tanımlanmalı. Sıfıra bölme hatası vermek yerine oranı sıfır kabul etmek, raporun bozulmadan çalışmasını sağlıyor.",[23,1524,1526],{"id":1525},"kontrol-listesi","Kontrol listesi",[11,1528,1529],{},"Yeni bir metrik ya da ekran eklerken sorduklarım:",[31,1531,1532,1535,1538,1541,1544],{},[34,1533,1534],{},"Bu metriğin kümesi, zaman alanı ve durum listesi nerede tanımlı?",[34,1536,1537],{},"Aynı tanımı kullanan başka ekranlar var mı, onlar da aynı yerden mi besleniyor?",[34,1539,1540],{},"Bu anlık bir sayı mı, dönemsel bir sayı mı? Ekranda bu ayrım görünüyor mu?",[34,1542,1543],{},"Oransa paydası ne ve adı bunu yansıtıyor mu?",[34,1545,1546],{},"Filtre değişince bu ekran diğerleriyle aynı yönde mi hareket ediyor?",[11,1548,1549],{},"Son madde en pratik testi veriyor: bir filtreyi değiştirdiğinde bütün ekranlar tutarlı biçimde hareket ediyorsa, kapsam ortak demektir. Biri sabit kalıyorsa, kendi sorgusunu yazıyor demektir.",[23,1551,350],{"id":349},[11,1553,1554,1555,1558],{},"Bir rakamın doğru olması yetmiyor; ",[15,1556,1557],{},"hangi kapsam üzerinden hesaplandığının anlaşılabilir olması"," gerekiyor. Sorgulanabilir olmayan bir sayıyı savunmak da mümkün olmuyor.",[11,1560,1561],{},"İki ekran aynı metrik için farklı sayı gösteriyorsa, önce hesaplamaya değil tanıma bak. Sorun büyük ihtimalle orada.",[86,1563,1564],{"title":359,"type":360},[11,1565,1566],{},"Buradaki SQL parçaları kavramı anlatmak için yazılmış örneklerdir; belirli bir projenin üretim kodu ya da gerçek bir veri modeli değildir. Sayfada geçen oran ve aşama adları da örnektir; herhangi bir kuruma ait gerçek performans verisi paylaşılmıyor.",[1079,1568,1569],{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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);}",{"title":365,"searchDepth":366,"depth":367,"links":1571},[1572,1573,1574,1575,1576,1577,1578,1579],{"id":1121,"depth":366,"text":1122},{"id":1157,"depth":366,"text":1158},{"id":1185,"depth":366,"text":1186},{"id":1463,"depth":366,"text":1464},{"id":1487,"depth":366,"text":1488},{"id":1497,"depth":366,"text":1498},{"id":1525,"depth":366,"text":1526},{"id":349,"depth":366,"text":350},"Analitik","\u002Fimages\u002Fblog\u002Fmetrik-kapsam.svg","2026-09-02","Sorun genellikle hesaplamada değil, kapsamın tanımında. Küme, zaman ve durum üçlüsünü ekranlar arasında bir sözleşmeye bağlamak.",{},"\u002Fyazilar\u002Fayni-metrik-farkli-sayi",{"title":1106,"description":1583},"yazilar\u002Fayni-metrik-farkli-sayi",[1580,1589,378],"Dashboard","1Jwm09Jf5fJiw1mV_W5RIqgQnsf58dV_w5M3fnW4Bns",{"id":1592,"title":1593,"body":1594,"category":2329,"cover":2330,"date":2331,"demo":381,"description":2332,"draft":381,"extension":383,"featured":384,"meta":2333,"navigation":384,"path":2334,"readingTime":592,"seo":2335,"stem":2336,"tags":2337,"updated":2331,"__hash__":2340},"blog\u002Fyazilar\u002Fdis-servis-bildirim-kuyrugu.md","Dış Servise Bağlı Bildirimlerde Kesinti Bir Hata Değildir",{"type":8,"value":1595,"toc":2320},[1596,1602,1608,1612,1615,1694,1697,1711,1718,1722,1729,1732,1944,1947,1951,1958,2090,2097,2100,2109,2113,2116,2122,2173,2183,2189,2225,2228,2232,2235,2246,2249,2252,2256,2259,2275,2278,2285,2289,2292,2306,2312,2317],[11,1597,1598,1599],{},"Bir kaydı hem kendi sisteminde tutup hem de dışarıdaki bir servise bildirmen gerekiyorsa — bir kamu web servisi, bir CRM, bir muhasebe sistemi — er ya da geç şu soruyla karşılaşıyorsun: ",[15,1600,1601],{},"servis yanıt vermediğinde ne oluyor?",[11,1603,1604,1605,18],{},"Bu sorunun cevabı çoğu entegrasyonun kalitesini belirliyor. Çünkü dış servisin geçici olarak erişilemez olması bir istisna değil; yeterince uzun çalışan her sistemde ",[15,1606,1607],{},"beklenen bir durum",[23,1609,1611],{"id":1610},"gönder-ve-sonucu-göster-neden-yetmiyor","\"Gönder ve sonucu göster\" neden yetmiyor",[11,1613,1614],{},"En doğal kurgu şu: kullanıcı kaydı oluşturur, aynı istek içinde dış servise gönderilir, sonuç ekranda gösterilir.",[413,1616,1620],{"className":1617,"code":1618,"language":1619,"meta":365,"style":365},"language-php shiki shiki-themes github-dark","$record = Record::create($data);\n$response = $client->notify($record);   \u002F\u002F dış servis burada\nreturn $response->successful() ? 'Bildirildi' : 'Hata';\n","php",[419,1621,1622,1642,1664],{"__ignoreMap":365},[422,1623,1624,1627,1630,1633,1636,1639],{"class":424,"line":425},[422,1625,1626],{"class":428},"$record ",[422,1628,1629],{"class":507},"=",[422,1631,1632],{"class":434}," Record",[422,1634,1635],{"class":507},"::",[422,1637,1638],{"class":514},"create",[422,1640,1641],{"class":428},"($data);\n",[422,1643,1644,1647,1649,1652,1655,1658,1661],{"class":424,"line":366},[422,1645,1646],{"class":428},"$response ",[422,1648,1629],{"class":507},[422,1650,1651],{"class":428}," $client",[422,1653,1654],{"class":507},"->",[422,1656,1657],{"class":514},"notify",[422,1659,1660],{"class":428},"($record);   ",[422,1662,1663],{"class":1223},"\u002F\u002F dış servis burada\n",[422,1665,1666,1669,1672,1674,1677,1680,1683,1686,1689,1692],{"class":424,"line":367},[422,1667,1668],{"class":507},"return",[422,1670,1671],{"class":428}," $response",[422,1673,1654],{"class":507},[422,1675,1676],{"class":514},"successful",[422,1678,1679],{"class":428},"() ",[422,1681,1682],{"class":507},"?",[422,1684,1685],{"class":441}," 'Bildirildi'",[422,1687,1688],{"class":507}," :",[422,1690,1691],{"class":441}," 'Hata'",[422,1693,1453],{"class":428},[11,1695,1696],{},"Bu akış mutlu günde çalışıyor. Sorun mutsuz günde:",[31,1698,1699,1702,1705,1708],{},[34,1700,1701],{},"Servis yanıt vermiyor ve kullanıcı bir hata ekranı görüyor. Kayıt oluştu mu, olmadı mı belli değil.",[34,1703,1704],{},"Kullanıcı tekrar deniyor. Şimdi iki kayıt var.",[34,1706,1707],{},"Ya da kullanıcı vazgeçiyor. Kayıt sistemde duruyor ama hiç bildirilmemiş — ve bunu kimse bilmiyor.",[34,1709,1710],{},"İstek zaman aşımına uğruyor, ama dış servis aslında işlemi almış oluyor. En kötüsü bu.",[11,1712,1713,1714,1717],{},"Ortak kusur şu: ",[15,1715,1716],{},"kaydın kendisiyle bildiriminin durumu tek bir şeymiş gibi ele alınıyor."," Halbuki bunlar iki ayrı olay ve ikisi aynı anda başarılı olmak zorunda değil.",[23,1719,1721],{"id":1720},"bildirim-durumu-ayrı-bir-varlıktır","Bildirim durumu ayrı bir varlıktır",[11,1723,1724,1725,1728],{},"Kayıtta ",[419,1726,1727],{},"bildirildi"," diye bir boolean alan tutmak yeterli görünüyor ama değil. Bir bildirimin kendi geçmişi var: ne zaman denendi, kaç kez denendi, en son ne cevap geldi, hâlâ denenmeli mi?",[11,1730,1731],{},"Bunu ayrı bir tabloya taşımak işi tümüyle değiştiriyor:",[413,1733,1735],{"className":1214,"code":1734,"language":1216,"meta":365,"style":365},"CREATE TABLE outbox (\n  id            BIGINT PRIMARY KEY AUTO_INCREMENT,\n  record_id     BIGINT NOT NULL,\n  event_type    VARCHAR(64) NOT NULL,\n  payload       JSON NOT NULL,\n  idempotency_key VARCHAR(80) NOT NULL,\n  status        ENUM('pending','sent','failed') NOT NULL DEFAULT 'pending',\n  attempts      INT NOT NULL DEFAULT 0,\n  next_retry_at DATETIME NULL,\n  last_error    TEXT NULL,\n  created_at    DATETIME NOT NULL,\n  UNIQUE KEY uniq_idem (idempotency_key),\n  KEY idx_due (status, next_retry_at)\n);\n",[419,1736,1737,1751,1765,1777,1797,1809,1827,1861,1878,1890,1902,1913,1924,1938],{"__ignoreMap":365},[422,1738,1739,1742,1745,1748],{"class":424,"line":425},[422,1740,1741],{"class":507},"CREATE",[422,1743,1744],{"class":507}," TABLE",[422,1746,1747],{"class":514}," outbox",[422,1749,1750],{"class":428}," (\n",[422,1752,1753,1756,1759,1762],{"class":424,"line":366},[422,1754,1755],{"class":428},"  id            ",[422,1757,1758],{"class":507},"BIGINT",[422,1760,1761],{"class":507}," PRIMARY KEY",[422,1763,1764],{"class":428}," AUTO_INCREMENT,\n",[422,1766,1767,1770,1772,1775],{"class":424,"line":367},[422,1768,1769],{"class":428},"  record_id     ",[422,1771,1758],{"class":507},[422,1773,1774],{"class":507}," NOT NULL",[422,1776,445],{"class":428},[422,1778,1779,1782,1785,1787,1790,1792,1795],{"class":424,"line":467},[422,1780,1781],{"class":428},"  event_type    ",[422,1783,1784],{"class":507},"VARCHAR",[422,1786,1238],{"class":428},[422,1788,1789],{"class":434},"64",[422,1791,1244],{"class":428},[422,1793,1794],{"class":507},"NOT NULL",[422,1796,445],{"class":428},[422,1798,1799,1802,1805,1807],{"class":424,"line":553},[422,1800,1801],{"class":428},"  payload       ",[422,1803,1804],{"class":507},"JSON",[422,1806,1774],{"class":507},[422,1808,445],{"class":428},[422,1810,1811,1814,1816,1818,1821,1823,1825],{"class":424,"line":559},[422,1812,1813],{"class":428},"  idempotency_key ",[422,1815,1784],{"class":507},[422,1817,1238],{"class":428},[422,1819,1820],{"class":434},"80",[422,1822,1244],{"class":428},[422,1824,1794],{"class":507},[422,1826,445],{"class":428},[422,1828,1829,1832,1835,1838,1841,1844,1846,1849,1851,1853,1856,1859],{"class":424,"line":565},[422,1830,1831],{"class":507},"  status",[422,1833,1834],{"class":428},"        ENUM(",[422,1836,1837],{"class":441},"'pending'",[422,1839,1840],{"class":428},",",[422,1842,1843],{"class":441},"'sent'",[422,1845,1840],{"class":428},[422,1847,1848],{"class":441},"'failed'",[422,1850,1244],{"class":428},[422,1852,1794],{"class":507},[422,1854,1855],{"class":507}," DEFAULT",[422,1857,1858],{"class":441}," 'pending'",[422,1860,445],{"class":428},[422,1862,1863,1866,1869,1871,1873,1876],{"class":424,"line":576},[422,1864,1865],{"class":428},"  attempts      ",[422,1867,1868],{"class":507},"INT",[422,1870,1774],{"class":507},[422,1872,1855],{"class":507},[422,1874,1875],{"class":434}," 0",[422,1877,445],{"class":428},[422,1879,1880,1883,1886,1888],{"class":424,"line":592},[422,1881,1882],{"class":428},"  next_retry_at ",[422,1884,1885],{"class":507},"DATETIME",[422,1887,1422],{"class":507},[422,1889,445],{"class":428},[422,1891,1892,1895,1898,1900],{"class":424,"line":387},[422,1893,1894],{"class":428},"  last_error    ",[422,1896,1897],{"class":507},"TEXT",[422,1899,1422],{"class":507},[422,1901,445],{"class":428},[422,1903,1904,1907,1909,1911],{"class":424,"line":1384},[422,1905,1906],{"class":428},"  created_at    ",[422,1908,1885],{"class":507},[422,1910,1774],{"class":507},[422,1912,445],{"class":428},[422,1914,1915,1918,1921],{"class":424,"line":1403},[422,1916,1917],{"class":507},"  UNIQUE",[422,1919,1920],{"class":507}," KEY",[422,1922,1923],{"class":428}," uniq_idem (idempotency_key),\n",[422,1925,1926,1929,1932,1935],{"class":424,"line":1442},[422,1927,1928],{"class":507},"  KEY",[422,1930,1931],{"class":428}," idx_due (",[422,1933,1934],{"class":507},"status",[422,1936,1937],{"class":428},", next_retry_at)\n",[422,1939,1941],{"class":424,"line":1940},14,[422,1942,1943],{"class":428},");\n",[11,1945,1946],{},"Artık \"bu kayıt bildirildi mi\" sorusunun cevabı bir tahmin değil. Ne zaman denendiği, neyle sonuçlandığı ve sırada olup olmadığı görülebiliyor.",[23,1948,1950],{"id":1949},"kaydı-ve-bildirim-niyetini-aynı-anda-yaz","Kaydı ve bildirim niyetini aynı anda yaz",[11,1952,1953,1954,1957],{},"Kritik nokta: kaydı oluşturan işlemle bildirim satırını oluşturan işlem ",[15,1955,1956],{},"aynı transaction içinde"," olmalı.",[413,1959,1961],{"className":1617,"code":1960,"language":1619,"meta":365,"style":365},"DB::transaction(function () use ($data) {\n    $record = Record::create($data);\n    Outbox::create([\n        'record_id' => $record->id,\n        'event_type' => 'record.created',\n        'payload' => $record->toNotificationPayload(),\n        'idempotency_key' => \"record.created:{$record->id}\",\n    ]);\n});\n",[419,1962,1963,1986,2001,2013,2029,2041,2058,2081,2086],{"__ignoreMap":365},[422,1964,1965,1967,1969,1972,1974,1977,1980,1983],{"class":424,"line":425},[422,1966,729],{"class":434},[422,1968,1635],{"class":507},[422,1970,1971],{"class":514},"transaction",[422,1973,1238],{"class":428},[422,1975,1976],{"class":507},"function",[422,1978,1979],{"class":428}," () ",[422,1981,1982],{"class":507},"use",[422,1984,1985],{"class":428}," ($data) {\n",[422,1987,1988,1991,1993,1995,1997,1999],{"class":424,"line":366},[422,1989,1990],{"class":428},"    $record ",[422,1992,1629],{"class":507},[422,1994,1632],{"class":434},[422,1996,1635],{"class":507},[422,1998,1638],{"class":514},[422,2000,1641],{"class":428},[422,2002,2003,2006,2008,2010],{"class":424,"line":367},[422,2004,2005],{"class":434},"    Outbox",[422,2007,1635],{"class":507},[422,2009,1638],{"class":514},[422,2011,2012],{"class":428},"([\n",[422,2014,2015,2018,2021,2024,2026],{"class":424,"line":467},[422,2016,2017],{"class":441},"        'record_id'",[422,2019,2020],{"class":507}," =>",[422,2022,2023],{"class":428}," $record",[422,2025,1654],{"class":507},[422,2027,2028],{"class":428},"id,\n",[422,2030,2031,2034,2036,2039],{"class":424,"line":553},[422,2032,2033],{"class":441},"        'event_type'",[422,2035,2020],{"class":507},[422,2037,2038],{"class":441}," 'record.created'",[422,2040,445],{"class":428},[422,2042,2043,2046,2048,2050,2052,2055],{"class":424,"line":559},[422,2044,2045],{"class":441},"        'payload'",[422,2047,2020],{"class":507},[422,2049,2023],{"class":428},[422,2051,1654],{"class":507},[422,2053,2054],{"class":514},"toNotificationPayload",[422,2056,2057],{"class":428},"(),\n",[422,2059,2060,2063,2065,2068,2071,2073,2076,2079],{"class":424,"line":565},[422,2061,2062],{"class":441},"        'idempotency_key'",[422,2064,2020],{"class":507},[422,2066,2067],{"class":441}," \"record.created:{",[422,2069,2070],{"class":428},"$record",[422,2072,1654],{"class":507},[422,2074,2075],{"class":428},"id",[422,2077,2078],{"class":441},"}\"",[422,2080,445],{"class":428},[422,2082,2083],{"class":424,"line":576},[422,2084,2085],{"class":428},"    ]);\n",[422,2087,2088],{"class":424,"line":592},[422,2089,599],{"class":428},[11,2091,2092,2093,2096],{},"Bunun adı outbox kalıbı ve tek bir şeyi garanti ediyor: ",[15,2094,2095],{},"kayıt varsa bildirim niyeti de vardır."," Kaydın oluşup bildiriminin hiç kuyruğa girmemesi mümkün olmuyor.",[11,2098,2099],{},"Gönderim ise ayrı bir işçi tarafından, isteğin dışında yapılıyor. Kullanıcı dış servisin hızını beklemiyor; kullanıcıya \"işlem alındı\" demek için dış servisin cevabına ihtiyaç kalmıyor.",[86,2101,2103,2106],{"title":2102,"type":89},"Kuyruğa atmak yetmiyor, önce yazmak gerekiyor",[11,2104,2105],{},"Kaydı oluşturup bildirimi doğrudan kuyruk sistemine göndermek de yaygın bir çözüm. Ama transaction commit olmadan kuyruğa mesaj bırakırsan, işçi henüz var olmayan bir kaydı okumaya çalışabiliyor. Commit sonrasında bırakırsan da, tam o aralıkta çöken bir süreçte mesaj hiç bırakılmamış oluyor.",[11,2107,2108],{},"Outbox bu aralığı kapatıyor: mesaj da veri de aynı veritabanı işleminde. Kuyruk, outbox'ı okuyan bir tetikleyiciye dönüşüyor.",[23,2110,2112],{"id":2111},"yeniden-denemenin-sınırları-olmalı","Yeniden denemenin sınırları olmalı",[11,2114,2115],{},"Sonsuz yeniden deneme, çalışmayan bir entegrasyonu sonsuza kadar gizler. Üç şeyi belirlemek gerekiyor:",[11,2117,2118,2121],{},[15,2119,2120],{},"Aralık."," Sabit aralıkla denemek, servis toparlandığı anda ona toplu bir yük bindiriyor. Üstel artan bir bekleme ve üzerine rastgele bir sapma (jitter) daha iyi çalışıyor — bütün işçiler aynı saniyede uyanmıyor.",[413,2123,2125],{"className":1617,"code":2124,"language":1619,"meta":365,"style":365},"\u002F\u002F 1., 2., 3. deneme: ~1dk, ~4dk, ~9dk (üzerine rastgele sapma)\n$delay = ($attempt ** 2) * 60 + random_int(0, 30);\n",[419,2126,2127,2132],{"__ignoreMap":365},[422,2128,2129],{"class":424,"line":425},[422,2130,2131],{"class":1223},"\u002F\u002F 1., 2., 3. deneme: ~1dk, ~4dk, ~9dk (üzerine rastgele sapma)\n",[422,2133,2134,2137,2139,2142,2145,2148,2150,2152,2155,2158,2161,2163,2166,2168,2171],{"class":424,"line":366},[422,2135,2136],{"class":428},"$delay ",[422,2138,1629],{"class":507},[422,2140,2141],{"class":428}," ($attempt ",[422,2143,2144],{"class":507},"**",[422,2146,2147],{"class":434}," 2",[422,2149,1244],{"class":428},[422,2151,1241],{"class":507},[422,2153,2154],{"class":434}," 60",[422,2156,2157],{"class":507}," +",[422,2159,2160],{"class":514}," random_int",[422,2162,1238],{"class":428},[422,2164,2165],{"class":434},"0",[422,2167,812],{"class":428},[422,2169,2170],{"class":434},"30",[422,2172,1943],{"class":428},[11,2174,2175,2178,2179,2182],{},[15,2176,2177],{},"Üst sınır."," Belirli bir denemeden sonra kayıt ",[419,2180,2181],{},"failed"," olmalı. Bu bir kayıp değil, bir görünürlük kazancı: artık birinin bakması gereken bir liste var.",[11,2184,2185,2188],{},[15,2186,2187],{},"Kalıcı hata ayrımı."," Her hata yeniden denemeyi hak etmiyor:",[31,2190,2191,2203],{},[34,2192,2193,2196,2197,812,2200,18],{},[15,2194,2195],{},"Yeniden dene:"," zaman aşımı, bağlantı hatası, ",[419,2198,2199],{},"5xx",[419,2201,2202],{},"429",[34,2204,2205,2208,2209,2212,2213,2216,2217,2220,2221,2224],{},[15,2206,2207],{},"Deneme, hemen işaretle:"," ",[419,2210,2211],{},"400"," (geçersiz veri), ",[419,2214,2215],{},"401","\u002F",[419,2218,2219],{},"403"," (yetki), ",[419,2222,2223],{},"422"," (doğrulama).",[11,2226,2227],{},"Geçersiz veriyi kırk kez göndermek onu geçerli yapmıyor. Bu ayrımı yapmayan bir kuyruk, çözülemeyecek işlerle doluyor ve gerçekten geçici olan hatalar arada kayboluyor.",[23,2229,2231],{"id":2230},"mükerrer-gönderimi-engellemek","Mükerrer gönderimi engellemek",[11,2233,2234],{},"Zaman aşımı, en zor durumu üretiyor: isteği gönderdin, cevap gelmedi, ama karşı taraf işlemi almış olabilir. Yeniden denersen aynı işlem iki kez oluşabilir.",[11,2236,2237,2238,2241,2242,2245],{},"Çözüm iki taraflı. Kendi tarafında her bildirime kararlı bir anahtar veriyorsun — ",[419,2239,2240],{},"record.created:1042"," gibi, rastgele değil, aynı olay için hep aynı üretilen bir değer. Karşı taraf bu anahtarı destekliyorsa (çoğu modern API ",[419,2243,2244],{},"Idempotency-Key"," başlığıyla destekliyor) tekrar gönderim güvenli hâle geliyor.",[11,2247,2248],{},"Desteklemiyorsa, göndermeden önce sorgulamak gerekiyor: \"bu referansla bir kayıt var mı?\" Bu ekstra bir istek maliyeti getiriyor ama mükerrer kayıt üretmekten ucuz.",[11,2250,2251],{},"Bunun neden önemli olduğunu ödeme tarafında çalışırken daha net görüyorsun: aynı ödemenin iki kez işlenmesi sadece bir fazla satır değil, dönüşüm oranını da bozan bir hata. Rapor yanlış çıkıyor ve yanlış olduğunu fark etmek günler alıyor.",[23,2253,2255],{"id":2254},"takılan-kayıt-görünür-olmalı","Takılan kayıt görünür olmalı",[11,2257,2258],{},"Bir kuyruk, kimse bakmadığında sessizce dolan bir yere dönüşürse hiçbir şey çözmemiş olur. En az iki şey gerekiyor:",[31,2260,2261,2269],{},[34,2262,2263,2208,2266,2268],{},[15,2264,2265],{},"Operasyon ekranı.",[419,2267,2181],{}," durumundaki kayıtlar, hatasıyla birlikte listeleniyor ve elle yeniden denenebiliyor.",[34,2270,2271,2274],{},[15,2272,2273],{},"Eşik uyarısı."," Bekleyen kayıt sayısı ya da en eski bekleyen kaydın yaşı bir eşiği aştığında haber veren bir kontrol.",[11,2276,2277],{},"İkincisi olmadan, dış servisin üç gündür veri almadığını ancak karşı taraf arayınca öğreniyorsun.",[11,2279,2280,2281,2284],{},"İş sağlığı ve güvenliği süreçlerini kamu web servisleriyle entegre eden bir sistemde çalışırken şunu öğrendim: resmi bildirim yapan bir sistemde ",[15,2282,2283],{},"\"bildirildi\" bilgisi, kaydın bir alanı değil, kendi geçmişi olan ayrı bir durumdur."," Ne zaman denendiği ve neyle sonuçlandığı görülemiyorsa, bildirimin yapıldığını söylemek de mümkün olmuyor.",[23,2286,2288],{"id":2287},"özet","Özet",[11,2290,2291],{},"Dayanıklı bir entegrasyon şu dört şeyden oluşuyor:",[291,2293,2294,2297,2300,2303],{},[34,2295,2296],{},"Kayıt ve bildirim niyeti aynı transaction'da yazılıyor.",[34,2298,2299],{},"Gönderim isteğin dışında, ayrı bir işçide yapılıyor.",[34,2301,2302],{},"Yeniden deneme sınırlı, artan aralıklı ve kalıcı hatayı ayırt ediyor.",[34,2304,2305],{},"Başarısız kayıtlar sessizce birikmiyor, görünür oluyor.",[11,2307,2308,2309,2311],{},"Hiçbiri karmaşık değil. Zor olan, kesintiyi baştan ",[15,2310,1607],{}," olarak kabul etmek — sonradan eklenen bir yeniden deneme mantığı, en başından bu varsayımla kurulmuş bir akış kadar iyi çalışmıyor.",[86,2313,2314],{"title":359,"type":360},[11,2315,2316],{},"Buradaki şema ve kod parçaları kavramı anlatmak için yazılmış örneklerdir; belirli bir projenin üretim kodu değildir. Yeniden deneme aralıkları ve hata sınıflandırması, entegre olduğun servisin sözleşmesine göre değişir — kendi sağlayıcının dokümantasyonuyla doğrula.",[1079,2318,2319],{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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 pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":365,"searchDepth":366,"depth":367,"links":2321},[2322,2323,2324,2325,2326,2327,2328],{"id":1610,"depth":366,"text":1611},{"id":1720,"depth":366,"text":1721},{"id":1949,"depth":366,"text":1950},{"id":2111,"depth":366,"text":2112},{"id":2230,"depth":366,"text":2231},{"id":2254,"depth":366,"text":2255},{"id":2287,"depth":366,"text":2288},"Entegrasyon","\u002Fimages\u002Fblog\u002Fbildirim-kuyrugu.svg","2026-08-26","Kayıt bizde, bildirim dışarıda. Servis yanıt vermediğinde kaydın kaybolmaması için bildirim durumunu ayrı bir varlık olarak ele almak.",{},"\u002Fyazilar\u002Fdis-servis-bildirim-kuyrugu",{"title":1593,"description":2332},"yazilar\u002Fdis-servis-bildirim-kuyrugu",[2329,2338,2339],"API","Kuyruk","segofW3JQnh32q6phe1vl5JiQ_EHILsbskfUfftC548",{"id":2342,"title":2343,"body":2344,"category":378,"cover":2835,"date":2836,"demo":381,"description":2837,"draft":381,"extension":383,"featured":384,"meta":2838,"navigation":384,"path":2839,"readingTime":592,"seo":2840,"stem":2841,"tags":2842,"updated":2836,"__hash__":2845},"blog\u002Fyazilar\u002Fcoklu-veritabani-veri-izolasyonu.md","Çok Kiracılı Sistemlerde Veri İzolasyonu",{"type":8,"value":2345,"toc":2825},[2346,2352,2355,2359,2362,2372,2378,2384,2476,2482,2488,2491,2533,2540,2547,2551,2554,2574,2577,2581,2584,2591,2598,2607,2611,2614,2620,2681,2688,2694,2700,2706,2709,2713,2716,2772,2775,2779,2782,2814,2817,2822],[11,2347,2348,2349],{},"Aynı ürünü birden fazla kuruma verdiğin anda cevaplaman gereken bir soru çıkıyor: ",[15,2350,2351],{},"bu kurumların verisi nerede duracak?",[11,2353,2354],{},"Soru ilk bakışta bir veritabanı tercihi gibi görünüyor. Değil. Verdiğin cevap; performansı, yetkilendirmeyi, yedeklemeyi, silme taleplerini ve en çok da yeni sürüm çıkarma biçimini belirliyor. Yanlış tarafı seçmenin bedeli ilk gün değil, altıncı ayda ödeniyor.",[23,2356,2358],{"id":2357},"üç-yaklaşım","Üç yaklaşım",[11,2360,2361],{},"Pratikte üç seçenek var:",[11,2363,2364,2367,2368,2371],{},[15,2365,2366],{},"Ortak tablo."," Bütün kurumlar aynı tabloları paylaşıyor, her satırda bir ",[419,2369,2370],{},"tenant_id"," duruyor. Kurulumu en basit olan, işletmesi en ucuz olan yaklaşım.",[11,2373,2374,2377],{},[15,2375,2376],{},"Ayrı şema."," Aynı veritabanı sunucusu, kurum başına ayrı şema. Tablolar çoğalıyor ama veri sınırı netleşiyor.",[11,2379,2380,2383],{},[15,2381,2382],{},"Ayrı veritabanı."," Her kurumun kendi veritabanı var. Uygulama, isteğin hangi kuruma ait olduğunu belirleyip bağlantıyı ona göre seçiyor.",[108,2385,2386,2401],{},[111,2387,2388],{},[114,2389,2390,2392,2395,2398],{},[117,2391],{},[117,2393,2394],{},"Ortak tablo",[117,2396,2397],{},"Ayrı şema",[117,2399,2400],{},"Ayrı veritabanı",[124,2402,2403,2417,2428,2439,2452,2465],{},[114,2404,2405,2408,2411,2414],{},[129,2406,2407],{},"Kurulum maliyeti",[129,2409,2410],{},"Düşük",[129,2412,2413],{},"Orta",[129,2415,2416],{},"Yüksek",[114,2418,2419,2422,2424,2426],{},[129,2420,2421],{},"Sızma riski",[129,2423,2416],{},[129,2425,2413],{},[129,2427,2410],{},[114,2429,2430,2433,2435,2437],{},[129,2431,2432],{},"Gürültülü komşu etkisi",[129,2434,2416],{},[129,2436,2413],{},[129,2438,2410],{},[114,2440,2441,2444,2447,2449],{},[129,2442,2443],{},"Kiracı bazlı yedek\u002Fgeri yükleme",[129,2445,2446],{},"Zor",[129,2448,2413],{},[129,2450,2451],{},"Kolay",[114,2453,2454,2457,2460,2463],{},[129,2455,2456],{},"Şema değişikliği",[129,2458,2459],{},"Tek işlem",[129,2461,2462],{},"N işlem",[129,2464,2462],{},[114,2466,2467,2470,2472,2474],{},[129,2468,2469],{},"Kiracılar arası rapor",[129,2471,2451],{},[129,2473,2413],{},[129,2475,2446],{},[11,2477,2478,2479],{},"Tablodaki son iki satır kararın gerçek eksenini gösteriyor: ",[15,2480,2481],{},"izolasyon kazandıkça operasyon zorlaşıyor.",[23,2483,2485,2486],{"id":2484},"ortak-tablonun-asıl-riski-bir-where","Ortak tablonun asıl riski bir ",[419,2487,1255],{},[11,2489,2490],{},"Ortak tablo yaklaşımında veri sınırı fiziksel değil, mantıksal. Yani her sorgunun doğru filtreyi taşımasına bağlı:",[413,2492,2494],{"className":1214,"code":2493,"language":1216,"meta":365,"style":365},"SELECT * FROM appointments\nWHERE tenant_id = :tenant AND status = 'pending';\n",[419,2495,2496,2509],{"__ignoreMap":365},[422,2497,2498,2500,2503,2506],{"class":424,"line":425},[422,2499,1229],{"class":507},[422,2501,2502],{"class":507}," *",[422,2504,2505],{"class":507}," FROM",[422,2507,2508],{"class":428}," appointments\n",[422,2510,2511,2513,2516,2518,2521,2524,2527,2529,2531],{"class":424,"line":366},[422,2512,1255],{"class":507},[422,2514,2515],{"class":428}," tenant_id ",[422,2517,1629],{"class":507},[422,2519,2520],{"class":428}," :tenant ",[422,2522,2523],{"class":507},"AND",[422,2525,2526],{"class":507}," status",[422,2528,1344],{"class":507},[422,2530,1858],{"class":441},[422,2532,1453],{"class":428},[11,2534,2535,2536,2539],{},"Bu satır yüzlerce yerde tekrar ediyor ve ",[15,2537,2538],{},"bir kez unutulması yeterli",". Unutulduğunda hata da vermiyor: sorgu çalışıyor, sonuç dönüyor, sadece başka bir kurumun verisi de içinde geliyor.",[11,2541,2542,2543,2546],{},"Bu riski azaltmanın yolları var — global scope'lar, repository katmanı, satır düzeyi güvenlik. Hepsi işe yarıyor. Ama hepsinin ortak özelliği şu: ",[15,2544,2545],{},"doğru davranış, geliştiricinin bir şeyi hatırlamasına bağlı kalıyor."," Sağlık ya da finans verisi taşıyan bir üründe bu, tek başına ayrı veritabanını düşünmek için yeterli bir sebep.",[23,2548,2550],{"id":2549},"neden-ayrı-veritabanını-seçtim","Neden ayrı veritabanını seçtim",[11,2552,2553],{},"Muayenehaneler ve küçük tıp merkezleri için geliştirdiğim bilgi yönetim sisteminde kurum bazlı ayrı veritabanı kullandım. Üç gerekçesi vardı:",[31,2555,2556,2562,2568],{},[34,2557,2558,2561],{},[15,2559,2560],{},"Performans izolasyonu."," Büyük bir kurumun veri hacmi, küçük bir kurumun sorgularını yavaşlatmıyor. Ortak tabloda bir kiracının büyümesi herkesin sorun yaşaması demek.",[34,2563,2564,2567],{},[15,2565,2566],{},"Veri sınırı."," Kurum verisi bir filtreye değil, ayrı bir veritabanı sınırına dayanıyor. Yanlış yazılmış tek bir sorgu diğer kurumu göremiyor.",[34,2569,2570,2573],{},[15,2571,2572],{},"Yetki ayrımı."," Erişim veritabanı düzeyinde de kısıtlanabiliyor; uygulama katmanının doğru davranmasına ek bir kat daha ekleniyor.",[11,2575,2576],{},"Buna bir de şu eklendi: aynı altyapı farklı ülkelerdeki kuruluşlara hizmet verecekti. Verinin nerede durduğunu kurum kurum söyleyebilmek, sonradan eklenmesi çok zor bir özellik.",[23,2578,2580],{"id":2579},"bedeli-şema-değişikliği-artık-bir-dağıtım-problemi","Bedeli: şema değişikliği artık bir dağıtım problemi",[11,2582,2583],{},"Ayrı veritabanının maliyeti sorgularda değil. Sorgular neredeyse aynı kalıyor; sadece hangi bağlantıya gittikleri değişiyor.",[11,2585,2586,2587,2590],{},"Asıl mesele şu: ",[15,2588,2589],{},"tek bir migrasyon, N kez çalışan bir operasyona dönüşüyor."," Ve bu operasyon kısmen başarısız olabiliyor. Otuz kurumdan yirmi sekizinde çalışıp ikisinde hata veren bir migrasyon, sistemi tutarsız bir duruma bırakıyor.",[11,2592,2593,2594,2597],{},"Buradan çıkan sorun, bu mimarinin en sinsi tarafı: ",[15,2595,2596],{},"şema kayması."," Tek bir kurumda elle yapılmış bir düzeltme, orada kalıyor. Bir sonraki migrasyon o kurumda farklı bir başlangıç noktası buluyor ve zamanla birbirinden ayrışan kopyalar oluşuyor. Altı ay sonra \"bu kurumda neden çalışmıyor\" sorusunun cevabı, kodda değil o veritabanının geçmişinde saklı oluyor.",[86,2599,2601,2604],{"title":2600,"type":263},"Elle yapılan tek düzeltme, kalıcı bir ayrışmadır",[11,2602,2603],{},"Bir kurumda acil bir sorunu doğrudan veritabanında çözmek çok cazip. Sorun o an gerçekten çözülüyor. Ama o kurum artık diğerleriyle aynı şemaya sahip değil ve bunu kimse bilmiyor.",[11,2605,2606],{},"Kural basit: düzeltme migrasyon olarak yazılır, sonra hepsine uygulanır. Acil durumda elle müdahale ettiysen, aynı gün içinde onu migrasyona çevir.",[23,2608,2610],{"id":2609},"migrasyonu-izlenebilir-hâle-getirmek","Migrasyonu izlenebilir hâle getirmek",[11,2612,2613],{},"Ayrı veritabanı mimarisinde migrasyon çalıştırmak bir komut değil, bir süreç. Ele alınması gereken dört şey var:",[11,2615,2616,2619],{},[15,2617,2618],{},"Her kiracının kendi sürümünü bilmek."," Hangi migrasyonun nerede uygulandığı, tahmin edilecek değil sorgulanacak bir bilgi olmalı:",[413,2621,2623],{"className":1214,"code":2622,"language":1216,"meta":365,"style":365},"SELECT tenant_id, MAX(migration) AS son_surum, MAX(applied_at) AS son_tarih\nFROM tenant_migrations\nGROUP BY tenant_id\nORDER BY son_surum ASC;\n",[419,2624,2625,2654,2661,2668],{"__ignoreMap":365},[422,2626,2627,2629,2632,2635,2638,2641,2644,2646,2649,2651],{"class":424,"line":425},[422,2628,1229],{"class":507},[422,2630,2631],{"class":428}," tenant_id, ",[422,2633,2634],{"class":434},"MAX",[422,2636,2637],{"class":428},"(migration) ",[422,2639,2640],{"class":507},"AS",[422,2642,2643],{"class":428}," son_surum, ",[422,2645,2634],{"class":434},[422,2647,2648],{"class":428},"(applied_at) ",[422,2650,2640],{"class":507},[422,2652,2653],{"class":428}," son_tarih\n",[422,2655,2656,2658],{"class":424,"line":366},[422,2657,1247],{"class":507},[422,2659,2660],{"class":428}," tenant_migrations\n",[422,2662,2663,2665],{"class":424,"line":367},[422,2664,1280],{"class":507},[422,2666,2667],{"class":428}," tenant_id\n",[422,2669,2670,2673,2676,2679],{"class":424,"line":467},[422,2671,2672],{"class":507},"ORDER BY",[422,2674,2675],{"class":428}," son_surum ",[422,2677,2678],{"class":507},"ASC",[422,2680,1453],{"class":428},[11,2682,2683,2684,2687],{},"Bu sorgunun sonucunda birden fazla farklı ",[419,2685,2686],{},"son_surum"," görüyorsan, kayma başlamış demektir.",[11,2689,2690,2693],{},[15,2691,2692],{},"Sıralı ve tekrarlanabilir uygulama."," Migrasyonlar her kiracıda aynı sırayla çalışmalı ve ikinci kez çalıştırıldığında bozmamalı.",[11,2695,2696,2699],{},[15,2697,2698],{},"Başarısızlıkta durmak, devam etmemek."," Bir kiracıda hata alındığında kalanlara devam etmek, tutarsızlığı büyütüyor. Durup raporlamak daha iyi.",[11,2701,2702,2705],{},[15,2703,2704],{},"Sonuç raporu."," Kaç kiracıda çalıştı, hangilerinde çalışmadı, hata neydi. Bu rapor olmadan \"migrasyon tamam\" cümlesi bir varsayım.",[11,2707,2708],{},"Yeni kiracı açmak da aynı sürecin parçası. Yeni veritabanı, en güncel şemayla ve tüm migrasyon kayıtları işaretlenmiş hâlde oluşturulmalı — yoksa ilk günden farklı bir noktada başlıyor.",[23,2710,2712],{"id":2711},"bağlantı-seçimi-tek-bir-yerde-kalmalı","Bağlantı seçimi tek bir yerde kalmalı",[11,2714,2715],{},"Uygulama tarafında dikkat edilecek şey, bağlantı seçiminin dağılmaması. Hangi kurumun veritabanına bağlanılacağı isteğin başında bir kez belirlenmeli; sonrasındaki kod bunu bilmemeli.",[413,2717,2719],{"className":1617,"code":2718,"language":1619,"meta":365,"style":365},"\u002F\u002F İsteğin başında bir kez: bundan sonrası hangi kiracıda olduğunu bilmez.\n$tenant = $this->tenants->resolve($request);\n$this->connection->useDatabase($tenant->database);\n",[419,2720,2721,2726,2749],{"__ignoreMap":365},[422,2722,2723],{"class":424,"line":425},[422,2724,2725],{"class":1223},"\u002F\u002F İsteğin başında bir kez: bundan sonrası hangi kiracıda olduğunu bilmez.\n",[422,2727,2728,2731,2733,2736,2738,2741,2743,2746],{"class":424,"line":366},[422,2729,2730],{"class":428},"$tenant ",[422,2732,1629],{"class":507},[422,2734,2735],{"class":434}," $this",[422,2737,1654],{"class":507},[422,2739,2740],{"class":428},"tenants",[422,2742,1654],{"class":507},[422,2744,2745],{"class":514},"resolve",[422,2747,2748],{"class":428},"($request);\n",[422,2750,2751,2754,2756,2759,2761,2764,2767,2769],{"class":424,"line":367},[422,2752,2753],{"class":434},"$this",[422,2755,1654],{"class":507},[422,2757,2758],{"class":428},"connection",[422,2760,1654],{"class":507},[422,2762,2763],{"class":514},"useDatabase",[422,2765,2766],{"class":428},"($tenant",[422,2768,1654],{"class":507},[422,2770,2771],{"class":428},"database);\n",[11,2773,2774],{},"Bu ayrım korunmadığında, bağlantı seçimi servislere sızıyor ve test edilmesi zor bir yapı ortaya çıkıyor. Daha kötüsü, arka planda çalışan işlerde kiracı bağlamının hiç kurulmaması gibi hatalar mümkün hâle geliyor — kuyruk işçileri bir HTTP isteğinden gelmediği için bu bağlamı ayrıca taşımaları gerekiyor.",[23,2776,2778],{"id":2777},"ne-zaman-hangisi","Ne zaman hangisi",[11,2780,2781],{},"Karar verirken baktığım şey:",[31,2783,2784,2790,2796,2802,2808],{},[34,2785,2786,2789],{},[15,2787,2788],{},"Veri hassasiyeti yüksekse"," (sağlık, finans, kişisel veri) izolasyon tarafına yaslan.",[34,2791,2792,2795],{},[15,2793,2794],{},"Kiracı sayısı çok yüksek ve her biri küçükse"," ortak tablo daha yönetilebilir; binlerce veritabanına migrasyon çalıştırmak kendi başına bir problem.",[34,2797,2798,2801],{},[15,2799,2800],{},"Kiracı sayısı sınırlı ve her biri büyükse"," ayrı veritabanı hem performans hem sınır olarak kazandırıyor.",[34,2803,2804,2807],{},[15,2805,2806],{},"Kiracılar arası raporlama ürünün merkezindeyse"," ayrı veritabanı bunu pahalı hâle getiriyor; ayrı bir raporlama katmanı gerekiyor.",[34,2809,2810,2813],{},[15,2811,2812],{},"Kiracı bazlı yedek alma veya veri silme talebi bekliyorsan"," ayrı veritabanı bunu önemsiz bir işe indiriyor.",[11,2815,2816],{},"Son madde giderek daha belirleyici oluyor. \"Bu kurumun tüm verisini silin\" talebi, ortak tabloda dikkatli bir operasyon; ayrı veritabanında tek bir işlem.",[86,2818,2819],{"title":359,"type":360},[11,2820,2821],{},"Buradaki kod parçaları kavramı anlatmak için yazılmış örneklerdir; belirli bir projenin üretim kodu değildir. Kendi kurulumunda uygularken veritabanı sürümünün ve ORM'inin davranışını kendi ortamında doğrula.",[1079,2823,2824],{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}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 pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":365,"searchDepth":366,"depth":367,"links":2826},[2827,2828,2830,2831,2832,2833,2834],{"id":2357,"depth":366,"text":2358},{"id":2484,"depth":366,"text":2829},"Ortak tablonun asıl riski bir WHERE",{"id":2549,"depth":366,"text":2550},{"id":2579,"depth":366,"text":2580},{"id":2609,"depth":366,"text":2610},{"id":2711,"depth":366,"text":2712},{"id":2777,"depth":366,"text":2778},"\u002Fimages\u002Fblog\u002Fveri-izolasyonu.svg","2026-08-19","Ortak tablo mu, ayrı veritabanı mı? Kararın kolay kısmı sorgular; zor kısmı şema değişikliğinin her kiracıya tutarlı ulaşması.",{},"\u002Fyazilar\u002Fcoklu-veritabani-veri-izolasyonu",{"title":2343,"description":2837},"yazilar\u002Fcoklu-veritabani-veri-izolasyonu",[378,2843,2844],"Veritabanı","Çok Kiracılılık","ed9_AsUkRT_s2T7xgy2DRBBuNXvTRWDLS5Quan_vYmg",{"id":1105,"title":1106,"body":2847,"category":1580,"cover":1581,"date":1582,"demo":381,"description":1583,"draft":381,"extension":383,"featured":384,"meta":3186,"navigation":384,"path":1585,"readingTime":592,"seo":3187,"stem":1587,"tags":3188,"updated":1582,"__hash__":1590},{"type":8,"value":2848,"toc":3176},[2849,2853,2855,2857,2859,2873,2875,2879,2881,2885,2889,2893,2897,2899,2901,2905,2909,2913,2915,3103,3107,3109,3113,3115,3119,3121,3123,3125,3127,3129,3131,3136,3138,3142,3144,3146,3148,3160,3162,3164,3168,3170,3174],[11,2850,1111,2851,1115],{},[15,2852,1114],{},[11,2854,1118],{},[23,2856,1122],{"id":1121},[11,2858,1125],{},[31,2860,2861,2865,2869],{},[34,2862,2863,1133],{},[15,2864,1132],{},[34,2866,2867,1139],{},[15,2868,1138],{},[34,2870,2871,1145],{},[15,2872,1144],{},[11,2874,1148],{},[86,2876,2877],{"title":1151,"type":89},[11,2878,1154],{},[23,2880,1158],{"id":1157},[11,2882,2883,1164],{},[15,2884,1163],{},[11,2886,2887,1170],{},[15,2888,1169],{},[11,2890,2891,1176],{},[15,2892,1175],{},[11,2894,1179,2895,18],{},[15,2896,1182],{},[23,2898,1186],{"id":1185},[11,2900,1189],{},[11,2902,2903,1195],{},[15,2904,1194],{},[11,2906,2907,1201],{},[15,2908,1200],{},[11,2910,1204,2911,1208],{},[15,2912,1207],{},[11,2914,1211],{},[413,2916,2917],{"className":1214,"code":1215,"language":1216,"meta":365,"style":365},[419,2918,2919,2923,2941,2959,2965,2969,2973,2993,2999,3021,3047,3061,3091],{"__ignoreMap":365},[422,2920,2921],{"class":424,"line":425},[422,2922,1224],{"class":1223},[422,2924,2925,2927,2929,2931,2933,2935,2937,2939],{"class":424,"line":366},[422,2926,1229],{"class":507},[422,2928,1232],{"class":428},[422,2930,1235],{"class":434},[422,2932,1238],{"class":428},[422,2934,1241],{"class":507},[422,2936,1244],{"class":428},[422,2938,1247],{"class":507},[422,2940,1250],{"class":428},[422,2942,2943,2945,2947,2949,2951,2953,2955,2957],{"class":424,"line":367},[422,2944,1255],{"class":507},[422,2946,1258],{"class":428},[422,2948,1261],{"class":507},[422,2950,1264],{"class":441},[422,2952,1267],{"class":507},[422,2954,1258],{"class":428},[422,2956,1272],{"class":507},[422,2958,1275],{"class":441},[422,2960,2961,2963],{"class":424,"line":467},[422,2962,1280],{"class":507},[422,2964,1283],{"class":428},[422,2966,2967],{"class":424,"line":553},[422,2968,1288],{"emptyLinePlaceholder":384},[422,2970,2971],{"class":424,"line":559},[422,2972,1293],{"class":1223},[422,2974,2975,2977,2979,2981,2983,2985,2987,2989,2991],{"class":424,"line":565},[422,2976,1229],{"class":507},[422,2978,1300],{"class":434},[422,2980,18],{"class":428},[422,2982,1305],{"class":434},[422,2984,812],{"class":428},[422,2986,1235],{"class":434},[422,2988,1238],{"class":428},[422,2990,1241],{"class":507},[422,2992,1316],{"class":428},[422,2994,2995,2997],{"class":424,"line":576},[422,2996,1247],{"class":507},[422,2998,1323],{"class":428},[422,3000,3001,3003,3005,3007,3009,3011,3013,3015,3017,3019],{"class":424,"line":592},[422,3002,1328],{"class":507},[422,3004,1331],{"class":428},[422,3006,1334],{"class":507},[422,3008,1300],{"class":434},[422,3010,18],{"class":428},[422,3012,1341],{"class":434},[422,3014,1344],{"class":507},[422,3016,1347],{"class":434},[422,3018,18],{"class":428},[422,3020,1352],{"class":434},[422,3022,3023,3025,3027,3029,3031,3033,3035,3037,3039,3041,3043,3045],{"class":424,"line":387},[422,3024,1255],{"class":507},[422,3026,1347],{"class":434},[422,3028,18],{"class":428},[422,3030,1363],{"class":434},[422,3032,1366],{"class":507},[422,3034,1264],{"class":441},[422,3036,1267],{"class":507},[422,3038,1347],{"class":434},[422,3040,18],{"class":428},[422,3042,1363],{"class":434},[422,3044,1379],{"class":507},[422,3046,1275],{"class":441},[422,3048,3049,3051,3053,3055,3057,3059],{"class":424,"line":1384},[422,3050,1387],{"class":507},[422,3052,1300],{"class":434},[422,3054,18],{"class":428},[422,3056,1394],{"class":434},[422,3058,1397],{"class":507},[422,3060,1400],{"class":441},[422,3062,3063,3065,3067,3069,3071,3073,3075,3077,3079,3081,3083,3085,3087,3089],{"class":424,"line":1403},[422,3064,1387],{"class":507},[422,3066,1408],{"class":428},[422,3068,1411],{"class":434},[422,3070,18],{"class":428},[422,3072,1416],{"class":434},[422,3074,1419],{"class":507},[422,3076,1422],{"class":507},[422,3078,1425],{"class":507},[422,3080,1300],{"class":434},[422,3082,18],{"class":428},[422,3084,1416],{"class":434},[422,3086,1434],{"class":507},[422,3088,1437],{"class":441},[422,3090,1316],{"class":428},[422,3092,3093,3095,3097,3099,3101],{"class":424,"line":1442},[422,3094,1280],{"class":507},[422,3096,1300],{"class":434},[422,3098,18],{"class":428},[422,3100,1305],{"class":434},[422,3102,1453],{"class":428},[11,3104,1456,3105,1460],{},[15,3106,1459],{},[23,3108,1464],{"id":1463},[11,3110,1467,3111,1471],{},[15,3112,1470],{},[11,3114,1474],{},[11,3116,1477,3117,1481],{},[15,3118,1480],{},[11,3120,1484],{},[23,3122,1488],{"id":1487},[11,3124,1491],{},[11,3126,1494],{},[23,3128,1498],{"id":1497},[11,3130,1501],{},[413,3132,3134],{"className":3133,"code":1506,"language":1507,"meta":365},[1505],[419,3135,1506],{"__ignoreMap":365},[11,3137,1512],{},[11,3139,1515,3140,1519],{},[15,3141,1518],{},[11,3143,1522],{},[23,3145,1526],{"id":1525},[11,3147,1529],{},[31,3149,3150,3152,3154,3156,3158],{},[34,3151,1534],{},[34,3153,1537],{},[34,3155,1540],{},[34,3157,1543],{},[34,3159,1546],{},[11,3161,1549],{},[23,3163,350],{"id":349},[11,3165,1554,3166,1558],{},[15,3167,1557],{},[11,3169,1561],{},[86,3171,3172],{"title":359,"type":360},[11,3173,1566],{},[1079,3175,1569],{},{"title":365,"searchDepth":366,"depth":367,"links":3177},[3178,3179,3180,3181,3182,3183,3184,3185],{"id":1121,"depth":366,"text":1122},{"id":1157,"depth":366,"text":1158},{"id":1185,"depth":366,"text":1186},{"id":1463,"depth":366,"text":1464},{"id":1487,"depth":366,"text":1488},{"id":1497,"depth":366,"text":1498},{"id":1525,"depth":366,"text":1526},{"id":349,"depth":366,"text":350},{},{"title":1106,"description":1583},[1580,1589,378],[3190,3433,3939,4282,4827],{"id":5,"title":6,"body":3191,"category":378,"cover":379,"date":380,"demo":381,"description":382,"draft":381,"extension":383,"featured":384,"meta":3430,"navigation":384,"path":386,"readingTime":387,"seo":3431,"stem":389,"tags":3432,"updated":380,"__hash__":393},{"type":8,"value":3192,"toc":3419},[3193,3197,3199,3201,3203,3213,3215,3217,3219,3237,3239,3247,3249,3251,3293,3295,3297,3301,3303,3307,3309,3311,3333,3335,3353,3361,3363,3367,3369,3371,3389,3391,3393,3395,3407,3409,3411,3413,3415],[11,3194,13,3195,18],{},[15,3196,17],{},[11,3198,21],{},[23,3200,26],{"id":25},[11,3202,29],{},[31,3204,3205,3207,3209,3211],{},[34,3206,36],{},[34,3208,39],{},[34,3210,42],{},[34,3212,45],{},[11,3214,48],{},[23,3216,52],{"id":51},[11,3218,55],{},[31,3220,3221,3225,3229,3233],{},[34,3222,3223,63],{},[15,3224,62],{},[34,3226,3227,69],{},[15,3228,68],{},[34,3230,3231,75],{},[15,3232,74],{},[34,3234,3235,81],{},[15,3236,80],{},[11,3238,84],{},[86,3240,3241,3245],{"title":88,"type":89},[11,3242,92,3243,96],{},[15,3244,95],{},[11,3246,99],{},[23,3248,103],{"id":102},[11,3250,106],{},[108,3252,3253,3261],{},[111,3254,3255],{},[114,3256,3257,3259],{},[117,3258,119],{},[117,3260,122],{},[124,3262,3263,3269,3275,3281,3287],{},[114,3264,3265,3267],{},[129,3266,131],{},[129,3268,134],{},[114,3270,3271,3273],{},[129,3272,139],{},[129,3274,142],{},[114,3276,3277,3279],{},[129,3278,147],{},[129,3280,150],{},[114,3282,3283,3285],{},[129,3284,155],{},[129,3286,158],{},[114,3288,3289,3291],{},[129,3290,163],{},[129,3292,166],{},[11,3294,169],{},[23,3296,173],{"id":172},[11,3298,176,3299,180],{},[15,3300,179],{},[11,3302,183],{},[11,3304,186,3305,190],{},[15,3306,189],{},[23,3308,194],{"id":193},[11,3310,197],{},[31,3312,3313,3317,3321,3325,3329],{},[34,3314,3315,205],{},[15,3316,204],{},[34,3318,3319,211],{},[15,3320,210],{},[34,3322,3323,217],{},[15,3324,216],{},[34,3326,3327,223],{},[15,3328,222],{},[34,3330,3331,229],{},[15,3332,228],{},[23,3334,233],{"id":232},[31,3336,3337,3341,3345,3349],{},[34,3338,3339,241],{},[15,3340,240],{},[34,3342,3343,247],{},[15,3344,246],{},[34,3346,3347,253],{},[15,3348,252],{},[34,3350,3351,259],{},[15,3352,258],{},[86,3354,3355,3359],{"title":262,"type":263},[11,3356,266,3357,270],{},[15,3358,269],{},[11,3360,273],{},[23,3362,277],{"id":276},[11,3364,280,3365],{},[15,3366,283],{},[11,3368,286],{},[11,3370,289],{},[291,3372,3373,3377,3381,3385],{},[34,3374,3375,298],{},[15,3376,297],{},[34,3378,3379,304],{},[15,3380,303],{},[34,3382,3383,310],{},[15,3384,309],{},[34,3386,3387,316],{},[15,3388,315],{},[11,3390,319],{},[23,3392,323],{"id":322},[11,3394,326],{},[31,3396,3397,3399,3401,3403,3405],{},[34,3398,331],{},[34,3400,334],{},[34,3402,337],{},[34,3404,340],{},[34,3406,343],{},[11,3408,346],{},[23,3410,350],{"id":349},[11,3412,353],{},[11,3414,356],{},[86,3416,3417],{"title":359,"type":360},[11,3418,363],{},{"title":365,"searchDepth":366,"depth":367,"links":3420},[3421,3422,3423,3424,3425,3426,3427,3428,3429],{"id":25,"depth":366,"text":26},{"id":51,"depth":366,"text":52},{"id":102,"depth":366,"text":103},{"id":172,"depth":366,"text":173},{"id":193,"depth":366,"text":194},{"id":232,"depth":366,"text":233},{"id":276,"depth":366,"text":277},{"id":322,"depth":366,"text":323},{"id":349,"depth":366,"text":350},{},{"title":6,"description":382},[391,378,392],{"id":395,"title":396,"body":3434,"category":1092,"cover":1093,"date":1094,"demo":381,"description":1095,"draft":381,"extension":383,"featured":384,"meta":3936,"navigation":384,"path":1097,"readingTime":565,"seo":3937,"stem":1099,"tags":3938,"updated":380,"__hash__":1103},{"type":8,"value":3435,"toc":3926},[3436,3438,3440,3442,3444,3480,3490,3492,3494,3568,3578,3580,3582,3652,3656,3660,3664,3666,3668,3744,3748,3750,3754,3822,3832,3838,3840,3844,3846,3862,3868,3870,3872,3884,3890,3892,3894,3918,3920,3924],[11,3437,401],{},[11,3439,404],{},[23,3441,408],{"id":407},[11,3443,411],{},[413,3445,3446],{"className":415,"code":416,"language":417,"meta":365,"style":365},[419,3447,3448,3452,3462,3476],{"__ignoreMap":365},[422,3449,3450],{"class":424,"line":425},[422,3451,429],{"class":428},[422,3453,3454,3456,3458,3460],{"class":424,"line":366},[422,3455,435],{"class":434},[422,3457,438],{"class":428},[422,3459,442],{"class":441},[422,3461,445],{"class":428},[422,3463,3464,3466,3468,3470,3472,3474],{"class":424,"line":367},[422,3465,450],{"class":434},[422,3467,453],{"class":428},[422,3469,456],{"class":434},[422,3471,438],{"class":428},[422,3473,461],{"class":441},[422,3475,464],{"class":428},[422,3477,3478],{"class":424,"line":467},[422,3479,470],{"class":428},[11,3481,3482,476,3484,480,3486,484,3488,488],{},[419,3483,475],{},[419,3485,479],{},[419,3487,483],{},[419,3489,487],{},[23,3491,492],{"id":491},[11,3493,495],{},[413,3495,3496],{"className":498,"code":499,"language":500,"meta":365,"style":365},[419,3497,3498,3508,3512,3520,3532,3536,3540,3548,3560,3564],{"__ignoreMap":365},[422,3499,3500,3502,3504,3506],{"class":424,"line":425},[422,3501,508],{"class":507},[422,3503,511],{"class":507},[422,3505,515],{"class":514},[422,3507,518],{"class":428},[422,3509,3510],{"class":424,"line":366},[422,3511,523],{"class":428},[422,3513,3514,3516,3518],{"class":424,"line":367},[422,3515,528],{"class":428},[422,3517,531],{"class":441},[422,3519,534],{"class":428},[422,3521,3522,3524,3526,3528,3530],{"class":424,"line":467},[422,3523,539],{"class":428},[422,3525,542],{"class":441},[422,3527,545],{"class":428},[422,3529,548],{"class":441},[422,3531,534],{"class":428},[422,3533,3534],{"class":424,"line":553},[422,3535,556],{"class":428},[422,3537,3538],{"class":424,"line":559},[422,3539,562],{"class":428},[422,3541,3542,3544,3546],{"class":424,"line":565},[422,3543,568],{"class":428},[422,3545,571],{"class":441},[422,3547,445],{"class":428},[422,3549,3550,3552,3554,3556,3558],{"class":424,"line":576},[422,3551,579],{"class":428},[422,3553,582],{"class":434},[422,3555,585],{"class":428},[422,3557,582],{"class":434},[422,3559,534],{"class":428},[422,3561,3562],{"class":424,"line":592},[422,3563,556],{"class":428},[422,3565,3566],{"class":424,"line":387},[422,3567,599],{"class":428},[11,3569,3570,605,3572,609,3574,613,3576,617],{},[419,3571,604],{},[419,3573,608],{},[419,3575,612],{},[419,3577,616],{},[23,3579,621],{"id":620},[11,3581,624],{},[413,3583,3584],{"className":415,"code":627,"language":417,"meta":365,"style":365},[419,3585,3586,3590,3600,3610,3620,3626,3636,3644,3648],{"__ignoreMap":365},[422,3587,3588],{"class":424,"line":425},[422,3589,429],{"class":428},[422,3591,3592,3594,3596,3598],{"class":424,"line":366},[422,3593,638],{"class":434},[422,3595,438],{"class":428},[422,3597,643],{"class":441},[422,3599,445],{"class":428},[422,3601,3602,3604,3606,3608],{"class":424,"line":367},[422,3603,650],{"class":434},[422,3605,438],{"class":428},[422,3607,655],{"class":441},[422,3609,445],{"class":428},[422,3611,3612,3614,3616,3618],{"class":424,"line":467},[422,3613,662],{"class":434},[422,3615,665],{"class":428},[422,3617,668],{"class":441},[422,3619,671],{"class":428},[422,3621,3622,3624],{"class":424,"line":553},[422,3623,676],{"class":434},[422,3625,679],{"class":428},[422,3627,3628,3630,3632,3634],{"class":424,"line":559},[422,3629,684],{"class":434},[422,3631,438],{"class":428},[422,3633,689],{"class":441},[422,3635,445],{"class":428},[422,3637,3638,3640,3642],{"class":424,"line":565},[422,3639,696],{"class":434},[422,3641,438],{"class":428},[422,3643,701],{"class":441},[422,3645,3646],{"class":424,"line":576},[422,3647,706],{"class":428},[422,3649,3650],{"class":424,"line":592},[422,3651,470],{"class":428},[11,3653,713,3654,717],{},[419,3655,716],{},[11,3657,3658,723],{},[419,3659,722],{},[11,3661,726,3662,730],{},[419,3663,729],{},[23,3665,734],{"id":733},[11,3667,737],{},[413,3669,3670],{"className":498,"code":740,"language":500,"meta":365,"style":365},[419,3671,3672,3678,3688,3698,3708,3712,3718,3740],{"__ignoreMap":365},[422,3673,3674,3676],{"class":424,"line":425},[422,3675,747],{"class":514},[422,3677,679],{"class":428},[422,3679,3680,3682,3684,3686],{"class":424,"line":366},[422,3681,754],{"class":441},[422,3683,757],{"class":428},[422,3685,582],{"class":434},[422,3687,534],{"class":428},[422,3689,3690,3692,3694,3696],{"class":424,"line":367},[422,3691,766],{"class":441},[422,3693,757],{"class":428},[422,3695,582],{"class":434},[422,3697,534],{"class":428},[422,3699,3700,3702,3704,3706],{"class":424,"line":467},[422,3701,777],{"class":441},[422,3703,757],{"class":428},[422,3705,582],{"class":434},[422,3707,534],{"class":428},[422,3709,3710],{"class":424,"line":553},[422,3711,788],{"class":428},[422,3713,3714,3716],{"class":424,"line":559},[422,3715,793],{"class":514},[422,3717,679],{"class":428},[422,3719,3720,3722,3724,3726,3728,3730,3732,3734,3736,3738],{"class":424,"line":565},[422,3721,800],{"class":514},[422,3723,453],{"class":428},[422,3725,805],{"class":514},[422,3727,438],{"class":428},[422,3729,582],{"class":434},[422,3731,812],{"class":428},[422,3733,815],{"class":514},[422,3735,438],{"class":428},[422,3737,582],{"class":434},[422,3739,534],{"class":428},[422,3741,3742],{"class":424,"line":576},[422,3743,470],{"class":428},[11,3745,3746,831],{},[419,3747,830],{},[23,3749,835],{"id":834},[11,3751,838,3752,842],{},[419,3753,841],{},[413,3755,3756],{"className":498,"code":845,"language":500,"meta":365,"style":365},[419,3757,3758,3764,3774,3784,3794,3800,3814,3818],{"__ignoreMap":365},[422,3759,3760,3762],{"class":424,"line":425},[422,3761,852],{"class":514},[422,3763,679],{"class":428},[422,3765,3766,3768,3770,3772],{"class":424,"line":366},[422,3767,859],{"class":514},[422,3769,438],{"class":428},[422,3771,864],{"class":441},[422,3773,445],{"class":428},[422,3775,3776,3778,3780,3782],{"class":424,"line":367},[422,3777,871],{"class":514},[422,3779,438],{"class":428},[422,3781,864],{"class":441},[422,3783,445],{"class":428},[422,3785,3786,3788,3790,3792],{"class":424,"line":467},[422,3787,882],{"class":514},[422,3789,438],{"class":428},[422,3791,864],{"class":441},[422,3793,445],{"class":428},[422,3795,3796,3798],{"class":424,"line":553},[422,3797,893],{"class":514},[422,3799,679],{"class":428},[422,3801,3802,3804,3806,3808,3810,3812],{"class":424,"line":559},[422,3803,900],{"class":514},[422,3805,903],{"class":428},[422,3807,906],{"class":434},[422,3809,909],{"class":507},[422,3811,912],{"class":441},[422,3813,445],{"class":428},[422,3815,3816],{"class":424,"line":565},[422,3817,556],{"class":428},[422,3819,3820],{"class":424,"line":576},[422,3821,470],{"class":428},[11,3823,925,3824,812,3826,932,3828,936,3830,940],{},[419,3825,928],{},[419,3827,931],{},[419,3829,935],{},[419,3831,939],{},[11,3833,3834,945,3836,949],{},[419,3835,906],{},[419,3837,948],{},[23,3839,953],{"id":952},[11,3841,956,3842,959],{},[419,3843,716],{},[11,3845,962],{},[31,3847,3848,3850,3852,3854,3856,3860],{},[34,3849,967],{},[34,3851,970],{},[34,3853,973],{},[34,3855,976],{},[34,3857,3858,982],{},[419,3859,981],{},[34,3861,985],{},[11,3863,988,3864,992,3866,996],{},[419,3865,991],{},[15,3867,995],{},[23,3869,1000],{"id":999},[11,3871,1003],{},[413,3873,3874],{"className":1006,"code":1007,"language":1008,"meta":365,"style":365},[419,3875,3876,3880],{"__ignoreMap":365},[422,3877,3878],{"class":424,"line":425},[422,3879,1015],{},[422,3881,3882],{"class":424,"line":366},[422,3883,1020],{},[11,3885,1023,3886,1027,3888,1031],{},[419,3887,1026],{},[419,3889,1030],{},[23,3891,1035],{"id":1034},[11,3893,1038],{},[413,3895,3896],{"className":1006,"code":1041,"language":1008,"meta":365,"style":365},[419,3897,3898,3902,3906,3910,3914],{"__ignoreMap":365},[422,3899,3900],{"class":424,"line":425},[422,3901,1048],{},[422,3903,3904],{"class":424,"line":366},[422,3905,1053],{},[422,3907,3908],{"class":424,"line":367},[422,3909,1058],{},[422,3911,3912],{"class":424,"line":467},[422,3913,1063],{},[422,3915,3916],{"class":424,"line":553},[422,3917,1068],{},[11,3919,1071],{},[86,3921,3922],{"title":1074,"type":360},[11,3923,1077],{},[1079,3925,1081],{},{"title":365,"searchDepth":366,"depth":367,"links":3927},[3928,3929,3930,3931,3932,3933,3934,3935],{"id":407,"depth":366,"text":408},{"id":491,"depth":366,"text":492},{"id":620,"depth":366,"text":621},{"id":733,"depth":366,"text":734},{"id":834,"depth":366,"text":835},{"id":952,"depth":366,"text":953},{"id":999,"depth":366,"text":1000},{"id":1034,"depth":366,"text":1035},{},{"title":396,"description":1095},[1092,1101,1102],{"id":1105,"title":1106,"body":3940,"category":1580,"cover":1581,"date":1582,"demo":381,"description":1583,"draft":381,"extension":383,"featured":384,"meta":4279,"navigation":384,"path":1585,"readingTime":592,"seo":4280,"stem":1587,"tags":4281,"updated":1582,"__hash__":1590},{"type":8,"value":3941,"toc":4269},[3942,3946,3948,3950,3952,3966,3968,3972,3974,3978,3982,3986,3990,3992,3994,3998,4002,4006,4008,4196,4200,4202,4206,4208,4212,4214,4216,4218,4220,4222,4224,4229,4231,4235,4237,4239,4241,4253,4255,4257,4261,4263,4267],[11,3943,1111,3944,1115],{},[15,3945,1114],{},[11,3947,1118],{},[23,3949,1122],{"id":1121},[11,3951,1125],{},[31,3953,3954,3958,3962],{},[34,3955,3956,1133],{},[15,3957,1132],{},[34,3959,3960,1139],{},[15,3961,1138],{},[34,3963,3964,1145],{},[15,3965,1144],{},[11,3967,1148],{},[86,3969,3970],{"title":1151,"type":89},[11,3971,1154],{},[23,3973,1158],{"id":1157},[11,3975,3976,1164],{},[15,3977,1163],{},[11,3979,3980,1170],{},[15,3981,1169],{},[11,3983,3984,1176],{},[15,3985,1175],{},[11,3987,1179,3988,18],{},[15,3989,1182],{},[23,3991,1186],{"id":1185},[11,3993,1189],{},[11,3995,3996,1195],{},[15,3997,1194],{},[11,3999,4000,1201],{},[15,4001,1200],{},[11,4003,1204,4004,1208],{},[15,4005,1207],{},[11,4007,1211],{},[413,4009,4010],{"className":1214,"code":1215,"language":1216,"meta":365,"style":365},[419,4011,4012,4016,4034,4052,4058,4062,4066,4086,4092,4114,4140,4154,4184],{"__ignoreMap":365},[422,4013,4014],{"class":424,"line":425},[422,4015,1224],{"class":1223},[422,4017,4018,4020,4022,4024,4026,4028,4030,4032],{"class":424,"line":366},[422,4019,1229],{"class":507},[422,4021,1232],{"class":428},[422,4023,1235],{"class":434},[422,4025,1238],{"class":428},[422,4027,1241],{"class":507},[422,4029,1244],{"class":428},[422,4031,1247],{"class":507},[422,4033,1250],{"class":428},[422,4035,4036,4038,4040,4042,4044,4046,4048,4050],{"class":424,"line":367},[422,4037,1255],{"class":507},[422,4039,1258],{"class":428},[422,4041,1261],{"class":507},[422,4043,1264],{"class":441},[422,4045,1267],{"class":507},[422,4047,1258],{"class":428},[422,4049,1272],{"class":507},[422,4051,1275],{"class":441},[422,4053,4054,4056],{"class":424,"line":467},[422,4055,1280],{"class":507},[422,4057,1283],{"class":428},[422,4059,4060],{"class":424,"line":553},[422,4061,1288],{"emptyLinePlaceholder":384},[422,4063,4064],{"class":424,"line":559},[422,4065,1293],{"class":1223},[422,4067,4068,4070,4072,4074,4076,4078,4080,4082,4084],{"class":424,"line":565},[422,4069,1229],{"class":507},[422,4071,1300],{"class":434},[422,4073,18],{"class":428},[422,4075,1305],{"class":434},[422,4077,812],{"class":428},[422,4079,1235],{"class":434},[422,4081,1238],{"class":428},[422,4083,1241],{"class":507},[422,4085,1316],{"class":428},[422,4087,4088,4090],{"class":424,"line":576},[422,4089,1247],{"class":507},[422,4091,1323],{"class":428},[422,4093,4094,4096,4098,4100,4102,4104,4106,4108,4110,4112],{"class":424,"line":592},[422,4095,1328],{"class":507},[422,4097,1331],{"class":428},[422,4099,1334],{"class":507},[422,4101,1300],{"class":434},[422,4103,18],{"class":428},[422,4105,1341],{"class":434},[422,4107,1344],{"class":507},[422,4109,1347],{"class":434},[422,4111,18],{"class":428},[422,4113,1352],{"class":434},[422,4115,4116,4118,4120,4122,4124,4126,4128,4130,4132,4134,4136,4138],{"class":424,"line":387},[422,4117,1255],{"class":507},[422,4119,1347],{"class":434},[422,4121,18],{"class":428},[422,4123,1363],{"class":434},[422,4125,1366],{"class":507},[422,4127,1264],{"class":441},[422,4129,1267],{"class":507},[422,4131,1347],{"class":434},[422,4133,18],{"class":428},[422,4135,1363],{"class":434},[422,4137,1379],{"class":507},[422,4139,1275],{"class":441},[422,4141,4142,4144,4146,4148,4150,4152],{"class":424,"line":1384},[422,4143,1387],{"class":507},[422,4145,1300],{"class":434},[422,4147,18],{"class":428},[422,4149,1394],{"class":434},[422,4151,1397],{"class":507},[422,4153,1400],{"class":441},[422,4155,4156,4158,4160,4162,4164,4166,4168,4170,4172,4174,4176,4178,4180,4182],{"class":424,"line":1403},[422,4157,1387],{"class":507},[422,4159,1408],{"class":428},[422,4161,1411],{"class":434},[422,4163,18],{"class":428},[422,4165,1416],{"class":434},[422,4167,1419],{"class":507},[422,4169,1422],{"class":507},[422,4171,1425],{"class":507},[422,4173,1300],{"class":434},[422,4175,18],{"class":428},[422,4177,1416],{"class":434},[422,4179,1434],{"class":507},[422,4181,1437],{"class":441},[422,4183,1316],{"class":428},[422,4185,4186,4188,4190,4192,4194],{"class":424,"line":1442},[422,4187,1280],{"class":507},[422,4189,1300],{"class":434},[422,4191,18],{"class":428},[422,4193,1305],{"class":434},[422,4195,1453],{"class":428},[11,4197,1456,4198,1460],{},[15,4199,1459],{},[23,4201,1464],{"id":1463},[11,4203,1467,4204,1471],{},[15,4205,1470],{},[11,4207,1474],{},[11,4209,1477,4210,1481],{},[15,4211,1480],{},[11,4213,1484],{},[23,4215,1488],{"id":1487},[11,4217,1491],{},[11,4219,1494],{},[23,4221,1498],{"id":1497},[11,4223,1501],{},[413,4225,4227],{"className":4226,"code":1506,"language":1507,"meta":365},[1505],[419,4228,1506],{"__ignoreMap":365},[11,4230,1512],{},[11,4232,1515,4233,1519],{},[15,4234,1518],{},[11,4236,1522],{},[23,4238,1526],{"id":1525},[11,4240,1529],{},[31,4242,4243,4245,4247,4249,4251],{},[34,4244,1534],{},[34,4246,1537],{},[34,4248,1540],{},[34,4250,1543],{},[34,4252,1546],{},[11,4254,1549],{},[23,4256,350],{"id":349},[11,4258,1554,4259,1558],{},[15,4260,1557],{},[11,4262,1561],{},[86,4264,4265],{"title":359,"type":360},[11,4266,1566],{},[1079,4268,1569],{},{"title":365,"searchDepth":366,"depth":367,"links":4270},[4271,4272,4273,4274,4275,4276,4277,4278],{"id":1121,"depth":366,"text":1122},{"id":1157,"depth":366,"text":1158},{"id":1185,"depth":366,"text":1186},{"id":1463,"depth":366,"text":1464},{"id":1487,"depth":366,"text":1488},{"id":1497,"depth":366,"text":1498},{"id":1525,"depth":366,"text":1526},{"id":349,"depth":366,"text":350},{},{"title":1106,"description":1583},[1580,1589,378],{"id":1592,"title":1593,"body":4283,"category":2329,"cover":2330,"date":2331,"demo":381,"description":2332,"draft":381,"extension":383,"featured":384,"meta":4824,"navigation":384,"path":2334,"readingTime":592,"seo":4825,"stem":2336,"tags":4826,"updated":2331,"__hash__":2340},{"type":8,"value":4284,"toc":4815},[4285,4289,4293,4295,4297,4353,4355,4365,4369,4371,4375,4377,4545,4547,4549,4553,4661,4665,4667,4673,4675,4677,4681,4721,4727,4731,4753,4755,4757,4759,4765,4767,4769,4771,4773,4785,4787,4791,4793,4795,4805,4809,4813],[11,4286,1598,4287],{},[15,4288,1601],{},[11,4290,1604,4291,18],{},[15,4292,1607],{},[23,4294,1611],{"id":1610},[11,4296,1614],{},[413,4298,4299],{"className":1617,"code":1618,"language":1619,"meta":365,"style":365},[419,4300,4301,4315,4331],{"__ignoreMap":365},[422,4302,4303,4305,4307,4309,4311,4313],{"class":424,"line":425},[422,4304,1626],{"class":428},[422,4306,1629],{"class":507},[422,4308,1632],{"class":434},[422,4310,1635],{"class":507},[422,4312,1638],{"class":514},[422,4314,1641],{"class":428},[422,4316,4317,4319,4321,4323,4325,4327,4329],{"class":424,"line":366},[422,4318,1646],{"class":428},[422,4320,1629],{"class":507},[422,4322,1651],{"class":428},[422,4324,1654],{"class":507},[422,4326,1657],{"class":514},[422,4328,1660],{"class":428},[422,4330,1663],{"class":1223},[422,4332,4333,4335,4337,4339,4341,4343,4345,4347,4349,4351],{"class":424,"line":367},[422,4334,1668],{"class":507},[422,4336,1671],{"class":428},[422,4338,1654],{"class":507},[422,4340,1676],{"class":514},[422,4342,1679],{"class":428},[422,4344,1682],{"class":507},[422,4346,1685],{"class":441},[422,4348,1688],{"class":507},[422,4350,1691],{"class":441},[422,4352,1453],{"class":428},[11,4354,1696],{},[31,4356,4357,4359,4361,4363],{},[34,4358,1701],{},[34,4360,1704],{},[34,4362,1707],{},[34,4364,1710],{},[11,4366,1713,4367,1717],{},[15,4368,1716],{},[23,4370,1721],{"id":1720},[11,4372,1724,4373,1728],{},[419,4374,1727],{},[11,4376,1731],{},[413,4378,4379],{"className":1214,"code":1734,"language":1216,"meta":365,"style":365},[419,4380,4381,4391,4401,4411,4427,4437,4453,4479,4493,4503,4513,4523,4531,4541],{"__ignoreMap":365},[422,4382,4383,4385,4387,4389],{"class":424,"line":425},[422,4384,1741],{"class":507},[422,4386,1744],{"class":507},[422,4388,1747],{"class":514},[422,4390,1750],{"class":428},[422,4392,4393,4395,4397,4399],{"class":424,"line":366},[422,4394,1755],{"class":428},[422,4396,1758],{"class":507},[422,4398,1761],{"class":507},[422,4400,1764],{"class":428},[422,4402,4403,4405,4407,4409],{"class":424,"line":367},[422,4404,1769],{"class":428},[422,4406,1758],{"class":507},[422,4408,1774],{"class":507},[422,4410,445],{"class":428},[422,4412,4413,4415,4417,4419,4421,4423,4425],{"class":424,"line":467},[422,4414,1781],{"class":428},[422,4416,1784],{"class":507},[422,4418,1238],{"class":428},[422,4420,1789],{"class":434},[422,4422,1244],{"class":428},[422,4424,1794],{"class":507},[422,4426,445],{"class":428},[422,4428,4429,4431,4433,4435],{"class":424,"line":553},[422,4430,1801],{"class":428},[422,4432,1804],{"class":507},[422,4434,1774],{"class":507},[422,4436,445],{"class":428},[422,4438,4439,4441,4443,4445,4447,4449,4451],{"class":424,"line":559},[422,4440,1813],{"class":428},[422,4442,1784],{"class":507},[422,4444,1238],{"class":428},[422,4446,1820],{"class":434},[422,4448,1244],{"class":428},[422,4450,1794],{"class":507},[422,4452,445],{"class":428},[422,4454,4455,4457,4459,4461,4463,4465,4467,4469,4471,4473,4475,4477],{"class":424,"line":565},[422,4456,1831],{"class":507},[422,4458,1834],{"class":428},[422,4460,1837],{"class":441},[422,4462,1840],{"class":428},[422,4464,1843],{"class":441},[422,4466,1840],{"class":428},[422,4468,1848],{"class":441},[422,4470,1244],{"class":428},[422,4472,1794],{"class":507},[422,4474,1855],{"class":507},[422,4476,1858],{"class":441},[422,4478,445],{"class":428},[422,4480,4481,4483,4485,4487,4489,4491],{"class":424,"line":576},[422,4482,1865],{"class":428},[422,4484,1868],{"class":507},[422,4486,1774],{"class":507},[422,4488,1855],{"class":507},[422,4490,1875],{"class":434},[422,4492,445],{"class":428},[422,4494,4495,4497,4499,4501],{"class":424,"line":592},[422,4496,1882],{"class":428},[422,4498,1885],{"class":507},[422,4500,1422],{"class":507},[422,4502,445],{"class":428},[422,4504,4505,4507,4509,4511],{"class":424,"line":387},[422,4506,1894],{"class":428},[422,4508,1897],{"class":507},[422,4510,1422],{"class":507},[422,4512,445],{"class":428},[422,4514,4515,4517,4519,4521],{"class":424,"line":1384},[422,4516,1906],{"class":428},[422,4518,1885],{"class":507},[422,4520,1774],{"class":507},[422,4522,445],{"class":428},[422,4524,4525,4527,4529],{"class":424,"line":1403},[422,4526,1917],{"class":507},[422,4528,1920],{"class":507},[422,4530,1923],{"class":428},[422,4532,4533,4535,4537,4539],{"class":424,"line":1442},[422,4534,1928],{"class":507},[422,4536,1931],{"class":428},[422,4538,1934],{"class":507},[422,4540,1937],{"class":428},[422,4542,4543],{"class":424,"line":1940},[422,4544,1943],{"class":428},[11,4546,1946],{},[23,4548,1950],{"id":1949},[11,4550,1953,4551,1957],{},[15,4552,1956],{},[413,4554,4555],{"className":1617,"code":1960,"language":1619,"meta":365,"style":365},[419,4556,4557,4575,4589,4599,4611,4621,4635,4653,4657],{"__ignoreMap":365},[422,4558,4559,4561,4563,4565,4567,4569,4571,4573],{"class":424,"line":425},[422,4560,729],{"class":434},[422,4562,1635],{"class":507},[422,4564,1971],{"class":514},[422,4566,1238],{"class":428},[422,4568,1976],{"class":507},[422,4570,1979],{"class":428},[422,4572,1982],{"class":507},[422,4574,1985],{"class":428},[422,4576,4577,4579,4581,4583,4585,4587],{"class":424,"line":366},[422,4578,1990],{"class":428},[422,4580,1629],{"class":507},[422,4582,1632],{"class":434},[422,4584,1635],{"class":507},[422,4586,1638],{"class":514},[422,4588,1641],{"class":428},[422,4590,4591,4593,4595,4597],{"class":424,"line":367},[422,4592,2005],{"class":434},[422,4594,1635],{"class":507},[422,4596,1638],{"class":514},[422,4598,2012],{"class":428},[422,4600,4601,4603,4605,4607,4609],{"class":424,"line":467},[422,4602,2017],{"class":441},[422,4604,2020],{"class":507},[422,4606,2023],{"class":428},[422,4608,1654],{"class":507},[422,4610,2028],{"class":428},[422,4612,4613,4615,4617,4619],{"class":424,"line":553},[422,4614,2033],{"class":441},[422,4616,2020],{"class":507},[422,4618,2038],{"class":441},[422,4620,445],{"class":428},[422,4622,4623,4625,4627,4629,4631,4633],{"class":424,"line":559},[422,4624,2045],{"class":441},[422,4626,2020],{"class":507},[422,4628,2023],{"class":428},[422,4630,1654],{"class":507},[422,4632,2054],{"class":514},[422,4634,2057],{"class":428},[422,4636,4637,4639,4641,4643,4645,4647,4649,4651],{"class":424,"line":565},[422,4638,2062],{"class":441},[422,4640,2020],{"class":507},[422,4642,2067],{"class":441},[422,4644,2070],{"class":428},[422,4646,1654],{"class":507},[422,4648,2075],{"class":428},[422,4650,2078],{"class":441},[422,4652,445],{"class":428},[422,4654,4655],{"class":424,"line":576},[422,4656,2085],{"class":428},[422,4658,4659],{"class":424,"line":592},[422,4660,599],{"class":428},[11,4662,2092,4663,2096],{},[15,4664,2095],{},[11,4666,2099],{},[86,4668,4669,4671],{"title":2102,"type":89},[11,4670,2105],{},[11,4672,2108],{},[23,4674,2112],{"id":2111},[11,4676,2115],{},[11,4678,4679,2121],{},[15,4680,2120],{},[413,4682,4683],{"className":1617,"code":2124,"language":1619,"meta":365,"style":365},[419,4684,4685,4689],{"__ignoreMap":365},[422,4686,4687],{"class":424,"line":425},[422,4688,2131],{"class":1223},[422,4690,4691,4693,4695,4697,4699,4701,4703,4705,4707,4709,4711,4713,4715,4717,4719],{"class":424,"line":366},[422,4692,2136],{"class":428},[422,4694,1629],{"class":507},[422,4696,2141],{"class":428},[422,4698,2144],{"class":507},[422,4700,2147],{"class":434},[422,4702,1244],{"class":428},[422,4704,1241],{"class":507},[422,4706,2154],{"class":434},[422,4708,2157],{"class":507},[422,4710,2160],{"class":514},[422,4712,1238],{"class":428},[422,4714,2165],{"class":434},[422,4716,812],{"class":428},[422,4718,2170],{"class":434},[422,4720,1943],{"class":428},[11,4722,4723,2178,4725,2182],{},[15,4724,2177],{},[419,4726,2181],{},[11,4728,4729,2188],{},[15,4730,2187],{},[31,4732,4733,4741],{},[34,4734,4735,2196,4737,812,4739,18],{},[15,4736,2195],{},[419,4738,2199],{},[419,4740,2202],{},[34,4742,4743,2208,4745,2212,4747,2216,4749,2220,4751,2224],{},[15,4744,2207],{},[419,4746,2211],{},[419,4748,2215],{},[419,4750,2219],{},[419,4752,2223],{},[11,4754,2227],{},[23,4756,2231],{"id":2230},[11,4758,2234],{},[11,4760,2237,4761,2241,4763,2245],{},[419,4762,2240],{},[419,4764,2244],{},[11,4766,2248],{},[11,4768,2251],{},[23,4770,2255],{"id":2254},[11,4772,2258],{},[31,4774,4775,4781],{},[34,4776,4777,2208,4779,2268],{},[15,4778,2265],{},[419,4780,2181],{},[34,4782,4783,2274],{},[15,4784,2273],{},[11,4786,2277],{},[11,4788,2280,4789,2284],{},[15,4790,2283],{},[23,4792,2288],{"id":2287},[11,4794,2291],{},[291,4796,4797,4799,4801,4803],{},[34,4798,2296],{},[34,4800,2299],{},[34,4802,2302],{},[34,4804,2305],{},[11,4806,2308,4807,2311],{},[15,4808,1607],{},[86,4810,4811],{"title":359,"type":360},[11,4812,2316],{},[1079,4814,2319],{},{"title":365,"searchDepth":366,"depth":367,"links":4816},[4817,4818,4819,4820,4821,4822,4823],{"id":1610,"depth":366,"text":1611},{"id":1720,"depth":366,"text":1721},{"id":1949,"depth":366,"text":1950},{"id":2111,"depth":366,"text":2112},{"id":2230,"depth":366,"text":2231},{"id":2254,"depth":366,"text":2255},{"id":2287,"depth":366,"text":2288},{},{"title":1593,"description":2332},[2329,2338,2339],{"id":2342,"title":2343,"body":4828,"category":378,"cover":2835,"date":2836,"demo":381,"description":2837,"draft":381,"extension":383,"featured":384,"meta":5187,"navigation":384,"path":2839,"readingTime":592,"seo":5188,"stem":2841,"tags":5189,"updated":2836,"__hash__":2845},{"type":8,"value":4829,"toc":5178},[4830,4834,4836,4838,4840,4846,4850,4854,4930,4934,4938,4940,4974,4978,4982,4984,4986,5000,5002,5004,5006,5010,5014,5020,5022,5024,5028,5076,5080,5084,5088,5092,5094,5096,5098,5142,5144,5146,5148,5170,5172,5176],[11,4831,2348,4832],{},[15,4833,2351],{},[11,4835,2354],{},[23,4837,2358],{"id":2357},[11,4839,2361],{},[11,4841,4842,2367,4844,2371],{},[15,4843,2366],{},[419,4845,2370],{},[11,4847,4848,2377],{},[15,4849,2376],{},[11,4851,4852,2383],{},[15,4853,2382],{},[108,4855,4856,4868],{},[111,4857,4858],{},[114,4859,4860,4862,4864,4866],{},[117,4861],{},[117,4863,2394],{},[117,4865,2397],{},[117,4867,2400],{},[124,4869,4870,4880,4890,4900,4910,4920],{},[114,4871,4872,4874,4876,4878],{},[129,4873,2407],{},[129,4875,2410],{},[129,4877,2413],{},[129,4879,2416],{},[114,4881,4882,4884,4886,4888],{},[129,4883,2421],{},[129,4885,2416],{},[129,4887,2413],{},[129,4889,2410],{},[114,4891,4892,4894,4896,4898],{},[129,4893,2432],{},[129,4895,2416],{},[129,4897,2413],{},[129,4899,2410],{},[114,4901,4902,4904,4906,4908],{},[129,4903,2443],{},[129,4905,2446],{},[129,4907,2413],{},[129,4909,2451],{},[114,4911,4912,4914,4916,4918],{},[129,4913,2456],{},[129,4915,2459],{},[129,4917,2462],{},[129,4919,2462],{},[114,4921,4922,4924,4926,4928],{},[129,4923,2469],{},[129,4925,2451],{},[129,4927,2413],{},[129,4929,2446],{},[11,4931,2478,4932],{},[15,4933,2481],{},[23,4935,2485,4936],{"id":2484},[419,4937,1255],{},[11,4939,2490],{},[413,4941,4942],{"className":1214,"code":2493,"language":1216,"meta":365,"style":365},[419,4943,4944,4954],{"__ignoreMap":365},[422,4945,4946,4948,4950,4952],{"class":424,"line":425},[422,4947,1229],{"class":507},[422,4949,2502],{"class":507},[422,4951,2505],{"class":507},[422,4953,2508],{"class":428},[422,4955,4956,4958,4960,4962,4964,4966,4968,4970,4972],{"class":424,"line":366},[422,4957,1255],{"class":507},[422,4959,2515],{"class":428},[422,4961,1629],{"class":507},[422,4963,2520],{"class":428},[422,4965,2523],{"class":507},[422,4967,2526],{"class":507},[422,4969,1344],{"class":507},[422,4971,1858],{"class":441},[422,4973,1453],{"class":428},[11,4975,2535,4976,2539],{},[15,4977,2538],{},[11,4979,2542,4980,2546],{},[15,4981,2545],{},[23,4983,2550],{"id":2549},[11,4985,2553],{},[31,4987,4988,4992,4996],{},[34,4989,4990,2561],{},[15,4991,2560],{},[34,4993,4994,2567],{},[15,4995,2566],{},[34,4997,4998,2573],{},[15,4999,2572],{},[11,5001,2576],{},[23,5003,2580],{"id":2579},[11,5005,2583],{},[11,5007,2586,5008,2590],{},[15,5009,2589],{},[11,5011,2593,5012,2597],{},[15,5013,2596],{},[86,5015,5016,5018],{"title":2600,"type":263},[11,5017,2603],{},[11,5019,2606],{},[23,5021,2610],{"id":2609},[11,5023,2613],{},[11,5025,5026,2619],{},[15,5027,2618],{},[413,5029,5030],{"className":1214,"code":2622,"language":1216,"meta":365,"style":365},[419,5031,5032,5054,5060,5066],{"__ignoreMap":365},[422,5033,5034,5036,5038,5040,5042,5044,5046,5048,5050,5052],{"class":424,"line":425},[422,5035,1229],{"class":507},[422,5037,2631],{"class":428},[422,5039,2634],{"class":434},[422,5041,2637],{"class":428},[422,5043,2640],{"class":507},[422,5045,2643],{"class":428},[422,5047,2634],{"class":434},[422,5049,2648],{"class":428},[422,5051,2640],{"class":507},[422,5053,2653],{"class":428},[422,5055,5056,5058],{"class":424,"line":366},[422,5057,1247],{"class":507},[422,5059,2660],{"class":428},[422,5061,5062,5064],{"class":424,"line":367},[422,5063,1280],{"class":507},[422,5065,2667],{"class":428},[422,5067,5068,5070,5072,5074],{"class":424,"line":467},[422,5069,2672],{"class":507},[422,5071,2675],{"class":428},[422,5073,2678],{"class":507},[422,5075,1453],{"class":428},[11,5077,2683,5078,2687],{},[419,5079,2686],{},[11,5081,5082,2693],{},[15,5083,2692],{},[11,5085,5086,2699],{},[15,5087,2698],{},[11,5089,5090,2705],{},[15,5091,2704],{},[11,5093,2708],{},[23,5095,2712],{"id":2711},[11,5097,2715],{},[413,5099,5100],{"className":1617,"code":2718,"language":1619,"meta":365,"style":365},[419,5101,5102,5106,5124],{"__ignoreMap":365},[422,5103,5104],{"class":424,"line":425},[422,5105,2725],{"class":1223},[422,5107,5108,5110,5112,5114,5116,5118,5120,5122],{"class":424,"line":366},[422,5109,2730],{"class":428},[422,5111,1629],{"class":507},[422,5113,2735],{"class":434},[422,5115,1654],{"class":507},[422,5117,2740],{"class":428},[422,5119,1654],{"class":507},[422,5121,2745],{"class":514},[422,5123,2748],{"class":428},[422,5125,5126,5128,5130,5132,5134,5136,5138,5140],{"class":424,"line":367},[422,5127,2753],{"class":434},[422,5129,1654],{"class":507},[422,5131,2758],{"class":428},[422,5133,1654],{"class":507},[422,5135,2763],{"class":514},[422,5137,2766],{"class":428},[422,5139,1654],{"class":507},[422,5141,2771],{"class":428},[11,5143,2774],{},[23,5145,2778],{"id":2777},[11,5147,2781],{},[31,5149,5150,5154,5158,5162,5166],{},[34,5151,5152,2789],{},[15,5153,2788],{},[34,5155,5156,2795],{},[15,5157,2794],{},[34,5159,5160,2801],{},[15,5161,2800],{},[34,5163,5164,2807],{},[15,5165,2806],{},[34,5167,5168,2813],{},[15,5169,2812],{},[11,5171,2816],{},[86,5173,5174],{"title":359,"type":360},[11,5175,2821],{},[1079,5177,2824],{},{"title":365,"searchDepth":366,"depth":367,"links":5179},[5180,5181,5182,5183,5184,5185,5186],{"id":2357,"depth":366,"text":2358},{"id":2484,"depth":366,"text":2829},{"id":2549,"depth":366,"text":2550},{"id":2579,"depth":366,"text":2580},{"id":2609,"depth":366,"text":2610},{"id":2711,"depth":366,"text":2712},{"id":2777,"depth":366,"text":2778},{},{"title":2343,"description":2837},[378,2843,2844],1788979557491]