4 puan yazan GN⁺ 2024-04-08 | 1 yorum | WhatsApp'ta paylaş
  • pgmock, birim testleri ve E2E testleri için bellek içi bir PostgreSQL mock sunucusudur; dış bağımlılık olmadan Node.js ve tarayıcıda WebAssembly üzerinde çalışır
  • node-postgres kullanıcıları, port açmayan bir yapılandırma nesnesi alarak bağlanabilir; bu yöntem tarayıcıda da çalışır
  • Tarayıcıda web uygulamaları TCP portu açamaz, ancak PostgresMock.createSocket ve node-postgres yapılandırması kullanılabilir; bundler statik import’ları analiz ederse isteğe bağlı Node.js modülleri için uyarı verebilir
  • Uygulama şu anda PostgreSQL sunucusunu bir x86 emülatörü içinde çalıştırma yaklaşımını kullanıyor; test ve prodüksiyon arasındaki davranış farklarını önlemeyi performansa göre önceliklendiriyor
  • Uzun vadede, yerel PostgreSQL WASM fork’u olgunlaştığında iki yaklaşımı da sunma ve sonrasında varsayılanı yerel WASM’e çevirme planı var

pgmock’un sundukları

  • pgmock, birim testleri ve E2E testleri için bellek içi bir PostgreSQL mock sunucusudur
  • Dış bağımlılık gerektirmez; hem Node.js hem de tarayıcı tarafında WebAssembly içinde çalışır
  • npm ile kurulabilir
npm install pgmock

Temel kullanım akışı

  • Bellek içi sunucu PostgresMock.create() ile oluşturulur ve listen(5432) ile bağlantı dizesi alınabilir
import { PostgresMock } from "pgmock";

const mock = await PostgresMock.create();
const connectionString = await mock.listen(5432);
  • node-postgres kullanılıyorsa mock.getNodePostgresConfig(), port dinlemeden bağlanmayı sağlayan bir yapılandırma nesnesi sunar
  • İş bitince kaynakları serbest bırakmak için mock.destroy() çağrılması önerilir
mock.destroy();

Tarayıcı desteği ve pglite ile farkı

  • pgmock, tarayıcı ortamını tam olarak destekler
  • Web uygulamaları TCP portu açamaz, ancak PostgresMock.createSocket ve node-postgres yapılandırması kullanılabilir
  • Bundler import’ları statik olarak analiz ederse, isteğe bağlı Node.js modüllerinin bulunmadığına dair uyarı verebilir; Webpack yapılandırma örneği examples/web-demo/next.config.mjs içinde yer alır
  • Tarayıcıda yalnızca veritabanı çalıştırmak istiyorsanız pglite değerlendirilebilir
    • pglite daha hızlı ve hafiftir, ancak özellik kümesi sınırlıdır
    • pgmock, test ortamında istenen prodüksiyon PostgreSQL ile özellik eşdeğerliğini hedefleyecek şekilde tasarlanmıştır

PostgreSQL’i WebAssembly’de çalıştırma yöntemleri

  • PostgreSQL’i WebAssembly’de çalıştırmanın iki yolu vardır
  • Yerel WASM fork’u yaklaşımı daha hızlıdır ve çok daha az bellek kullanır, ancak yalnızca tek kullanıcı modunu destekler; bağlantıları ve eklentileri desteklemez
  • pgmock şu anda x86 emülatörü yaklaşımını kullanıyor
    • Amaç, test ve prodüksiyon arasındaki uyumsuzluğu önlemektir
    • Çünkü testlerde performans genellikle büyük bir sorun değildir
  • Orta vadede yerel PostgreSQL WASM fork’u olgunlaştığında iki seçeneği de sunma planı var
  • Sonrasında varsayılanı yerel WASM’e çevirme planlanıyor; PostgresMock.subtle iç API’si dışında çok fazla büyük breaking change beklenmiyor

Mevcut tarayıcı PostgreSQL projeleriyle farkı

  • pgmock, JavaScript runtime’ı içinde tam özellik uyumluluğu sağlar ve iletişim için ağ proxy’sine bağımlı değildir
  • Ağ yığınını JavaScript ile simüle ederek gerçek ağ gibi davranmasını sağlar ve raw socket erişimine izin vermeyen platformlarda da TCP bağlantısını simüle edebilir

Genişletilebilirlik ve ilgili projeler

  • Diğer Docker imajlarını veya veritabanlarını çalıştırmak teorik olarak mümkündür, ancak test edilmemiştir
  • İlgili uygulamalar ve temel projeler olarak şunlar belirtilmiştir
    • v86: x86 emülatörü
    • Supabase & Snaplet: PostgreSQL’i WebAssembly içinde çalıştırma yaklaşımının temeli
    • Stackframe: pgmock geliştirilirken maaş sağlayan şirket olarak anılır

