@comunica/actor-query-source-identify-hypermedia
Version:
A hypermedia query-source-identify actor
108 lines • 5.04 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.QuerySourceHypermedia = void 0;
const asynciterator_1 = require("asynciterator");
const lru_cache_1 = require("lru-cache");
const MediatedLinkedRdfSourcesAsyncRdfIterator_1 = require("./MediatedLinkedRdfSourcesAsyncRdfIterator");
class QuerySourceHypermedia {
referenceValue;
firstLink;
mediators;
dataFactory;
bindingsFactory;
/**
* A cache for source URLs to source states.
*/
sourcesState;
cacheSize;
maxIterators;
constructor(cacheSize, firstUrl, maxIterators, mediators, dataFactory, bindingsFactory) {
this.referenceValue = firstUrl.url;
this.cacheSize = cacheSize;
this.firstLink = firstUrl;
this.maxIterators = maxIterators;
this.mediators = mediators;
this.dataFactory = dataFactory;
this.bindingsFactory = bindingsFactory;
this.sourcesState = new lru_cache_1.LRUCache({ max: this.cacheSize });
}
async getSelectorShape(context) {
const source = await this.getSourceCached(this.firstLink, {}, context);
return source.source.getSelectorShape(context);
}
async getFilterFactor(context) {
const source = await this.getSourceCached(this.firstLink, {}, context);
return source.source.getFilterFactor(context);
}
queryBindings(operation, context, options) {
// Initialize the sources state on first call
if (this.sourcesState.size === 0) {
this.getSourceCached(this.firstLink, {}, context)
.catch(error => it.destroy(error));
}
const it = new MediatedLinkedRdfSourcesAsyncRdfIterator_1.MediatedLinkedRdfSourcesAsyncRdfIterator(operation, options, context, this.firstLink, this.maxIterators, (link, handledDatasets) => this.getSourceCached(link, handledDatasets, context), this.mediators.mediatorMetadataAccumulate, this.mediators.mediatorRdfResolveHypermediaLinks, this.mediators.mediatorRdfResolveHypermediaLinksQueue);
return it;
}
queryQuads(operation, context) {
return new asynciterator_1.TransformIterator(async () => {
const source = await this.getSourceCached(this.firstLink, {}, context);
return source.source.queryQuads(operation, context);
}, { autoStart: false });
}
async queryBoolean(operation, context) {
const source = await this.getSourceCached(this.firstLink, {}, context);
return await source.source.queryBoolean(operation, context);
}
async queryVoid(operation, context) {
const source = await this.getSourceCached(this.firstLink, {}, context);
return await source.source.queryVoid(operation, context);
}
/**
* Resolve a source for the given URL.
* @param link A source link.
* @param handledDatasets A hash of dataset identifiers that have already been handled.
* @param context The action context.
*/
async getSource(link, handledDatasets, context) {
const { source, metadata, cachePolicy } = await this.mediators.mediatorQuerySourceDereferenceLink.mediate({
link,
handledDatasets,
context,
});
return { link, source, metadata, handledDatasets, cachePolicy };
}
/**
* Resolve a source for the given URL.
* This will first try to retrieve the source from cache.
* @param link A source ILink.
* @param handledDatasets A hash of dataset identifiers that have already been handled.
* @param context The action context.
*/
getSourceCached(link, handledDatasets, context) {
let source = this.sourcesState.get(link.url);
if (source) {
return (async () => {
// Check if cache policy is still valid
const sourceMaterialized = await source;
if (sourceMaterialized.cachePolicy &&
!await sourceMaterialized.cachePolicy?.satisfiesWithoutRevalidation({ link, context })) {
// If it's not valid, delete cache entry, and re-fetch immediately
// LIMITATION: we're not sending re-validation requests. So if the server sends a 304, we will perform a new
// request and re-index the source. If an HTTP-level cache is active, the actual HTTP request will not be
// sent, so only local re-indexing will happen, which is negligible in most cases.
this.sourcesState.delete(link.url);
return this.getSourceCached(link, handledDatasets, context);
}
return sourceMaterialized;
})();
}
source = this.getSource(link, handledDatasets, context);
this.sourcesState.set(link.url, source);
return source;
}
toString() {
return `QuerySourceHypermedia(${this.firstLink.url})`;
}
}
exports.QuerySourceHypermedia = QuerySourceHypermedia;
//# sourceMappingURL=QuerySourceHypermedia.js.map