7
ci / docker (backend, backend/Dockerfile, backend) (push) Successful in 12m50s
ci / docker (frontend, frontend/Dockerfile, frontend) (push) Successful in 12m49s

This commit is contained in:
2025-10-14 02:43:38 +02:00
parent c17a9484ca
commit 9aa43d2753
5 changed files with 183 additions and 298 deletions
+22 -53
View File
@@ -17,14 +17,34 @@ export const getAssetFromVersion = (currentVersion, assetType) => {
return getAssetFromGroup(currentVersion.assets, assetType);
};
export const resolveDocumentAssetUrl = (doc, type, { ensureAssetUrl, getAsset, ensureOptions } = {}) => {
if (!doc || !type) {
return null;
}
const asset = typeof getAsset === 'function' ? getAsset(doc, type) : null;
if (!asset) {
return null;
}
const now = Date.now();
const expiresAt = typeof asset.expiresAt === 'number' ? asset.expiresAt : null;
const hasFreshUrl = asset.url && (!expiresAt || expiresAt > now);
if (hasFreshUrl) {
return asset.url;
}
if (doc.id && asset.id && typeof ensureAssetUrl === 'function') {
const force = Boolean(asset.url && expiresAt && expiresAt <= now);
const options = ensureOptions ? { ...ensureOptions, force } : { force };
ensureAssetUrl(doc.id, asset, options).catch(() => {});
}
return null;
};
class AssetManager {
constructor({ api, assetPresignTtlMs }) {
this.api = api;
this.assetPresignTtlMs = assetPresignTtlMs;
this.assetCache = new Map();
this.assetInflight = new Map();
this.previewCache = new Map();
this.previewInflight = new Map();
}
setApi(api) {
@@ -197,60 +217,9 @@ class AssetManager {
return request;
}
ensurePreview(documentId, { force = false } = {}) {
if (!documentId) {
return Promise.resolve(null);
}
const cached = this.previewCache.get(documentId);
const now = Date.now();
if (!force && cached && (!cached.expiresAt || cached.expiresAt > now)) {
return Promise.resolve(cached);
}
if (!force && this.previewInflight.has(documentId)) {
return this.previewInflight.get(documentId);
}
if (!this.api) {
return Promise.reject(new Error('AssetManager API client is not configured.'));
}
const request = this.api
.get(`/documents/${documentId}/download`)
.then(({ data }) => {
const ttl = data.expires_in ? Math.max(data.expires_in - 60, 30) * 1000 : 5 * 60 * 1000;
const entry = {
url: data.url,
contentType: data.content_type || null,
filename: data.filename,
expiresAt: Date.now() + ttl,
};
this.previewCache.set(documentId, entry);
return entry;
})
.finally(() => {
this.previewInflight.delete(documentId);
});
this.previewInflight.set(documentId, request);
return request;
}
getPreview(documentId) {
return this.previewCache.get(documentId) || null;
}
deleteDocument(documentId) {
if (!documentId) return;
this.previewCache.delete(documentId);
this.previewInflight.delete(documentId);
}
reset() {
this.assetCache.clear();
this.assetInflight.clear();
this.previewCache.clear();
this.previewInflight.clear();
}
}