1 yorum

 
GN⁺ 2024-04-08
Hacker News yorumları
  • Birkaç aydır şirkette bellek içi Postgres sürümü üzerinde çalışıyorduk ve üretim veritabanıyla özellik eşdeğerliğine sahip
    Avantajı, harici bir süreç ya da proxy gerektirmemesi. Platform WASM çalıştırabiliyorsa pgmock’u Node.js’te veya tarayıcıda da çalıştırabilirsiniz; sahte verilerle dolu yeni bir veritabanı oluşturmak da bir JavaScript nesnesi oluşturmak kadar basit
    pgmock’u açık kaynak yapmamızı sağlayan pglite’tan biraz farklı. pgmock, özgün Postgres’i bir x86 emülatörü içinde çalıştırıyor; pglite ise bir Postgres fork’unu doğrudan native WASM’e derlediği için daha hızlı ve hafif
    Ancak pglite tek kullanıcı modunu ve yalnızca bazı eklentileri desteklediğinden normal Postgres istemcileriyle bağlanılamıyor; bu da E2E testlerinde oldukça önemli
    Teorik olarak WebAssembly platformunda herhangi bir Docker imajını çalıştıracak şekilde değiştirilebilir; görmek istediğiniz belirli bir hedef var mı merak ediyorum

    • Harika iş. PGlite’ın şu anda yalnızca tek kullanıcı desteklediği doğru ve bazı ortamlarda entegrasyon testleri için kullanmak sorun olabilir
      Çoklu bağlantı modu eklemek için birkaç yol düşünüyoruz ama biraz zaman alacak gibi. PGlite’ta tek kullanıcı moduyla ilgili başka sınırlamalar da var; örneğin pg_notify’ı henüz desteklemiyor, bunu da düzeltmeyi planlıyoruz
      Öte yandan bu proje gerçek Postgres’e çok daha yakın, bu yüzden doğrudan çalışması daha olası. Bu tür bellek içi Postgres projeleri test çalışma sürelerini dörtte birin altına indirebilecek gibi görünüyor ve test alanında büyük potansiyele sahip
      PGlite üzerinde çalışan biri olarak düşüncelerim bunlar
    • Docker imajlarını WASM’de çalıştırma fikri birçok sorun için umut verici görünüyor
      Yakın zamanda istemcide FFMPEG/SoX hattı çalıştırmak istemiştim; bağımlılıkları o kadar fazlaydı ki Emscripten ile kolayca yeniden derlemek zordu. Bu yaklaşımın böyle durumlarda da yardımcı olup olamayacağını merak ediyorum
    • pgvector eklentisini destekleyebilirse, Postgres’in tüm gücüne sahip çok hızlı bir vektör veritabanına dönüşebilir
      İlişkisel özellikler sayesinde, normalde ilişkisel veritabanlarında bulunan zengin alana özgü metaverileri ekleyip birlikte sorgulayabilirsiniz
    • Bu arada çevrimiçi demo, hoşuna gitmeyen sorgularda bozuluyor gibi
      select foo(); çalıştırınca Error.captureStackTrace is not a function çıkıyor; Linux’ta Firefox 124.0.2’de oluyor
    • Harika ama E2E test kavramının kendisi, bileşenleri mock’larla değiştirmek yerine gerçek ortamı kullanmak anlamına gelmiyor mu?
  • Postgres dosyalarını basitçe ramdisk üzerine koyup çalıştırmak olmaz mı diye merak ediyorum
    Güncelleme: Tarayıcı/Node ortamında çalışabildiği için testler oluşturup güncelleyip silebiliyor gibi. Fazlasıyla backend geliştiricisi olduğumdan, sıradan geliştirme ortamına göre avantajını pek kavrayamıyorum. Nerede, ne zaman ve nasıl daha iyi olduğunu açıklayabilirseniz iyi olur

    • Emülatörün içinde de genel olarak benzer bir şey oluyor. Emüle edilen disk, bellek içi 9P dosya sistemi
      WebAssembly ile yapılmasının nedeni; platformlar, mimariler, tarayıcı veya edge ortamları arasında davranışı daha taşınabilir biçimde eşleyebilmek ve Docker’a bile ihtiyaç duymayan, harici bağımlılıksız bir kurulum elde etmek
      Emülatör zaten çalışır durumdayken doğrudan önyükleme yapabildiği için emüle edilen veritabanı, gerçek bir veritabanı ya da Docker konteyneri başlatmaktan daha hızlı açılıyor. Ancak bu, tasarım hedefinden çok şans eseri elde edilmiş bir etki
    • Ben de pek emin değilim. Emülatör, ağ yığını vb. gereksiz kod çok fazla görünüyor
      https://testcontainers.com/ gibi bir şey kullanılamaz mı diye merak ediyorum. Konteyner motorunun harici bağımlılık olması gerçekten o kadar kötü mü?
    • E2E testlerinin amacı sistemi gerçek durumunda test etmektir. Üretim ortamının bir emülasyonu olduğu için fiş çekilince ya da disk dolunca ne olacağını da görebilirsiniz
      İçine mock soktuğunuz anda bu birim testine dönüşür. Etkilidir ama aynı şey değildir. E2E’nin kilit noktalarından biri, mock olmadığı için testin doğru olduğunu bilebilmenizdir. Bu, Postgres’i test etmek değil; her seferinde bu sistemi test etmek demektir
      Gömülü, hafif, düşük performanslı sistemler için PG yapıyorsanız, yavaş gerçek E2E testlerinden önce doğrulama testi olarak mantıklı. Benim de böyle bir kullanımım var
      Bunun dışında güzel bir proje ve PG shim gerektiğinde kullanılabilecek bir araç gibi görünüyor
    • Test izolasyonu için yararlı olabilir. Redis backend’ini testlerde FakeRedis’e taşıyınca test paketindeki gürültü epey azaldı
      Postgres’te savepoint kullanıyoruz ama ramdisk üzerinde bile pek hızlı değil
  • Eskiden testlerde her türden özel sahte bellek içi sunucu çalıştırırdık. Bugünlerde https://testcontainers.com ile gerçek hedefleri çalıştırıyoruz

  • Prisma/Node.js geliştiricisi yerel geliştirme için yalnızca “kutuda Postgres” istiyorsa, PGlite’ın yakın zamanda çıkan sunuculaştırılmış sürümü pglite-server daha iyi olabilir: https://github.com/kamilogorek/pglite-server
    Daha hızlı ve verileri dosya sisteminde tutabiliyor; ancak yoğun kullanımda tam x86 emülatörü tabanlı E2E test sunucusundan daha az kararlı. pglite-server yalnızca 150MB bellek kullanırken pgmock-server 830MB kullandı
    dotenv ile yeni bir .env.local checkout edip tüm nextjs/prisma package.json çalıştırma betiklerinde DATABASE_URL’yi değiştirmeniz yeterli
    DATABASE_URL="postgresql://postgres@localhost:5432/awesomeproject"
    "db:pushlocal": "dotenv -e .env.local -- pnpm prisma db push"
    Her projeye çok kolayca eklenebilir; Neon’un bu alanı desteklemesini de anlayabiliyorum

  • Heves kırmak istemem ama ben bunu kullanmayı düşünmem
    Basit bir uygulamada işe yarayabilir; ancak kilitlenme riski olması veya veritabanı biçimine bağımlılık gibi karmaşıklık arttığında, davranıştaki küçük farklar bile ölümcül sorunlara dönüşebilir ve değeri azalır
    Bu aralar kaynak kısıtlı E2E ortamlarını tercih ediyorum. Çünkü yerel test çalıştırıcısına, biri aşırı verimsiz kod yazdığında bozulma fırsatı veriyor
    Ayrıca veritabanını birkaç saniye sonra anlık görüntüye dönüştürüp bu snapshot’ı test bölümlerine dağıtmak çok hızlı; test paketlerinden çoğu kez dakikalar kazandırdı
    İlginç bir fikir ve iyi bir öğrenme deneyimi, ancak hedef kullanıcı kitlesinin sınırlı olduğunu düşünüyorum

  • Başlık biraz kafa karıştırıcı. “Şirkette yaptı” deniyorsa, şirket kaynaklarının kullanıldığı varsayımıyla bu projenin fikri mülkiyet haklarının işverene ait olması gerekmez mi diye düşünüyorum
    Öyleyse teknik olarak açık kaynak yayımlanıp yayımlanamayacağını merak ediyorum

    • Startup olduğu için açık kaynak yayımlamak, ekibin geri kalanından onay almak kadar kolaydı
    • Depo Stackframe’e ait ve LICENSE dosyasında Copyright 2024 Stackframe. yazıyor. Görünüşe göre yazar Stackframe’de çalışıyor
  • Bunun H2’nin Postgres uyumluluk modu ile karşılaştırıldığında nasıl olduğunu merak ediyorum

    • Yanılıyor olabilirim ama H2’de PostgreSQL stored procedure’ları kullanılamıyor gibi
  • Oldukça havalı. Cevaplayabiliyorsanız birkaç şeyi merak ediyorum
    Şirkette bu projeyi yapmaya neyin yol açtığını, Docker container’ında Postgres çalıştırmanın çok mu yavaş olduğunu merak ediyorum
    pgmock’u akışa entegre etmeden önce ve sonra E2E testleri için CI yapılandırmasının nasıl değiştiğini de bilmek isterim
    Bu çözüme geçiş sürecinin zor olup olmadığını da merak ediyorum

  • Üretim verilerini dump edip tüm hassas verileri kaldırdıktan sonra, log tabloları gibi gereksiz tabloları truncate ederseniz geliştirme için iyi bir kopya elde edersiniz
    Bunu geliştirme, QA, E2E vb. ortamlara çoğaltabilirsiniz. E2E için gereken şey tam olarak o extension’lar, trigger’lar, fonksiyonlar, view’lar, indeksler ve verilerdir

  • Neden sadece Docker kullanıp ayrı bir test veritabanı tutmuyoruz, merak ediyorum
    Elixir bunu böyle yapıyor; test framework’ü her testi bir transaction içine sarıyor ve izolasyon için rollback yapıyor. Bu yaklaşımın avantajının ne olduğunu öğrenmek ilginç olurdu