add persistent readiness health check
This commit is contained in:
@@ -32,7 +32,7 @@ jobs:
|
||||
cleanup() { docker rm -f "$cid" >/dev/null 2>&1 || true; }
|
||||
trap cleanup EXIT
|
||||
for attempt in $(seq 1 30); do
|
||||
if curl --fail --silent http://127.0.0.1:18080/api/health; then exit 0; fi
|
||||
if curl --fail --silent http://127.0.0.1:18080/api/ready; then exit 0; fi
|
||||
sleep 1
|
||||
done
|
||||
echo 'Container health endpoint did not become ready' >&2
|
||||
|
||||
@@ -2085,4 +2085,10 @@ Docker runtime image’ında backend’in kullandığı ortak `src/` klasörün
|
||||
|
||||
### 2026-09-06 · CI kalite kapıları
|
||||
|
||||
GitHub Actions iş akışı eklendi. Her push ve pull request’te test/üretim derlemesi; ayrıca Docker image build’i, nginx yapılandırma testi ve `/api/health` çalışma zamanı kontrolü otomatik çalışacak. Bu iş akışı gerçek production rollout kanıtının yerine geçmez.
|
||||
GitHub Actions iş akışı eklendi. Her push ve pull request’te test/üretim derlemesi; ayrıca Docker image build’i, nginx yapılandırma testi ve `/api/ready` çalışma zamanı kontrolü otomatik çalışacak. Bu iş akışı gerçek production rollout kanıtının yerine geçmez.
|
||||
|
||||
### 2026-09-06 · Production readiness endpoint’i
|
||||
|
||||
`/api/ready` eklendi. `/api/health` süreç canlılığını korurken readiness kontrolü kullanıcı ve ortak veri dizinlerini gerektiğinde oluşturup okuma/yazma erişimini doğruluyor; başarısızlıkta HTTP 503 ve hangi kontrolün kaldığını döndürüyor. CI container kontrolü artık bu endpoint’i kullanıyor.
|
||||
|
||||
Doğrulama: HTTP readiness testi geçti; toplam test ve build doğrulaması CI’da çalışacak.
|
||||
|
||||
@@ -75,6 +75,26 @@ const PORT = process.env.PORT || 3001;
|
||||
const ILAN_BASE = 'https://www.ilan.gov.tr';
|
||||
const CORS_ORIGINS = String(process.env.CORS_ORIGINS || '').split(',').map(value => value.trim()).filter(Boolean);
|
||||
|
||||
function readiness() {
|
||||
const directories = {
|
||||
userData: process.env.IHALEIST_USER_DATA_DIR || path.join(__dirname, 'data'),
|
||||
sharedData: process.env.IHALEIST_SHARED_DATA_DIR || path.join(__dirname, 'data'),
|
||||
};
|
||||
const checks = {};
|
||||
let ready = true;
|
||||
for (const [name, directory] of Object.entries(directories)) {
|
||||
try {
|
||||
fs.mkdirSync(directory, { recursive: true });
|
||||
fs.accessSync(directory, fs.constants.R_OK | fs.constants.W_OK);
|
||||
checks[name] = { ok: true };
|
||||
} catch (error) {
|
||||
ready = false;
|
||||
checks[name] = { ok: false, error: error.code || 'EACCES' };
|
||||
}
|
||||
}
|
||||
return { ready, checks };
|
||||
}
|
||||
|
||||
function validateHealthPortfolio(value) {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Firma profili geçersiz.');
|
||||
const portfolio = value.scrapedCapabilities?.healthPortfolio;
|
||||
@@ -1700,6 +1720,10 @@ const server = http.createServer(async (req, res) => {
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/health') return json(res, 200, { ok: true });
|
||||
if (url.pathname === '/api/ready') {
|
||||
const status = readiness();
|
||||
return json(res, status.ready ? 200 : 503, { ok: status.ready, ...status });
|
||||
}
|
||||
if (url.pathname === '/api/health/sektor') {
|
||||
const say = sektorZenginSayi();
|
||||
const genel = (cache.tenders || []).filter((t) => t.sektor === 'Genel').length;
|
||||
|
||||
@@ -47,6 +47,14 @@ test('HTTP preparation requires auth, persists draft and rejects stale revisions
|
||||
assert.equal((await request('/api/me/tender-state','PUT',data)).status,409);
|
||||
assert.deepEqual((await request('/api/me/tender-state','GET',null,other)).data.records,{});
|
||||
});
|
||||
test('readiness endpoint checks persistent data directories',async()=>{
|
||||
const response=await request('/api/ready','GET',null,null);
|
||||
assert.equal(response.status,200);
|
||||
assert.equal(response.data.ok,true);
|
||||
assert.equal(response.data.ready,true);
|
||||
assert.equal(response.data.checks.userData.ok,true);
|
||||
assert.equal(response.data.checks.sharedData.ok,true);
|
||||
});
|
||||
test('HTTP documents and API keys expose empty successful state, not endless load errors',async()=>{
|
||||
const docs=await request('/api/me/documents');assert.equal(docs.status,200);assert.deepEqual(docs.data.belgeler,[]);
|
||||
const keys=await request('/api/me/apikeys');assert.equal(keys.status,200);assert.deepEqual(keys.data.anahtarlar,[]);
|
||||
|
||||
Reference in New Issue
Block a user