Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 45 additions & 43 deletions tx/ocl/cs-ocl.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class OCLCodeSystemProvider extends AbstractCodeSystemProvider {
this._pendingChanges = null;
this._initialized = false;
this._initializePromise = null;
this._organizationIdsCache = null;
this._organizationIdsFetchPromise = null;
}

async initialize() {
Expand Down Expand Up @@ -206,35 +208,54 @@ class OCLCodeSystemProvider extends AbstractCodeSystemProvider {
}

async #fetchOrganizationIds() {
const endpoint = '/orgs/';
const orgs = await this.#fetchAllPages(endpoint);
// Return cached result if available
if (this._organizationIdsCache) {
return this._organizationIdsCache;
}

const ids = [];
const seen = new Set();
for (const org of orgs || []) {
if (!org || typeof org !== 'object') {
continue;
}
// Deduplicate concurrent requests
if (this._organizationIdsFetchPromise) {
return this._organizationIdsFetchPromise;
}

const id = org.id || org.mnemonic || org.short_code || org.shortCode || org.name || null;
if (!id) {
continue;
this._organizationIdsFetchPromise = (async () => {
const endpoint = '/orgs/';
const orgs = await this.#fetchAllPages(endpoint);

const ids = [];
const seen = new Set();
for (const org of orgs || []) {
if (!org || typeof org !== 'object') {
continue;
}

const id = org.id || org.mnemonic || org.short_code || org.shortCode || org.name || null;
if (!id) {
continue;
}

const normalized = String(id).trim();
if (!normalized || seen.has(normalized)) {
continue;
}

seen.add(normalized);
ids.push(normalized);
}

const normalized = String(id).trim();
if (!normalized || seen.has(normalized)) {
continue;
if (ids.length === 0 && this.org) {
ids.push(this.org);
}

seen.add(normalized);
ids.push(normalized);
}
this._organizationIdsCache = ids;
return ids;
})();

if (ids.length === 0 && this.org) {
ids.push(this.org);
try {
return await this._organizationIdsFetchPromise;
} finally {
this._organizationIdsFetchPromise = null;
}

return ids;
}

#sourceIdentity(source) {
Expand Down Expand Up @@ -998,7 +1019,7 @@ class OCLSourceCodeSystemProvider extends CodeSystemProvider {
const pending = (async () => {
let response;
try {
response = await this.httpClient.get(url);
response = await this.httpClient.get(url, { params: { verbose: true } });
} catch (error) {
// Missing concept should be treated as not-found, not as an internal server failure.
if (error && error.response && error.response.status === 404) {
Expand Down Expand Up @@ -1302,7 +1323,6 @@ class OCLSourceCodeSystemFactory extends CodeSystemFactoryProvider {

this.#applyConceptsToCodeSystemResource(this.meta?.codeSystem || null);

console.log(`[OCL] Loaded CodeSystem from cold cache: ${canonicalUrl} (${cached.concepts.length} concepts, fingerprint=${this.customFingerprint?.substring(0, 8)})`);
} catch (error) {
if (error.code !== 'ENOENT') {
console.error(`[OCL] Failed to load cold cache for CodeSystem ${canonicalUrl}:`, error.message);
Expand All @@ -1329,7 +1349,6 @@ class OCLSourceCodeSystemFactory extends CodeSystemFactoryProvider {
};

await fs.writeFile(cacheFilePath, JSON.stringify(cacheData, null, 2), 'utf-8');
console.log(`[OCL] Saved CodeSystem to cold cache: ${canonicalUrl} (${concepts.length} concepts, fingerprint=${fingerprint?.substring(0, 8)})`);

return fingerprint;
} catch (error) {
Expand All @@ -1343,7 +1362,6 @@ class OCLSourceCodeSystemFactory extends CodeSystemFactoryProvider {
const key = `${normalizedSystem}|${version || ''}`;
const factory = OCLSourceCodeSystemFactory.#findFactory(normalizedSystem, version);
if (!factory) {
console.log(`[OCL] CodeSystem load not scheduled (factory unavailable): ${key}`);
return false;
}
factory.scheduleBackgroundLoad(reason);
Expand Down Expand Up @@ -1412,20 +1430,17 @@ class OCLSourceCodeSystemFactory extends CodeSystemFactoryProvider {
}

if (cacheAgeMs != null && cacheAgeMs < COLD_CACHE_FRESHNESS_MS) {
console.log(`[OCL] Skipping warm-up for CodeSystem ${this.system()} (cold cache age: ${formatCacheAgeMinutes(cacheAgeMs)})`);
return;
}

const key = this.#resourceKey();
const jobKey = `cs:${key}`;

if (OCLBackgroundJobQueue.isQueuedOrRunning(jobKey)) {
console.log(`[OCL] CodeSystem load already queued or running: ${key}`);
return;
}

let queuedJobSize = null;
console.log(`[OCL] CodeSystem load enqueued: ${key} (${reason})`);
OCLBackgroundJobQueue.enqueue(
jobKey,
'CodeSystem load',
Expand All @@ -1444,7 +1459,6 @@ class OCLSourceCodeSystemFactory extends CodeSystemFactoryProvider {
}

async #runBackgroundLoad(key, knownConceptCount = null) {
console.log(`[OCL] CodeSystem load started: ${key}`);
try {
this.backgroundLoadProgress = { processed: 0, total: null };
const resolvedTotal = Number.isFinite(knownConceptCount) && knownConceptCount >= 0
Expand All @@ -1470,27 +1484,15 @@ class OCLSourceCodeSystemFactory extends CodeSystemFactoryProvider {
const allConcepts = Array.from(this.sharedConceptCache.values());
const newFingerprint = computeCodeSystemFingerprint(allConcepts);

if (this.customFingerprint && newFingerprint === this.customFingerprint) {
console.log(`[OCL] CodeSystem fingerprint unchanged: ${key} (fingerprint=${newFingerprint?.substring(0, 8)})`);
} else {
if (this.customFingerprint) {
console.log(`[OCL] CodeSystem fingerprint changed: ${key} (${this.customFingerprint?.substring(0, 8)} -> ${newFingerprint?.substring(0, 8)})`);
console.log(`[OCL] Replacing cold cache with new hot cache: ${key}`);
} else {
console.log(`[OCL] Computed fingerprint for CodeSystem: ${key} (fingerprint=${newFingerprint?.substring(0, 8)})`);
}

if (!this.customFingerprint || newFingerprint !== this.customFingerprint) {
// Save to cold cache
const savedFingerprint = await this.#saveColdCache(allConcepts);
if (savedFingerprint) {
this.customFingerprint = savedFingerprint;
}
}

console.log(`[OCL] CodeSystem load completed, marked content=complete: ${key}`);
const progress = OCLSourceCodeSystemFactory.loadProgress();
console.log(`[OCL] CodeSystem load completed: ${this.system()}. Loaded ${progress.loaded}/${progress.total} CodeSystems (${progress.percentage.toFixed(2)}%)`);
console.log(`[OCL] CodeSystem now available in cache: ${key} (${count} concepts)`);
console.log(`[OCL] CodeSystem loaded: ${this.system()} (${count} concepts)`);
} catch (error) {
console.error(`[OCL] CodeSystem background load failed: ${key}: ${error.message}`);
}
Expand Down
8 changes: 0 additions & 8 deletions tx/ocl/jobs/background-queue.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class OCLBackgroundJobQueue {
};
this.#insertPendingJobOrdered(job);
this.ensureHeartbeatRunning();
console.log(`[OCL] ${jobType || 'Background job'} enqueued: ${jobKey} (size=${normalizedSize}, queue=${this.pendingJobs.length}, active=${this.activeCount})`);
this.processNext();
};

Expand Down Expand Up @@ -77,7 +76,6 @@ class OCLBackgroundJobQueue {
// Prioridade máxima para userRequested
if (job.userRequested) {
this.pendingJobs.unshift(job);
console.log(`[OCL] User-requested job prioritized: ${job.jobKey}`);
return;
}
let index = this.pendingJobs.findIndex(existing => {
Expand Down Expand Up @@ -179,13 +177,8 @@ class OCLBackgroundJobQueue {
getProgress: job.getProgress || null,
startedAt: Date.now()
});
console.log(`[OCL] Background job started: ${job.jobType} ${job.jobKey} (size=${job.jobSize}, queue=${this.pendingJobs.length}, active=${this.activeCount})`);

Promise.resolve()
.then(() => job.runJob())
.then(() => {
console.log(`[OCL] Background job completed: ${job.jobType} ${job.jobKey}`);
})
.catch((error) => {
const message = error && error.message ? error.message : String(error);
console.error(`[OCL] Background job failed: ${job.jobType} ${job.jobKey}: ${message}`);
Expand All @@ -194,7 +187,6 @@ class OCLBackgroundJobQueue {
this.activeCount -= 1;
this.queuedOrRunningKeys.delete(job.jobKey);
this.activeJobs.delete(job.jobKey);
console.log(`[OCL] Background queue status: queue=${this.pendingJobs.length}, active=${this.activeCount}`);
this.processNext();
});
}
Expand Down
Loading
Loading