16 KiB
Kullanıcı verisi yedekleme ve geri yükleme
Araç users.sqlite ve veritabanında referansı bulunan belgeler/ dosyalarını kapsar. İhale/kalem arşivi, kaynak önbellekleri, ortam değişkenleri ve dağıtım yapılandırması bu yedeğin parçası değildir. Tam üretim geri dönüşü için bunların ayrıca platform volume/config yedeği gerekir.
Önkoşul
Uygulamayı ve bu dizine yazan bütün zamanlanmış işleri platform üzerinden durdurun. Etkin sunucu ortamından gerçek IHALEIST_USER_DATA_DIR/volume yolunu doğrulayın. --offline işlemlerin durdurulduğuna ilişkin operatör beyanıdır; araç çalışan servisleri otomatik bulup kapatmaz. Canlı dosya silme/yükleme sürerken tutarlı yedek garantisi verilmez.
Node'un node:sqlite modülü gerekli. Aşağıdaki yollar örnektir; doğrulanan yollarla değiştirin. Hedef dizin henüz bulunmamalı.
node server/backup-user-data.mjs backup /volume/data /backups/release-001 --offline
node server/backup-user-data.mjs verify /backups/release-001
node server/backup-user-data.mjs restore /backups/release-001 /recovery/release-001
Yedek aracı SQLite snapshot oluşturur, bütünlük kontrolü yapar, referanslı dosyaları kopyalar ve SHA-256/byte manifesti üretir. Kayıp dosya başarısızlıktır; eksik yedek başarılı gösterilmez. Dizin/dosya izinleri 0700/0600'dır. Doğrulama şifreleme veya imza değildir; yedeğin erişimini ve dış saklamasını platformda ayrıca yönetin.
Geri dönüş provası
- Önce yeni bir test dizinine geri yükleyin. Üretim dizininin üzerine yazmayın.
- Geri yüklenen dizine bağlı izole uygulamada iki test hesabının kayıtlarını, beş hazırlık kaydını, belgelerin indirilmesini, fiyat/toplam ve sürüm çakışmalarını doğrulayın.
- Yayın adayının migration'ını bu kopyada çalıştırın. Eski ve yeni uygulama sürümlerinin hangi şemayla uyumlu olduğunu kaydedin; otomatik ters migration varsaymayın.
- Uygulama ve veri geri dönüş noktalarını birlikte seçin. Platformun volume değiştirme adımı doğrulanmadan üretim dizinini silmeyin/yeniden adlandırmayın.
- Yayın sonrası kayıt/indirme hatası varsa ilgili özelliği kapatın; doğrulanmış uygulama/volume çiftine dönüşü uygulayın. Başarılı yeni kullanıcı kayıtları varsa eski yedeğe kör dönüşle bunları kaybetmeyin; ileri düzeltme veya veri birleştirme değerlendirin.
Mevcut kanıt
tests/backup-user-data.test.mjs izole SQLite ve gerçek Türkçe dosya baytlarıyla yedek/restore, hazırlık fiyatı, hedef üzerine yazmama ve değiştirilmiş yedeği reddetme senaryolarını doğrular. Üretim servis durdurma, volume yedeği ve platform geri dönüşü henüz denenmedi. Bu dosya yayın onayı veya tüm D11 tamamlandı beyanı değildir.
Bekleyen dosya temizliği
20260906_document_file_cleanup migration'ı, mantıksal olarak silinmiş belgelerin fiziksel dosyalarını kalıcı kuyrukta tutar. Erişim kaydı ve temizleme görevi aynı transaction'da değişir; sonraki veritabanı açılışları temizliği yeniden dener. Dosya sistemi sorunu sürüyorsa kuyrukta kalır. Bu dosyalar aktif belge yedeğine dahil değildir; yedekte kuyruk kaydı bulunup dosya bulunmazsa yeniden açılışta ENOENT başarılı temizleme olarak ele alınır. Fiziksel silmenin anında tamamlandığı varsayılmamalı; işletim kontrolünde kuyruk büyüklüğü ve volume izinleri izlenmelidir.
Kaynak gözlem geçmişi IHALEIST_SHARED_DATA_DIR/tender-history.sqlite içinde saklanır (değişken yoksa server/data). Kullanıcı verisi yedek aracı bu depoyu kapsamaz; tam yayın/geri dönüş provasında ortak veri volume'uyla birlikte ayrıca yedeklenmelidir.
Ortak veri volume'u için yedekleme
server/backup-data-volume.mjs, seçilen ortak veri dizinindeki normal dosyaları alt dizinleriyle kapsar. Dosya başlığından SQLite olarak tanınan depolar VACUUM INTO ile alınır; bağlı WAL/SHM dosyaları ayrı kopyalanmaz. Diğer dosyalar kopyalanır, boyut ve SHA-256 manifesti yazılır. Büyük dosyaların hash'i akışla hesaplanır. Sembolik bağlantılar, iç içe kaynak/hedef ve mevcut hedef dizinleri reddedilir.
Bütün kaynak yazıcılarını durdurduktan sonra, doğrulanmış gerçek volume yollarıyla:
node server/backup-data-volume.mjs backup /volume/shared /backups/shared-release-001 --offline
node server/backup-data-volume.mjs verify /backups/shared-release-001
node server/backup-data-volume.mjs restore /backups/shared-release-001 /recovery/shared-release-001
Bu araç seçilen dizin dışındaki worker depolarını, ortam değişkenlerini veya dağıtım yapılandırmasını kendiliğinden bulmaz. Kullanıcı belgelerinde veritabanı-dosya referans kontrolü için kullanıcı yedek aracını da kullanın. Tüm veri dizinleri ve kullanıcı yedeği aynı durdurulmuş sürümün seti olarak alınmalı; manifest zamanları tek başına servislerin durduğunu kanıtlamaz. Şifreleme/imzalama yapılmaz; backup erişimi ve dış saklama platformda yönetilir. Fiziksel boş dizinler ayrı manifest girdileri değildir.
tests/data-volume-backup.test.mjs, iki SQLite deposu, committed WAL verisi, alt dizin dosyası, restore, hedef üzerine yazmama, değişmiş/ek dosya ve sembolik bağlantı reddini doğrular. Gerçek üretim volume'larına bu komutlar henüz uygulanmadı; platform geri dönüş provası açık.
Kalıcı teklif asistanı işleri IHALEIST_USER_DATA_DIR/ai-jobs.sqlite içinde özel kaynak ve sonuç metni içerir. backup-user-data.mjs yalnız users.sqlite ve referanslı belgeleri aldığı için bu dosya ayrıca volume aracıyla yedeklenmelidir. Bütün yazıcılar durdurulmadan job/user yedek seti tutarlı kabul edilmez.
Kalıcı genel analiz ve teklif işleri için süreç kesintisi davranışı:
- İşçi kaynak metnini sabitledikten sonra aniden kapanırsa kayıt hemen başarısız sayılmaz. Son heartbeat üzerinden 60 saniye dolunca iş tarayıcısı kaydı
interrupteddurumuna geçirir. - Kesilen işi otomatik tekrar çağırmaz; kullanıcı Kayıtlı AI işleri üzerinden yeniden başlatır. Kaynak sabitlenmişse aynı girdi kullanılır. Sağlayıcıya daha önce ulaşmış çağrının ücretini veya sonucunu geri alma garantisi yoktur.
- İnsan incelemeli genel analizde dosya/inceleme sürümü değişmişse eski işi yeniden başlatmak yerine güncel incelemeyle yeni iş gerekir.
- Kaynağın sabitlenmesinden önce kesilen işin, geçmişte hangi uzak metni edinmiş olabileceği kanıtlanamaz. Eski sürümde tamamlanan kayıtların kaynakları geriye dönük üretilemez.
node --test tests/ai-job-crash.test.mjs: iki gerçek alt süreç SIGKILL testi; yeni süreçte kaynak/sonuç ve SQLite bütünlüğü kontrol edilir. Lease süresi testte saat parametresiyle ilerletilir. Gerçek AI sağlayıcısı ve üretim platformunun volume yeniden bağlama davranışı bu testin kapsamı dışındadır.
Bildirim ve takip taraması deposu artık IHALEIST_USER_DATA_DIR/takip.sqlite içindedir; değişken yoksa mevcut server/data/takip.sqlite yolu korunur. Özel kullanıcı veri diziniyle çalışan eski kurulum yükseltilirken eski sabit yoldaki takip.sqlite ayrıca envantere alınmalıdır. Tüm yazıcılar durdurularak SQLite tutarlı yedeği doğrulanmalı ve hedefte mevcut bir takip.sqlite üzerine yazmadan yeni dizine aktarılmalıdır. Bu yerel değişiklik üretim verisini taşımadı. Tam volume yedeği bu dosyayı kapsar; yalnız backup-user-data.mjs kullanmak bildirimleri yedeklemez.
E-posta aboneliği deposu notify.sqlite da IHALEIST_USER_DATA_DIR ayarını izler; değişken yoksa eski server/data yolu kullanılır. Özel dizinli eski kurulumlarda yükseltmeden önce sabit yoldaki notify.sqlite tutarlı biçimde yedeklenip yeni hedefe taşınmalıdır; mevcut hedef üzerine yazılmaz. Yerel değişiklik üretim deposunu taşımadı. Bu dosya yalnız kullanıcı/belge yedeğinin kapsamına girmez, tam volume envanterinde ayrıca bulunmalıdır.
notify.sqlite abonelik kimliği geçişi: criteria_key sütunu eklendi; konu ve kurum kümeleri dahil bütün filtreler aboneliğin kimliğine katılır. Eski tablo işlem içinde yeniden kurulur; id, oluşturulma, aktiflik, son gönderim, görülen ihaleler ve AUTOINCREMENT üst sınırı korunur. Eski eşdeğer yinelenen kayıtlar silinmez; ayrı legacy kimliğiyle korunur. Bozuk eski konu/kurum JSON'u geçişi başarısız yapar ve transaction geri alınır. Yükseltmeden önce notify.sqlite yedeği alınmalı; eski uygulama koduna dönülecekse eski unique kuralını kullanan INSERT nedeniyle yalnız kodu geri almak yeterli değildir: eşleşen eski veritabanı yedeğiyle birlikte geri dönüş gerekir. Yeni sürümde oluşan kayıtların geri dönüşte nasıl korunacağı ayrıca değerlendirilmelidir.
Kalıcı e-posta kuyruğu aynı notify.sqlite içinde notification_outbox tablosundadır. Tam içerik/gönderen/alıcı ve ihale listesi ile sağlayıcı istek kimliği burada korunur; yedeğe dahil edilmelidir. Bir bekleyen grup abonelik başına tek aktif kayıtla tutulur. 120 saniyelik işçi sahipliği, 30 saniyelik sağlayıcı isteğinden uzundur. İlk denemeden 23 saat sonra belirsiz kayıt otomatik tekrar gönderilmez; Resend'in 24 saatlik tekrar önleme süresine güvenli pay bırakılır. Yönetici sağlayıcı kaydını doğrulamalıdır; Mobil PWA sayfasındaki yöneticiye özel E-posta gönderim incelemesi bölümünden kayıt karara bağlanır. Sağlayıcı kabulü doğrulandıysa gönderim kimliği/onay/açıklama ile kapatılır; aksi halde yeniden göndermeden kapatma seçilebilir. Her iki işlem de yeni e-posta göndermez ve açıklamalı karar geçmişini korur. Bekleyen iş varken sağlayıcı hesabı/anahtarı değiştirilmemelidir: tekrar önleme anahtarı farklı sağlayıcı hesapları arasında garanti vermez. Eski uygulamaya dönmek kuyruğu yok sayabileceğinden kod ve DB geri dönüşü birlikte değerlendirilmelidir.
node --test tests/outbox-crash.test.mjs, sağlayıcı kabulünden sonra commit öncesi/sonrası gerçek SIGKILL kurtarmasını izole volume'da sınar. Ayrı süreçte aynı payload/istek kimliği ve SQLite bütünlüğü doğrulanır. Sağlayıcı yerel bir simülatördür; test gerçek Resend hesabının idempotency davranışını veya üretim platformundaki disk kurtarmasını kanıtlamaz.
Güncellik nedeniyle tutulan e-postalar
Kuyruktaki ilanın artık kaynakta bulunmaması, teklif zamanının değişmesi, iptal/sonuç veya süre aşımı halinde otomatik tekrar durur ve yönetici inceleme listesinde gerekçe görünür. Liste sınırlaması veya geçici kaynak eksikliği de bu durumu oluşturabilir. Önce sağlayıcı kaydını ve resmi ilanı karşılaştırın; mevcut karar akışından gönderildiğini kanıtlayarak veya yeniden göndermeden kapatarak çözün. Payload ya da idempotency anahtarını elle değiştirmeyin. Yeniden göndermeden kapatmak bu gruptaki ihale kimliklerini görülmüş sayar; değişen ilan için otomatik yeni e-posta taahhüt edilmez.
Firma profili / kayıtlı filtre sürüm sözleşmesi
GET /api/me/data artık veri ile aynı okumaya ait revisions döndürür. firma_profil ve saved_filters PUT/POST istekleri revision göndermelidir (yeni kayıt için null). Eksik sürüm 428, değişmiş sürüm 409 üretir; otomatik üzerine yazma veya otomatik tekrar yoktur. Frontend ve backend birlikte sürümlenmelidir. Eski açık sekme 428 alırsa kaydedilmemiş girdiler korunup sayfa yenilenmelidir. Veritabanı şeması değişmez; eski sunucuya dönmek bu iki anahtardaki çakışma korumasını kaldırır. Yayın kabulünde iki sekmenin aynı kaydı değiştirmesi ve reddedilen sekmenin girdilerinin korunması sınanmalıdır.
Ekip kaydı (ekip) da aynı içerik sürümü sözleşmesine dahil edildi. Yeni ekip arayüzü sunucu onayını bekler. Eski istemciden sürümsüz ekip yazımı 428 ile reddedilir; frontend/backend birlikte güncellenmelidir. Ekip alanlarının geçersiz veya kimliklerinin yinelenmiş olduğu eski kayıtlar önce düzeltilmelidir; sessiz veri temizliği yapılmaz.
Favori kurumlar (favori_kurumlar) da sürümlü kullanıcı verisi yazımı ister. Eski istemcinin sürümsüz yazımı 428 döner; frontend/backend birlikte sürümlenmelidir. Bekleyen değişiklikler sunucudan onay gelmeden favori listesinde gösterilmez.
Rakip izleme (rakip_izleme) da içerik sürümü zorunlu anahtarlara dahil edildi. Eski istemcilerde sürümsüz yazım 428 alır; güncel frontend ile aynı sürüm backend kullanılmalıdır. Eski rakip kayıtlarındaki ölçüler yeni arayüzde güncel havuz eşleşmesi yerine kullanılmaz; kayıtlı firma adı/sektör korunur.
Bildirim tercihleri (reminder) sürümlü yazım sözleşmesine dahil edildi. Saat alanları HH:mm, pushEnabled/quietEnabled alanları boolean olmalıdır. Frontend/backend birlikte güncellenmelidir. Eski e-postaEnabled kaydı e-posta aboneliği iptali anlamına gelmez; gönderimler abonelik yönetiminden denetlenir.
Haftalık özet brief anahtarı user-store tarafından artık kabul edilir. /api/me/brief GET tercih ve revision döndürür; metin/brief önizlemesi için ?preview=1 gerekir. POST boolean kapali ve okunan revision ister. Frontend/backend birlikte güncellenmelidir; eski sürüme dönmek brief kaydını tekrar reddeder ve opt-out tercihini okuyamayabilir.
Haftalık özet teslimat deposu IHALEIST_USER_DATA_DIR/brief.sqlite içindedir (ayar yoksa server/data). Alıcı, haftalık mesaj planı, mesaj içeriği, parça konumu, işçi sahipliği ve kabul/belirsizlik kayıtlarını içerir; özel veridir. Tam volume yedeği bu SQLite dosyasını kapsar, yalnız kullanıcı/belge yedeği kapsamaz. Dosya 0600, yeni dizin 0700 oluşturulur. Kod geri dönüşü bu kayıtları yok sayıp aynı haftanın özetini tekrar gönderebilir; eski kodun otomatik gönderimini açmadan geçiş haftası sağlayıcı kayıtları değerlendirilmelidir.
Eski server/data/brief-son.json silinmez: eski sürümün aynı hafta için işaretlediği otomatik gönderim geçişte tekrar yapılmaz. Eski sürüm bu işareti göndermeden önce yazdığı için bu kayıt teslimatı kanıtlamaz. Geçiş haftası manuel kontrol gerektirir. Yeni zamanlayıcı bu dosyaya tamamlandı kaydı yazmaz; kaynak yüklenemezse Pazartesi sonraki saatlik kontrolde tekrar yükleyebilir. Sağlayıcı çağrısına girilmiş fakat kabulü doğrulanamamış mesajlar otomatik yeniden gönderilmez. 120 saniyelik sahipliği sona eren yarım kayıt da belirsiz olur. brief-outbox.mjs içindeki salt-okuma inspect() sonuçları kayıt incelemesine yardım eder; yönetici karar ekranı/karar geçmişi henüz tamamlanmadı. Kayıtları silmek veya doğrudan pending yapmak yeniden mesaj gönderme riski taşır.
Haftalık belirsiz kayıtların karar akışı artık Yönetim → Mobil PWA → Haftalık özet gönderim incelemesi bölümündedir. /api/admin/brief/outbox yalnız yöneticiye açıktır. Gönderildi kararı sağlayıcı kimliği, açık kontrol onayı ve 20–2000 karakterlik açıklama ister; doğrulanamayan mesaj yeni gönderim yapmadan kapatılabilir. brief_reviews tablosu karar sahibini, türünü, açıklamasını ve tarihini aynı transaction içinde saklar. İkinci karar 409 ile reddedilir. Süresi dolmuş gönderim sahipliği liste yenilendiğinde belirsiz olarak görünür; etkin gönderim için karar verilemez. Tam volume yedeği karar tablosunu da kapsar. Bu bölüm önceki nottaki eksik yönetici karar ekranını tamamlar; sağlayıcı teslimat kanıtını otomatik olarak doğrulamaz.
Yeni haftalık Telegram kabulleri brief_messages.receipt alanında chat_id:message_id olarak saklanır. Eski telegram-accepted değerleri gerçek mesaj kimliği değildir ve geriye dönük kimlik üretilmez. Sağlayıcı incelemesinde mesajın ait olduğu sohbet de kontrol edilmelidir; mesaj numarası tek başına bütün sohbetlerde tekil kabul edilmez.