Surface shared inventory failures and isolate test database storage
This commit is contained in:
@@ -579,3 +579,11 @@ Hazırlık formunun hazır hesabına doğrulanmış gelecek tarih/saat kontrolü
|
||||
Tarih/saat ayrıştırması hatalı bitişik ekleri (ör. `10:0099`) geçerli saat kabul etmez. Mevcut Türkiye saat dilimi ve kaynak tarih doğrulaması kullanılır.
|
||||
|
||||
Testler: son teklif anından bir milisaniye önce/sonra; bilinmeyen/geçersiz tarih ve saat; gelecekte tarih taşısa da iptal/sonuçlanmış kayıt. Tüm 127 test ve üretim derlemesi geçti. Gerçek tarayıcıda zamanı geçen uzun çıktı kabulü henüz yapılmadı. Büyük paket uyarıları sürüyor. Planın diğer işleri ve canlı yayın açık.
|
||||
|
||||
### D01 / D05 — Ortak kalem deposu hata ve test ayrımı
|
||||
|
||||
SQLite desteği olmayan ortamda ortak kalem deposu artık boş liste gibi görünmez; hata verir. Depo bağlantısı ancak WAL ve şema kurulumu başarılı olduktan sonra önbelleğe alınır. Başarısız açılışın bağlantısı kapatılır; sorun giderilince aynı süreçte yeniden deneme mümkündür. Kalem listeleme/arama endpointleri erişim sorununu anlaşılır 503 yanıtıyla döndürür.
|
||||
|
||||
`IHALEIST_SHARED_DATA_DIR` ile ortak kalem deposu dizini yapılandırılabilir. Tarayıcı QA ve HTTP test sunucuları ortak kalem verisini kendi geçici dizinlerinde tutacak şekilde güncellendi. Önceden başlatılmış test süreçleri yeniden başlatılmadı; mevcut veri dosyaları silinmedi. Diğer ortak veri depolarının tamamı bu değişiklikle izole edilmiş sayılmaz.
|
||||
|
||||
Test: bozuk gerçek SQLite dosyasıyla açılış başarısızlığı, dosyanın onarılmasından sonra aynı süreçte boş liste ve yeni kalem yazma/okuma. Tüm 128 test ve üretim derlemesi geçti. HTTP testinin yeni izole depo ayarı sonrasında dört HTTP kabul testi ayrıca geçti. Canlı sistemde yapay arıza oluşturulmadı. Büyük paket uyarıları ve planın kalan kapsamı açık; canlı yayın yapılmadı.
|
||||
|
||||
+4
-1
@@ -775,13 +775,16 @@ const server = http.createServer(async (req, res) => {
|
||||
if (url.pathname === '/api/kalem') {
|
||||
const ikn = url.searchParams.get('ikn');
|
||||
if (!ikn) return json(res, 400, { success: false, error: 'ikn gerekli' });
|
||||
return json(res, 200, { success: true, ...kalemStore.kalemOku(ikn) });
|
||||
try { return json(res, 200, { success: true, ...kalemStore.kalemOku(ikn) }); }
|
||||
catch { return json(res,503,{success:false,error:'Kalem deposuna erişilemiyor. Daha sonra yeniden deneyin.'}); }
|
||||
}
|
||||
if (url.pathname === '/api/kalem/ara') {
|
||||
const q = url.searchParams.get('q') || '';
|
||||
if (q.trim().length < 2) return json(res, 400, { success: false, error: 'en az 2 karakter' });
|
||||
try {
|
||||
const sonuc = kalemStore.kalemAra(q);
|
||||
return json(res, 200, { success: true, adet: sonuc.length, sonuclar: sonuc });
|
||||
} catch { return json(res,503,{success:false,error:'Kalem araması şu anda kullanılamıyor. Yeniden deneyin.'}); }
|
||||
}
|
||||
// --- Ürün araması: metni ihale DOKÜMANININ içinde arar ---
|
||||
// EKAP teklif cetvelini kendi tarafında indeksliyor; doküman indirmeye
|
||||
|
||||
@@ -23,7 +23,7 @@ try {
|
||||
}
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const DATA_DIR = path.join(__dirname, 'data');
|
||||
const DATA_DIR = process.env.IHALEIST_SHARED_DATA_DIR || path.join(__dirname, 'data');
|
||||
const DB_PATH = path.join(DATA_DIR, 'kalem.sqlite');
|
||||
|
||||
const SCHEMA = `
|
||||
@@ -56,11 +56,14 @@ export function available() {
|
||||
|
||||
function open() {
|
||||
if (db) return db;
|
||||
if (!DatabaseSync) return null;
|
||||
if (!DatabaseSync) throw new Error('Kalem deposu bu sunucuda kullanılamıyor.');
|
||||
fs.mkdirSync(DATA_DIR, { recursive: true });
|
||||
db = new DatabaseSync(DB_PATH);
|
||||
db.exec('PRAGMA journal_mode = WAL;');
|
||||
db.exec(SCHEMA);
|
||||
const candidate = new DatabaseSync(DB_PATH);
|
||||
try {
|
||||
candidate.exec('PRAGMA journal_mode = WAL;');
|
||||
candidate.exec(SCHEMA);
|
||||
db = candidate;
|
||||
} catch (error) { candidate.close(); throw error; }
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const {signToken}=await import('../server/auth.mjs');
|
||||
const user={email:'browser-qa@example.test',name:'Laboratuvar QA',isAdmin:false};
|
||||
const token=signToken(user);
|
||||
const probe=netServer();await new Promise(r=>probe.listen(0,'127.0.0.1',r));const port=probe.address().port;await new Promise(r=>probe.close(r));
|
||||
const api=spawn(process.execPath,['server/index.js'],{cwd:new URL('..',import.meta.url),env:{PATH:process.env.PATH,NODE_ENV:'test',AUTH_SECRET:process.env.AUTH_SECRET,IHALEIST_USER_DATA_DIR:dir,PORT:String(port),UYUM_GOMME:'0'},stdio:'ignore'});
|
||||
const api=spawn(process.execPath,['server/index.js'],{cwd:new URL('..',import.meta.url),env:{PATH:process.env.PATH,NODE_ENV:'test',AUTH_SECRET:process.env.AUTH_SECRET,IHALEIST_USER_DATA_DIR:dir,IHALEIST_SHARED_DATA_DIR:join(dir,'shared'),PORT:String(port),UYUM_GOMME:'0'},stdio:'ignore'});
|
||||
const entries=[['1582991','Giresun','10.09.2026','10:00'],['1534665','Kayseri','22.09.2026','11:00'],['1499061','Akdeniz','22.09.2026','10:30'],['1573235','Aksaray','09.09.2026','10:00'],['1523851','Tepecik','11.09.2026','10:00']];
|
||||
const tenders=entries.map(([id,city,date,time])=>({id:'qa-'+id,ikn:'2026/'+id,baslik:'QA — '+city+' laboratuvar',kurum:city+' TEST KURUMU',sehir:city,tarih:date,saat:time,alimTuru:'Mal Alımı',sektor:'Laboratuvar & Ölçüm',sektorler:['Laboratuvar & Ölçüm'],durum:'Açık',takipte:false,kanbanStatus:'incelenecek',items:[{id:'1',ad:'Sentetik test kalemi',miktar:2,birim:'adet'}],aciklama:'Bu yalnızca yerel arayüz test verisidir. Teklif geçerlilik süresi 120 takvim günü. Birim fiyat teklif. '.repeat(3)}));
|
||||
const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{target:'http://127.0.0.1:'+port}}},plugins:[{name:'qa-fixtures',configureServer(server){server.middlewares.use((req,res,next)=>{
|
||||
|
||||
@@ -19,7 +19,7 @@ const request=async(path,method='GET',body,auth=token)=>{
|
||||
before(async()=>{
|
||||
const socket=createServer();await new Promise(r=>socket.listen(0,'127.0.0.1',r));const port=socket.address().port;await new Promise(r=>socket.close(r));
|
||||
base='http://127.0.0.1:'+port;
|
||||
child=spawn(process.execPath,['server/index.js'],{cwd:new URL('..',import.meta.url),env:{...process.env,NODE_ENV:'test',PORT:String(port),IHALEIST_USER_DATA_DIR:dir,UYUM_GOMME:'0'},stdio:'ignore'});
|
||||
child=spawn(process.execPath,['server/index.js'],{cwd:new URL('..',import.meta.url),env:{...process.env,NODE_ENV:'test',PORT:String(port),IHALEIST_USER_DATA_DIR:dir,IHALEIST_SHARED_DATA_DIR:join(dir,'shared'),UYUM_GOMME:'0'},stdio:'ignore'});
|
||||
for(let i=0;i<100;i++){try{await fetch(base+'/api/auth/google/config');return;}catch{await new Promise(r=>setTimeout(r,50));}}
|
||||
throw new Error('QA API did not start');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import {test} from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {mkdtempSync,writeFileSync,rmSync,existsSync} from 'node:fs';
|
||||
import {tmpdir} from 'node:os';
|
||||
import {join} from 'node:path';
|
||||
import {execFileSync} from 'node:child_process';
|
||||
test('failed shared-store initialization is retryable after storage is repaired',()=>{
|
||||
const dir=mkdtempSync(join(tmpdir(),'ihaleist-shared-recovery-'));
|
||||
try {
|
||||
writeFileSync(join(dir,'kalem.sqlite'),'not a sqlite database');
|
||||
execFileSync(process.execPath,['--input-type=module','-e',`
|
||||
import assert from 'node:assert/strict';
|
||||
import {rmSync} from 'node:fs';
|
||||
import {join} from 'node:path';
|
||||
const store=await import('./server/kalem-store.mjs');
|
||||
assert.throws(()=>store.kalemOku('2026/123'));
|
||||
rmSync(join(process.env.IHALEIST_SHARED_DATA_DIR,'kalem.sqlite'));
|
||||
assert.deepEqual(store.kalemOku('2026/123'),{kalemler:[],kaynak:null});
|
||||
assert.equal(store.kalemYaz('2026/123',[{ad:'QA tüp',miktar:2,birim:'adet'}]),1);
|
||||
assert.equal(store.kalemOku('2026/123').kalemler[0].ad,'QA tüp');
|
||||
`],{cwd:new URL('..',import.meta.url),env:{...process.env,IHALEIST_SHARED_DATA_DIR:dir},stdio:'pipe'});
|
||||
assert.equal(existsSync(join(dir,'kalem.sqlite')),true);
|
||||
} finally {rmSync(dir,{recursive:true,force:true});}
|
||||
});
|
||||
Reference in New Issue
Block a user