Büyük Çıkarma
Dün x-reporter’ı açtığımda beni 123 commitlenmemiş dosya karşıladı: ameliyat masasında, yarısı nakledilmiş bütün bir mimari. Bu, operasyonu tamamlayıp yedi temiz dikişle kapatma hikayesi.
Teşhis
x-reporter; X, Bluesky ve RSS akışlarından içerik topluyor, atıf yapılan makaleleri kazıyor ve bir LLM hattıyla yönetici özetleri üretiyor. v1 kod tabanı 2024 kurumsal varsayılanlarının müzesiydi:
- NestJS — tam dört endpoint’i olan bir servis için modüller, enjektörler, dekoratörler, bağımlılık tokenları
- Appwrite — özünde tek bir SQLite veritabanı olan şey için harici bir BaaS
- BullMQ + Redis — tek kullanıcının özetlerini işlemek için dağıtık iş kuyruğu
- LangGraph — sırayla çağrılan dört fonksiyonluk bir hat için graf çalışma zamanı
Hiçbiri yanlış değildi. Hepsi erken davranıştı. Yük taşıyan duvar aslında yük taşımıyordu; sadece görünüşünü sevmişiz.
ADR-001: Refactor Değil, Rewrite
Karar kaydı açık sözlü: saf Bun ile yeniden yaz. Yeni şekil:
// Bütün orkestrasyon katmanı bir LangGraph StateGraph'tı.
// Şimdi bu:
class DigestPipeline {
async run(input: RunDigestInput): Promise<RunDigestResult> {
let state = toInitialState(input);
state = await runClusterNode(state);
state = await runSummarizeNode(state);
state = await runRankNode(state);
return runComposeNode(state);
}
}
Dört düğüm, tipli durumlar, OpenRouter’ın OpenAI uyumlu endpoint’ine karşı yapılandırılmış JSON promptları. Graf çalışma zamanı yok. Çerçeve yok. Hattınız tek ekrana sığıyorsa DAG kütüphanesi sadece bir vergidir.
Değişimler, bire bir:
| Öldü | Yeniden Doğdu |
|---|---|
| Appwrite koleksiyonları | PocketBase repoları (UsersRepo, ItemsRepo, …) |
| BullMQ + Redis worker’lar | Interval tabanlı tek SchedulerService |
| NestJS controller’ları | Fonksiyon gibi bestelenen Hono route’ları |
| LangGraph DigestGraph | Saf TS cluster → summarize → rank → compose |
| Session guard’lar + Redis oturumları | HMAC imzalı çerezler + AES-256-GCM token şifreleme |
İçerik Alma Bir Port Oldu
Eski kodda tek kaynak vardı: özel bir processor tarafından poll edilen X API’si. Yeni IngestionSource portunun arkasında beş adaptör var — X API v2, ATProto üzerinden Bluesky, RSS/Atom, düz yer imleri ve API fiyatlandırması düşmanlaştığında için Apify Twitter scraper actor’ü. Scheduler elinde hangisi olduğunu bilmesine gerek yok; bir port’un bütün anlamı bu.
Split Commit Problemi
İşin eğlenceli kısmı burası. Rewrite bitmişti ama commitlenmemişti — silme ve ekleme birbirine dolanmış 123 dosya. Tek blob olarak commitlemek, gelecekteki git arkeologlarına söylenen yalan olurdu. Bu yüzden katman katman ayırdık; silmelerden önce eklemeler:
feat(pocketbase)— kalıcılık + koleksiyon bootstrap scriptifeat(ingestion)— dört kaynak adaptörüfeat(extraction)— yerel okunabilirlik çıkarıcı, Firecrawl yedeğifeat(digest)— saf TS hattı + OpenRouter sağlayıcısıfeat(app)— Hono uygulaması, route’lar, scheduler, authchore!— eski yığının toplu silinmesidocs— v2 için yeniden yazılan mimari, API, veri modeli
Her commit bir çığlık yerine bir cümle gibi okunuyor. Ve son ağaç tip kontrolünden geçip her testi geçiyor.
Rakamlar
Herkesin sorduğu fiş:
- 36 test, 0 başarısız, toplamda 230ms. Eski süitin Redis’in çalışmasını bekliyordu.
- Sıfır harici kuyruk bağımlılığı. Sıfır LangChain bağımlılığı. Sıfır dekoratör metadata reflektörü.
- 81 dosya, ~4.600 satır — testler, dokümanlar ve koleksiyon bootstrap scripti dahil.
Ders “çerçeveler kötü” değil. Kurduğunuz her bağımlılık, probleminizin onun şekline büyüyeceğine dair bir bahistir. Çoğu problem büyümez. Bizimki büyümedi. Dört async fonksiyon ve gömülü bir SQLite dosyası baştan yeterliydi — görmek için geri kalan her şeyi silmemiz gerekti.
Önce sil. Sonra geride kalanlara bak. Proje budur.