Nasıl çalışır
Bir parça C# kodu yazarsınız. Döndürdüğü şey birkaç saniye içinde HTTPS üzerinden, herkese açık bir adreste yayına girer. Aşağıda her şey, karşılaşacağınız sırayla anlatılıyor.
Lambda nedir?
Lambda, bir GenHTTP handler döndüren bir kod parçasıdır. Platform onu derler, yükler ve döndürdüğü şeyi kendi adresinizin altına bağlar. Proje yok, build dosyası yok, using satırı yok. Tüm GenHTTP modülleri zaten içe aktarılmış durumda.
return Content.From(Resource.FromString("hello"));
Bu, eksiksiz bir lambda. Yayına alındığında, anahtarından türetilen kendi adresinde, örneğin your-key.genhttp.run adresinde yanıt verir ve oradaki her istek “hello” kelimesini alır.
Kod parçası bir sınıf değildir, deyimlerden oluşur. Yaptığı son iş, istekleri karşılayabilen bir şey döndürmektir: bir handler ya da onu oluşturan bir builder.
İlk lambdanız
- 1Lambda oluştur düğmesine basın. Herkese açık bir adres ve bir editör anahtarı alırsınız. Anahtar, geri dönmenin tek yolu. Saklayın, çünkü kimse onu sizin için kurtaramaz.
- 2Ardından lambdanın kontrol paneline gelirsiniz. İlk sürüm olarak küçük bir REST servisi hazır bekler. Bu sadece bir başlangıç.
- 3Editör anahtarını bir ajana verin ve ne yapacağını söyleyin. Ajan MCP üzerinden yeni sürümler yazar. Ya da Kod bölümünü açıp kendiniz yazın: Kontrol et hiçbir şey kaydetmeden derler ve derleyicinin ne dediğini dosya ve satırıyla gösterir.
- 4Yayına al düğmesine basın. Artık yayında. Bundan önce hiçbir şeye erişilemez. Yeniden yayına almak da yayında kalma süresini uzatır.
Kontrol paneli
Editör linki bir metin kutusu değil, bir kontrol paneli açar. Buradaki kodun çoğunu ajanlar yazar, bu yüzden ekranda ilk gördüğünüz şey lambdanızın durumudur. Kenar çubuğunda lambdanın kendisi (yayında olup olmadığı, adresi ve daha yeni bir sürüm yayına alınmayı bekliyorsa bir düğme) ve bölümleri yer alır. Adresi değiştirmek ya da lambdayı silmek gibi nadiren yapılan işler, oradaki ⋯ menüsündedir.
- Genel bakış
- Uygulamanın ne olduğu, yayında olup olmadığı, bugün kaç istek aldığı ve kaçının başarısız olduğu, son değişiklik ve ne kadar yer kaldığı.
- Dokümantasyon
- Uygulamanın ne olduğu, kimin için ve neden var olduğu ve neden bu şekilde yapıldığı. Ajanlar yazar, her sürümle birlikte saklanır.
- Değiştir
- Neyin farklı olması gerektiğini yazın, gerisini bu sunucudaki ajan siz izlerken halleder. Değişikliği bir taslakta dener - kendi adresi olan bir kopya - ve çalışınca yayına alır. Taslağı önce kendiniz denemek isterseniz Bitince yayına al seçeneğini kapatın. Ajan yalnızca uygulamanız üzerinde çalışır: Uygulamayla ilgisi olmayan ya da zarar vermeye yönelik bir isteği reddeder ve nedenini söyler.
- Taslaklar
- Yayına alınmadan önce denenen değişiklikler: her biri kendi adresinde ve kendi test verileriyle çalışır. Açıldığında bir taslağın kendi kodu, test verileri ve logları vardır. Bu bölüm, bir taslak olduğunda görünür.
- Veriler
- Lambdanın çalışırken sakladıkları, tüm sürümler için ortak: veritabanı, çalışma alanı ve anahtarlar ve parolalar, her biri kendi sekmesinde. Tablolara ve dosyalara bakın, dosya yükleyin, anahtar ve parola girin ya da bir türü açıp kapatın. Basit görünüm, uygulama bir şey sakladığı anda bu bölümü gösterir.
- Sürümler
- Her sürümün neyi değiştirdiği, ne istendiği ve bir öncekinden farkı. Buradan yayına alabilir, eski bir sürüme dönebilir ya da herhangi bir sürümden bir taslak başlatabilirsiniz.
- Yayın geçmişi
- Ne zaman neyin yayında olduğu ve neden yayından kalktığı.
- İstatistikler
- Son bir saatin ya da günün istekleri, hataları, yanıt süreleri ve en çok istenen yolları.
- Loglar
- İstekler, lambdanın yazdırdıkları ve ters giden her şeyin stack trace’i, anında.
- Kod
- Bir sürümün her dosyası, yani kodu ve kaynakları, editörün yanında bir ağaçta - ne kadar yer tuttukları ve herkesin onlara erişip erişemediğiyle birlikte. Eski bir sürümü okumak için üstteki listeden onu seçin. Kontrol et derler, Kaydet bir sürüm oluşturur, Yayına al yayına alır. Bir taslakta ise Kaydet onu taslakta tutar ve taslağın adresinde gösterir.
Ctrl-Skaydeder,F12bir tanıma gider. - Testler
- Uygulamanın otomatik olarak nasıl test edildiği, bunun için gereken scriptler ve test verileriyle birlikte. Yalnızca tam görünümde.
Her bölüm aynı şekilde çalışır: başlığı, onu açıklayan bir ⓘ simgesi, sağda eylemleri ve birden fazla görünümü varsa altında bir sıra sekme. Tam görünüm bölümleri gruplar hâlinde toplar: insanların onu nasıl bulduğu, değişikliğin yapıldığı yer, sürümler ve veriler ve nasıl çalıştığı.
Trafik ve log bellekte tutulur. Saklamak için değil, izlemek içindir: sunucu yeniden başlarsa sıfırdan başlarlar. Sürümler ve yayın geçmişi ise kalıcı olarak saklanır.
Nedenini yazmak
Bir sürüm, kod ve isteğe bağlı iki nottan oluşur: spesifikasyon, yani kullanıcının ne istediği ve nedeni, mümkünse kendi sözleriyle; ve değişiklik, yani sürümün ne yaptığını anlatan tek bir satır. İkisi de sürüm geçmişinde diff’in yanında görünür. Böylece neden, ne ile yan yana kalır. Hem sizin için, hem de bir şeyi değiştirmeden önce geçmişi okuyan bir sonraki ajan için.
POST /api/v1/lambdas/{editorKey}/versions { "files": [ { "name": "lambda.cs", "code": "..." } ], "specification": "İnsanların imza atabileceği bir ziyaretçi defteri; kayıtlar yeniden başlatmada kaybolmamalı", "change": "Kayıtları veritabanında tutar, böylece yeniden başlatmada kaybolmazlar" }
Ajanlar da aynı iki alanı write_code aracına verir. Kod bölümünde kaydederken değişiklik sorulur. İkisi de isteğe bağlıdır. Uzun bir spesifikasyon reddedilmez, 4.000 karakterde kesilir; değişiklik ise 500 karakterde. Bir taslağın da kendi iki notu vardır; birleştirildiği sürüm bunları devralır.
Dokümantasyon ve testler
Her sürüm, kendisi hakkında yazılanları programının yanında saklar: dokümantasyonunu (uygulamanın ne olduğu, kimin için ve neden var olduğu, neden bu şekilde yapıldığı) ve testlerini: çalıştığının otomatik olarak nasıl kontrol edileceği, bunun için gereken scriptler ve test verileriyle birlikte. Ajanlar bunları yeni bir lambdayla birlikte yazar ve her değişiklikte günceller. Lambdayı değiştirecek bir sonraki ajan önce bunları okur; böylece uygulamanın ne için olduğunu ve neyin çalışmaya devam etmesi gerektiğini bilir. Kod tek başına bunu söylemez.
- docs/product.md
- uygulamanın ne olduğu, kimin için olduğu, insanların onunla ne yaptığı ve nedeni
- docs/decisions.md
- teknik kararlar ve neden alındıkları
- tests/README.md
- uygulamanın otomatik olarak nasıl test edildiği ve testlerin nasıl çalıştırılacağı
- tests/…
- testlerin kullandığı scriptler ve test verileri
Bunlar, kodunun diğer dosyaları gibi olan dosyalardır ve docs ile tests klasörlerinde durur: geçmiş, bir sürümün onlarda neyi değiştirdiğini gösterir; eski bir sürüme dönmek, o sürüm için geçerli olan dokümantasyonu geri getirir; bir taslağın da kendine ait, onunla birlikte yayına giren bir kopyası vardır. Asla derlenmez ve asla sunulmazlar; bir sürümün sahip olabileceği sınıra dahil edilirler.
Kontrol panelinde Dokümantasyon okunacak sayfaları, Testler ise uygulamanın nasıl test edildiğini ve yanındaki dosyaları gösterir; sürüm, dosyalarında olduğu gibi seçilir. Bir sayfa orada da düzenlenebilir; bu, bir sonraki sürümü kaydeder. Sade görünüm dokümantasyonu Hakkında olarak adlandırır ve yalnızca uygulamanın ne için olduğunu gösterir. Düzeltmek için ajana söyleyin.
Ajanla konuştuğunuz dilde, uygulamayı bir sonraki değiştirecek kişi için yazılırlar; bu bir insan da olabilir, bir ajan da. Kodun bir kopyası değildirler: uygulamanın ne için olduğunu ve nedenini anlatırlar.
Güvenle değiştirmek
Bir sürüm, kaydedildikten sonra bir daha değişmez. Her birini saklamaya değer kılan da bu: herhangi biriyle karşılaştırma yapılabilir, herhangi biri tam olduğu gibi yeniden yayına alınabilir. İnsanların kullandığı bir lambdayı değiştirmek için değişikliği önce bir taslak içinde deneyin.
- 1Sürümler altındaki herhangi bir sürümden başlatın ya da ajanın başlatmasına izin verin. Taslak, o sürümün kodunun ve kaynaklarının - dokümantasyonu ve testleri de dahil - bir de lambdanın verilerinin kopyasıdır.
- 2Gerektiği kadar değiştirin: Kod bölümünde ya da ajandan isteyerek. Taslağın önizlemesi kendi adresinde,
/features/…/altında, kendine ait test verileriyle yanıt verir. Lambdanın ziyaretçileri bunların hiçbirini görmez; taslağın yazdığı hiçbir şey lambdanın verilerine ulaşmaz. - 3Hazır olunca Yayına al düğmesine basın: notlarıyla birlikte bir sonraki sürüm olur ve yayına girer. Taslak ise önizlemesi ve test verileriyle birlikte kaldırılır.
POST /api/v1/lambdas/{editorKey}/features { "name": "Skor tablosu" } PUT /api/v1/lambdas/{editorKey}/features/{feature}/files?deploy=true POST /api/v1/lambdas/{editorKey}/features/{feature}/merge { "deploy": true }
Aynı anda birden fazla taslak üzerinde çalışılabilir. Yalnızca en yeni sürümle güncel olan bir taslak yayına alınabilir; böylece taslak başladıktan sonra kaydedilen bir sürüm asla geri alınmaz. Önce başka bir taslak yayına alındıysa onun değişikliklerini taslağa taşıyın (ya da ajandan isteyin), sonra taslağı güncel olarak işaretleyin. Hiçbir şey kendiliğinden yayına girmez; bu bilinçli bir tercih. API bir taslağa feature, onu yayına almaya merge der.
Kod ve kaynaklar
Bir sürüm, iki bölüme ayrılmış istediğiniz sayıda dosyadır. Kodu, kaynakları dışındaki her dosyadır:.cs dosyaları, her C# projesinde olduğu gibi hangi klasörde olursa olsun derlenir; diğer her dosya sürümle birlikte saklanır ve asla derlenmez ya da sunulmaz: dokümantasyonu, testleri, bir ön yüzün neyden derlendiği. Kaynakları, yani resources/ içindekiler, sürümün çalışırken okuyup sunduğu şeylerdir - sayfalar, scriptler, stiller, görseller, veritabanının migration’ları - ve koddan Resources olarak erişilir.
lambda.cs the snippet: what it returns is served Shelf.cs more C#, compiled beside it models/Book.cs C# in a folder, compiled the same docs/ tests/ what is written about it frontend/ whatever else - kept, never compiled or served resources/ what it reads and serves while it runs
Türlerin, onları kullanan kodun altında durması gerekmez. Kod bölümünde kodun yanındaki +düğmesine basın ve bir ad yazın: bir .cs dosyası, hangi klasörde olursa olsun, kod parçasıyla aynı namespace içinde onunla birlikte derlenir. Böylece erişmek için hiçbir şeyi içe aktarmanız gerekmez. Uzantısı ve klasörü olmayan bir ad C# dosyası sayılır.
var shelf = new Shelf(); return Inline.Create() .Get(() => shelf.All()) .Post((Book book) => shelf.Add(book));
public sealed class Shelf { private readonly List<Book> _books = []; public IEnumerable<Book> All() => _books; public Book Add(Book book) { _books.Add(book); return book; } } public record Book(string Title, string Author);
Kodun nasıl düzenleneceği onu yazana kalmıştır - türler için bir klasör, bir ön yüzün kaynakları için bir klasör, scriptler için bir klasör. Her .cs dosyası uygulamaya derlenir; bu yüzden uygulamanın parçası olmayan C# - bir test, kendi başına bir araç - kodda .cs dosyası olarak yer almaz. Bir sürümün kodu ve kaynakları, genel bakışta görünen tek bir yer payını paylaşır.
Sayfa sunmak
Sayfa sunmanın iki yolu var. İnsanların yanına yüklediği dosyalar için de bir üçüncüsü.
Tek sayfa, kodun içinde
Küçük şeyler için yeterli. Sayfa doğrudan kodun içinde yer alır.
var page = Resource.FromString(""" <!doctype html> <title>Mine</title> <h1>It works</h1> """) .Type(new ContentType("text/html; charset=utf-8")); return Content.From(page);
Gerçek dosyalarla bir klasör
Stil dosyası ve script içeren her şey için doğru seçim. Dosyalar sürümün kaynaklarıdır ve tam yazıldığı gibi sunulur. Derlenmezler.
return Layout.Create() .Add("api", api) .Add(Resources.App("site"));
Yüklenen dosyalar, verilerden
İnsanların yüklediği ya da lambdanın oluşturduğu şeyler (görseller, belgeler) için; uygulamanın yanında sunulurlar. Uygulamanın kendi sayfaları için değil: onların yeri kaynaklardır, orada onlara ihtiyaç duyan kodla birlikte sürümlenirler.
return Layout.Create() .Add("api", api) .Add("uploads", Workspace.Files("uploads")) .Add(Resources.App("site"));
Adım adım bir frontend
Bunların ikincisi, baştan sona. Her demo, sayfasını bu şekilde resources/web içinden sunar. Bir örnek görmek için demo-crud demosunu açın. Demolar salt okunurdur; editör anahtarları adlarıyla aynıdır.
- 1Kod bölümünde kaynakların yanındaki + düğmesine basın ve
site/index.htmlyazın: dosyaresources/site/index.htmlolur. Adında eğik çizgi olan bir dosya bir klasöre girer. Uzantısı olan bir ad da uzantısının söylediği türde dosya sayılır. - 2
site/app.cssvesite/app.jsdosyalarını da aynı şekilde ekleyin. Sayfanız onlarahref="app.css"örneğindeki gibi adlarıyla başvurur. Çünkü klasör adresin bir parçası değil, sunulan içeriğin köküdür. - 3Görsel ya da font gibi metin olmayan dosyalar için
siteklasöründeki bir dosyayı açın ve kaynakların yanındaki yükleme düğmesine basın. Dosya aynı klasöre gider. PNG bir metin editöründe yazılamaz, o yüzden yolu bu. - 4
lambda.csdosyasında klasörü sunun:return Layout.Create().Add(Resources.App("site"));
- 5Yayına al düğmesine basın.
site/index.htmldosyası/adresinde,site/app.cssdosyası/app.cssadresinde yanıt verir. Hiçbir dosyayla eşleşmeyen her adreste sayfanın kendisi döner. Böylece kendi yönlendirmesini yapan bir frontend, biri bir deep link üzerinde sayfayı yenilediğinde de çalışır. - 6Yanına bir API ekleyin, sayfanın konuşacağı bir şey olsun:
var api = Inline.Create().Get("notes", () => notes); return Layout.Create() .Add("api", api) .Add(Resources.App("site"));
Neyden derlendiği
Bir lambda’nın bir kısmı, sunulduğu ya da derlendiği şekliyle yazılmak yerine bir derleme aracıyla - derlenerek, paketlenerek ya da üretilerek - oluşturulabilir. Sürüm, aracın ürettiği şeyi - kaynakları ya da kodu olarak - tutar; onları ürettiği dosyalar ise kodunun parçasıdır ve kendi klasöründe durur, örneğin frontend/, nasıl derlendiğini anlatan bir README ile. Ajanınız bu dosyaları değiştirir, derlemeyi çalıştığı yerde yapar ve ikisini de aynı sürümde kaydeder. Bu platform hiçbir şey derlemez.
frontend/ what it is built from, in whatever shape the tool wants frontend/README.md how it is built, and where the build goes frontend/.gitignore what the build installs or keeps for itself, left out resources/web/ what the build wrote, if it makes resources *.cs what it wrote, if it makes code # run the build where you work, then git add -A && git commit -m "…" && git push -o deploy
Dokümantasyon gibi onlar da sürüme aittir: geçmişte karşılaştırılır, geri alınır, bir taslağa kopyalanır, klonlanır, indirilir ve kodun geri kalanıyla birlikte yayımlanır - ve asla derlenmez ya da sunulmaz. Kontrol panelinde sürümün diğer tüm dosyalarıyla birlikte Kod içindedirler.
Sunulduğu ya da derlendiği şekliyle yazılan şeylerin buna ihtiyacı yoktur. Bir derlemenin kendisi için kurduğu ya da sakladığı şeyler - örneğin node_modules - asla bir sürümün parçası olmaz: klasöründeki bir .gitignore onları dışarıda tutar.
Bir sürüm ve verileri
Bir lambda dosyaları iki yerde tutar ve editör onları ayrı gösterir: Kod bir sürümün dosyalarını (programı), Veriler ise çalışma alanını (programın sakladıklarını) tutar. Fark, kime ait olduklarında yatar. Bir sürümün dosyaları o sürüme aittir; veriler ise lambdaya aittir ve her sürüm onları paylaşır. Her birinin tek bir yer payı vardır: bir sürümün kodu ve kaynakları birini paylaşır, lambdanın veritabanı ve çalışma alanı da diğerini.
| Bir sürümde | Verilerde | |
|---|---|---|
| ne tutar | kod ve kaynaklar: frontend dahil programın kendisi, bir de dokümantasyonu, testleri ve neyden derlendiği | lambdanın yazdığı ya da birinin yüklediği her şey |
| ne zaman değişir | hiçbir zaman: her değişiklik yeni bir sürümdür | içine bir şey yazıldığı anda |
| yayına alma | tam olarak bu dosyaları yayına alır | ona hiç dokunmaz |
| eski bir sürüme dönmek | eski dosyaları geri getirir | etkisi yok: her sürüm onu paylaşır |
| bir taslak | onların bir kopyasıyla başlar | onun bir kopyası üzerinde çalışır |
| ne zaman silinir | sınır aşılınca, eski sürümlerle birlikte | lambdayla birlikte ya da siz kapattığınızda |
| koddan erişim | Resources | Workspace |
İkisi tek bir yer olamaz. Olsaydı, her yayına alma ya lambdanızın o zamandan beri yazdığı her şeyi silerdi ya da yayına aldığınız dosyalardan hiçbir şey kaldırılamazdı. Skor tablosu tutan bir oyun ikincisini ister, sunduğu sayfa ise birincisini. Bu yüzden sayfa sürüme, skor tablosu da verilere girer.
Kayıt tutmak
Kayıtlar (girdiler, hesaplar, siparişler, oylar) veritabanına aittir: lambdanın kendine ait, Veriler altında açılan bir SQLite veritabanı. Kod Database.GetConnection() ile bir bağlantı açar ve tabloları eşleyen kendi bağlamıyla veritabanını Entity Framework Core üzerinden okuyup yazar:
// resources/migrations/V1__Create_notes.sql: // CREATE TABLE notes (id INTEGER PRIMARY KEY, text TEXT NOT NULL); using (var connection = Database.GetConnection()) { new Evolve(connection) { Locations = [Resources.Root + "migrations"] }.Migrate(); } return Inline.Create() .Get("notes", () => { using var db = new Notes(Database.GetConnection()); return db.Entries.OrderBy(n => n.Id).Select(n => n.Text).ToList(); }) .Post("notes", (NoteInput input) => { using var db = new Notes(Database.GetConnection()); db.Entries.Add(new Note { Text = input.Text }); return db.SaveChanges(); }); record NoteInput(string Text); class Note { public long Id { get; set; } public string Text { get; set; } } // maps the table the migration made, on the connection it is handed class Notes(SqliteConnection connection) : DbContext { public DbSet<Note> Entries => Set<Note>(); protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite(connection, contextOwnsConnection: true); protected override void OnModelCreating(ModelBuilder model) => model.Entity<Note>().ToTable("notes"); }
Tablolarını migration’lar oluşturur: sürümle birlikte resources/migrations/ içinde gelen ve lambda başlarken Evolve tarafından sırayla uygulanan SQL dosyaları. Her biri yalnızca bir kez uygulanır, yani yeni bir sürüm yalnızca yeni olanı çalıştırır. Uygulanmış bir migration’ı asla değiştirmeyin; bir tablodaki değişiklik bir sonraki dosyadır.
Tüm veriler gibi veritabanı da tüm sürümler için ortaktır; yayına alma ve eski bir sürüme dönme ona dokunmaz, bir taslak ise onun bir kopyası üzerinde çalışır. Veriler altında tablolarını ve içlerindekileri görürsünüz; basit görünüm bunlara kayıt der. .NET projesi olarak indir onu düz bir SQLite dosyası olarak birlikte getirir.
Bağlamı ihtiyaç duyduğunuz yerde oluşturun, işiniz bitince serbest bırakın ve senkron kullanın: ToListAsync ve SaveChangesAsync değil, ToList ve SaveChanges. Tabloları migration’lar oluşturur, asla Entity Framework değil. demo-crud demosu bunların hepsini yapar.
Dosya saklamak
Workspace, lambdanızın okuyup yazabildiği özel bir klasördür ve dosyaların yeridir: birinin yüklediği görseller, lambdanın oluşturduğu bir belge, okuduğu bir model. Kayıtlar veritabanına aittir; bir dosya hakkında bilinenler (kimin ve ne zaman yüklediği) de bir kayıttır.
// uploads go into a folder of their own, served as they are Workspace.CreateFolder("photos"); return Layout.Create() .Add("photos", Workspace.Files("photos")) .Add("upload", Inline.Create().Post(async (Stream body) => { using var content = new MemoryStream(); await body.CopyToAsync(content); Workspace.WriteBytes($"photos/{Guid.NewGuid():N}.jpg", content.ToArray()); }));
Ayrıca ReadBytes, WriteBytes, Delete, List, CreateFolder ve içeriği sunmak için Tree/Files/App da var. Dosya sisteminin geri kalanına erişilemez.
Anahtarlar ve parolalar
Bir API anahtarı, parola veya token koda değil gizli değerlere aittir; kodda her sürüm, her indirme ve geçmişi okuyan herkes ona sahip olurdu. Kod bir gizli değeri adıyla okur:
var weather = new System.Net.Http.HttpClient(); weather.DefaultRequestHeaders.Add("X-Api-Key", Secret.Read("WEATHER_API_KEY")); return Inline.Create() .Get("today", async () => await weather.GetStringAsync("https://weather.example/today"));
Gizli değerleri Veriler altında açın ve değeri orada ayarlayın. Kaydedildikten sonra bir daha gösterilmez – ne size ne de bir ajana; yalnızca değiştirebilirsiniz. Liste, kodun okuduğu ama henüz değeri olmayan adları gösterir, genel bakış da bunları ister. Secret.Exists bir değerin ayarlı olup olmadığını söyler; onsuz da çalışan kod için. Tüm veriler gibi gizli değerler de tüm sürümler için ortaktır ve bir taslak bir kopya üzerinde çalışır.
Veritabanında bulunmayan bir anahtarla şifrelenmiş olarak saklanırlar. İndirilen bir projede Secret.Read("NAME") NAME ortam değişkenini okur – değerlerin kendisi burada kalır.
Websocket’ler
Destekleniyor, hem de sonradan akla gelmiş bir özellik olarak değil. demo-game demosu oyuncuları eşleştirir ve her oyunu sunucuda yürütür. En basit hâli üç callback’ten oluşur:
var room = new ConcurrentDictionary<IReactiveConnection, string>(); var socket = Websocket.Functional() .OnOpen(c => { room[c] = "someone"; return ValueTask.CompletedTask; }) .OnMessage(async (c, text) => { foreach (var other in room.Keys) { await other.WritePayloadAsync(text); } }) .OnClose((c, _) => { room.TryRemove(c, out _); return ValueTask.CompletedTask; }); return Layout.Create().Add("chat", socket);
Sayfa yalnızca dinliyorsa (bir sayaç, bir akış, bir skor tablosu) sunucu tarafından gönderilen olaylar daha basittir: sunucunun yazmaya devam ettiği ve tarayıcının kendiliğinden yeniden bağlandığı tek bir uzun yanıt. demo-live demosu her oyu bu yolla o sırada izleyen herkese gönderir. Hangisini seçerseniz seçin, değişeni sunucu iletir. Birkaç saniyede bir yeniden soran bir sayfa, bir şey değişmiş olsun olmasın her seferinde bir istek gönderir ve yine de geç kalır.
Herkesin takıldığı bir nokta var: tarayıcı, websocket el sıkışmasında header ekleyemez. Handler’ın ihtiyaç duyduğu bilgiyi sorgu parametrelerinde gönderin; handler onu connection.Request.Header.Query üzerinden okur. Ya da gizli bilgileri ilk mesaj olarak gönderin.
İzin verilmeyenler
Kodunuz ortak bir sunucuda çalışır. Bu yüzden C# dilinin bazı kısımları derlenmeden önce reddedilir: süreç başlatmak, kendi soketlerinizi açmak, assembly yüklemek, çalışma alanınızın dışında dosya sistemine erişmek ve bunları aşmak için reflection kullanmak. Bir task’ı await yerine .Result veya .Wait() ile beklemek de reddedilir: istekler çekirdek başına tek bir thread üzerinde çalışır ve task, onu bekleyen thread’in ta kendisinde tamamlanmak zorunda kalırdı.
Geri kalan her şey mevcut, GenHTTP modül API’sinin tamamı dahil. Bir şey reddedilirse sadece başarısız olduğu değil, hangi satırda ve neden reddedildiği de söylenir.
Kodunuzu alıp gitmek
Editördeki .NET projesi olarak indir ile lambdanın tamamını alırsınız: açabileceğiniz, dotnet run ile çalıştırabileceğiniz ve saklayabileceğiniz bir solution. Yalnızca GenHTTP paketine ihtiyaç duyar ve container olarak derleyip çalıştırmanız için bir Dockerfile ile gelir.
Kod parçanız Project.cs olur, Program.cs de döndürdüğü şeyi sunar. Diğer dosyalarınız tam yazdığınız gibi, bulundukları yerde gelir: kaynaklar resources içinde, dokümantasyon docs içinde, testler tests içinde. Workspace ve Resources programın yanında, ayrı bir Platform klasöründe iki klasör olur ve aynı metotlarla çalışır. Yani kodunuzda hiçbir şeyi değiştirmeniz gerekmez. Secret orada aynı adlı ortam değişkenlerini okur; değerler burada kalır. Database ise database/database.db dosyasını açar; indirilen proje bu dosyayı uygulamanızın tuttuğu kayıtlarla birlikte getirir.
Burada bir şey yapmadan önce bilmekte fayda var: yazdığınız kod sizindir ve eksiksiz olarak sizinle gelir. Onu bu makinede çalıştırmak, onu bu makineye bağlamaz.
git ile üzerinde çalışmak
Her lambda aynı zamanda bir git deposudur. Kontrol panelinin genel bakışındaki ve kodunun yanındaki Klonla düğmesi onun adresini verir - editörünüzün adresi ve ardından uygulamanın adı. git clone, size İndir ile aldığınız projeyi verir; her sürüm main’in bir commit’idir, v1, v2 gibi etiketlenir ve her taslak bir daldır. Kendi editörünüzde açın, kodlama ajanınıza verin, dotnet run ile çalıştırın.
git clone https://genhttp.dev/editor/<editor key>/my-app.git cd my-app # change, commit git push -o deploy
Push edin, burada olsun. main’e push edilen her commit sonraki sürüm olur; ilk satırı yaptığı değişikliktir - önce derlenir, derlenmezse reddedilir - ve git push -o deploy onu yayına alır. Push ettiğiniz bir dal taslak olur ve önizlemesi kendi adresinde yayındadır; onu main’e push edin ya da son push’una -o merge ekleyin, sonraki sürüm olsun. Platformun kodunuzu bir proje yapmak için etrafına koyduğu şeyler - Program.cs, proje dosyası, Platform - uygulamanızın parçası değildir; bu yüzden onları değiştiren bir push reddedilir ve nedenini söyler. Depodaki AGENTS.md, bir kodlama ajanına gerisini anlatır.
Adres, editörün adresi gibi editör anahtarınızı içerir: ona sahip olan push edebilir. Uygulamanızın tuttukları - kayıtları, dosyaları, anahtarları ve parolaları - asla depoda bulunmaz.
Kodu yayımlamak
Yaptığınız şey başka birinin işine yarayabilecekse kodunu yayımlayın: kontrol panelinde Açık kaynak bölümünü açın, bir lisans seçin (başka bir lisans istemiyorsanız MIT) ve düğmeyi açın. Kodu, açık kaynak uygulamalar arasında kendi sayfasını alır. Orada herkes onu okuyabilir, ona yıldız verebilir, herhangi bir sürümünü İndir ile aldığınız projenin aynısı olarak, yanında lisansıyla birlikte indirebilir ya da her sürümünü git ile klonlayabilir.
Her sürüm yayımlanır, öncekiler de; her biri tüm koduyla (dokümantasyonu ve testleri de bunun içinde) ve yaptığı değişiklikle birlikte. Uygulamanın sakladıkları (kayıtları, kaydettiği dosyalar, anahtarlarının ve parolalarının değerleri) asla yayımlanmaz; kendi sözlerinizle ne istediğiniz ve uygulamayı kimlerin kullandığı da. Kapattığınızda sayfa kaldırılır; yıldızları ise yeniden yayımladığınızda geri gelmek üzere saklanır.
Koddaki her şey herkese açık hâle gelir, önceki sürümler de dahil. Bir anahtarın ya da parolanın yeri, Veriler altındaki anahtarlar ve parolalardır; yayımlansın ya da yayımlanmasın, asla kod değildir.
İşi bir ajana bırakmak
/mcp adresinde bir MCP endpoint’i var. Bir ajanı buraya bağlayın, editörün yaptığı her şeyi yapabilir: kılavuzu okur, bir demoyu baştan sona inceler, dosya yazar, derler ve yayına alır. Altta aynı API çalışır.
Ajan çalışırken nedenini de söyler (write_code aracı spesifikasyonu ve değişikliği alır) ve yayına aldığı şeye bakabilir: read_logs aracı lambdanın son isteklerini, yazdırdıklarını ve fırlattığı her hatanın stack trace’ini döndürür. Ajan, kodunun çalıştığını varsaymak yerine böyle öğrenir. Siz de aynı şeyi kontrol panelinde izlersiniz. Ajan çalışırken dokümantasyonu ve testleri de yazar, bir şeyi değiştirmeden önce onları okur ve bir taslağı yayına almadan önce testleri taslağın adresi üzerinde çalıştırır. Bulunması istenen bir sayfaya başlık, açıklama, simge ve linki paylaşıldığında görünen bir önizleme ekler. Oluşturduğu sayfaların altına, GenHTTP Lambda ile yapıldıklarını belirten küçük bir satır ekler; istemezseniz ajana söyleyin, satırı kaldırır.