This commit is contained in:
@@ -594,6 +594,9 @@
|
||||
<button class="market-intel-icon-button" type="button" title="檢查 queue writer preflight" data-market-intel-sample-candidate-queue-preflight>
|
||||
<i class="fas fa-database" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button class="market-intel-icon-button" type="button" title="檢查 queue writer post-write smoke" data-market-intel-sample-candidate-queue-postwrite-smoke>
|
||||
<i class="fas fa-search" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -924,6 +927,7 @@
|
||||
const sampleCandidateQueueTransaction = sampleReviewRoot ? sampleReviewRoot.querySelector('[data-market-intel-sample-candidate-queue-transaction]') : null;
|
||||
const sampleCandidateQueueWriter = sampleReviewRoot ? sampleReviewRoot.querySelector('[data-market-intel-sample-candidate-queue-writer]') : null;
|
||||
const sampleCandidateQueuePreflight = sampleReviewRoot ? sampleReviewRoot.querySelector('[data-market-intel-sample-candidate-queue-preflight]') : null;
|
||||
const sampleCandidateQueuePostwriteSmoke = sampleReviewRoot ? sampleReviewRoot.querySelector('[data-market-intel-sample-candidate-queue-postwrite-smoke]') : null;
|
||||
const sampleReviewEndpoint = "{{ url_for('market_intel.market_intel_manual_sample_review') }}";
|
||||
const sampleReviewEvaluateEndpoint = "{{ url_for('market_intel.market_intel_manual_sample_review_evaluate') }}";
|
||||
const sampleCandidateHandoffEndpoint = "{{ url_for('market_intel.market_intel_manual_sample_candidate_handoff') }}";
|
||||
@@ -932,6 +936,7 @@
|
||||
const sampleCandidateQueueTransactionEndpoint = "{{ url_for('market_intel.market_intel_manual_sample_candidate_queue_transaction') }}";
|
||||
const sampleCandidateQueueWriterEndpoint = "{{ url_for('market_intel.market_intel_manual_sample_candidate_queue_writer_status') }}";
|
||||
const sampleCandidateQueuePreflightEndpoint = "{{ url_for('market_intel.market_intel_manual_sample_candidate_queue_writer_preflight') }}";
|
||||
const sampleCandidateQueuePostwriteSmokeEndpoint = "{{ url_for('market_intel.market_intel_manual_sample_candidate_queue_writer_postwrite_smoke') }}";
|
||||
const schedulerMeta = schedulerRoot ? schedulerRoot.querySelector('[data-market-intel-scheduler-meta]') : null;
|
||||
const schedulerBody = schedulerRoot ? schedulerRoot.querySelector('[data-market-intel-scheduler-body]') : null;
|
||||
const schedulerRefresh = schedulerRoot ? schedulerRoot.querySelector('[data-market-intel-scheduler-refresh]') : null;
|
||||
@@ -2389,6 +2394,67 @@
|
||||
}
|
||||
};
|
||||
|
||||
const renderCandidateQueuePostwriteSmoke = data => {
|
||||
const blockers = (data.blocked_reasons || []).join(' / ');
|
||||
const found = data.found_dedupe_keys || [];
|
||||
const missing = data.missing_dedupe_keys || [];
|
||||
sampleReviewMeta.innerHTML = [
|
||||
`mode=${data.mode || 'unknown'}`,
|
||||
`passed=${data.postwrite_smoke_passed ? 'yes' : 'no'}`,
|
||||
`expected=${data.expected_dedupe_key_count || 0}`,
|
||||
`found=${data.found_count || 0}`,
|
||||
`missing=${data.missing_count || 0}`
|
||||
].map(item => `<span class="market-intel-pill">${escapeHtml(item)}</span>`).join('');
|
||||
sampleReviewBody.innerHTML = `
|
||||
<div class="market-intel-empty mb-3">此卡只做 CLI 寫入後的 queue row 只讀驗證;頁面預設不連 DB、不寫 queue。${blockers ? `阻擋:${escapeHtml(blockers)}` : ''}</div>
|
||||
<div class="market-intel-operation-list">
|
||||
<article class="market-intel-operation">
|
||||
<strong>found dedupe keys</strong>
|
||||
<small>${escapeHtml(found.join(', ') || 'none')}</small>
|
||||
</article>
|
||||
<article class="market-intel-operation">
|
||||
<strong>missing dedupe keys</strong>
|
||||
<small>${escapeHtml(missing.join(', ') || 'none')}</small>
|
||||
</article>
|
||||
<article class="market-intel-operation">
|
||||
<strong>read-only status</strong>
|
||||
<small>query=${data.read_only_query_executed ? 'yes' : 'no'} / write=${data.database_write_executed ? 'yes' : 'no'} / commit=${data.database_commit_executed ? 'yes' : 'no'}</small>
|
||||
</article>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
|
||||
const loadCandidateQueuePostwriteSmoke = async () => {
|
||||
if (!sampleReviewMeta || !sampleReviewBody || !sampleReviewInput) return;
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(sampleReviewInput.value || '{}');
|
||||
} catch (error) {
|
||||
sampleReviewMeta.innerHTML = '<span class="market-intel-pill">json_error</span>';
|
||||
sampleReviewBody.innerHTML = `<div class="market-intel-empty">JSON 格式錯誤:${escapeHtml(error.message)}</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
sampleReviewBody.innerHTML = '<div class="market-intel-empty">檢查 queue writer post-write smoke 中...</div>';
|
||||
try {
|
||||
const response = await fetch(sampleCandidateQueuePostwriteSmokeEndpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
body: JSON.stringify({ sample_result: parsed })
|
||||
});
|
||||
const data = await response.json();
|
||||
if (!response.ok && !data.mode) throw new Error(`HTTP ${response.status}`);
|
||||
renderCandidateQueuePostwriteSmoke(data);
|
||||
} catch (error) {
|
||||
sampleReviewMeta.innerHTML = '<span class="market-intel-pill">error</span>';
|
||||
sampleReviewBody.innerHTML = `<div class="market-intel-empty">queue writer post-write smoke 檢查失敗:${escapeHtml(error.message)}</div>`;
|
||||
}
|
||||
};
|
||||
|
||||
const renderSchedulerMeta = data => {
|
||||
schedulerMeta.innerHTML = [
|
||||
`mode=${data.mode || 'unknown'}`,
|
||||
@@ -3901,6 +3967,9 @@
|
||||
if (sampleCandidateQueuePreflight) {
|
||||
sampleCandidateQueuePreflight.addEventListener('click', loadCandidateQueuePreflight);
|
||||
}
|
||||
if (sampleCandidateQueuePostwriteSmoke) {
|
||||
sampleCandidateQueuePostwriteSmoke.addEventListener('click', loadCandidateQueuePostwriteSmoke);
|
||||
}
|
||||
if (schedulerRefresh) {
|
||||
schedulerRefresh.addEventListener('click', loadScheduler);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user