@paroicms/server-image-cache-engine
Version:
The image variant engine that we use at Paroi.
122 lines • 4.98 kB
JavaScript
import { completeInput, makeOwnerKey } from "../internal/utils.js";
import { makeBatchOfImagesAvailable } from "./owner-batch.js";
import { promiseToHandleSafely } from "./owner-utils.js";
export async function makeTransactionImageAvailable(otContext, inputs, { optimizeForBatch, }) {
const { engineContext, ownerHandle, canBeRetrievedByOwner, localCache } = otContext;
const completedInputs = inputs.map(completeInput);
let unresolvedInputs = completedInputs.filter((input) => !localCache.has(input.taskKey));
const pendingVariants = new Map();
for (const input of unresolvedInputs) {
const pt = engineContext.pendingTasks.get(input.taskKey);
if (pt) {
pt.task.owners.set(ownerHandle, { ownerHandle, rawResizeR: input.rawResizeR });
pendingVariants.set(input.taskKey, pt.task.variant);
if (canBeRetrievedByOwner) {
pt.ownerKeys.add(makeOwnerKey({
mediaId: input.sourceImage.mediaId,
mediaType: input.requestedVariant.mediaType,
ownerHandle,
rawResizeR: input.rawResizeR,
}));
}
}
}
unresolvedInputs = unresolvedInputs.filter((input) => !pendingVariants.has(input.taskKey));
if (unresolvedInputs.length > 0) {
const unresolvedTaskKeys = new Set(unresolvedInputs.map((i) => i.taskKey));
let augmentedInputs = unresolvedInputs;
if (optimizeForBatch) {
const newItems = optimizeForBatch
.getMoreInputsForBatch((candidate) => {
return unresolvedTaskKeys.has(completeInput(candidate).taskKey);
})
.map(completeInput);
augmentedInputs = augmentedInputs.concat(newItems);
}
await makeBatchOfImagesAvailable(otContext, augmentedInputs);
}
createTasksAndCollectImageOwners(otContext, completedInputs, canBeRetrievedByOwner);
return completedInputs.map((input) => {
const pending = pendingVariants.get(input.taskKey);
if (pending)
return pending;
const v = localCache.get(input.taskKey);
if (!v) {
throw new Error(`Missing image variant for task "${input.taskKey}" (ownerHandle: ${ownerHandle})`);
}
v.usedBy = input;
return v.variant;
});
}
function createTasksAndCollectImageOwners(otContext, completedInputs, canBeRetrievedByOwner) {
const { startQueue } = otContext;
let hasCreatedTask = false;
for (const input of completedInputs) {
const taskCreated = processImageInput(otContext, input, canBeRetrievedByOwner);
if (taskCreated) {
hasCreatedTask = true;
}
}
if (hasCreatedTask) {
startQueue();
}
}
/**
* @returns `true` if a new task was created.
*/
function processImageInput(otContext, input, canBeRetrievedByOwner) {
const { engineContext, ownerHandle } = otContext;
const cacheItem = otContext.localCache.get(input.taskKey);
if (!cacheItem)
return false;
const { stored } = cacheItem;
if (stored) {
// Item is already stored - always add to owner image manager to ensure it's not
// deleted during the replacement phase in associateOwnerToImages.
// Even if already owned, we must include it in the new set of images.
otContext.ownerImageManager.add(stored.imageCacheId, input.rawResizeR);
return false;
}
// Item needs a task - check if task already exists
const pending = engineContext.pendingTasks.get(input.taskKey);
if (pending) {
pending.task.owners.set(ownerHandle, { ownerHandle, rawResizeR: input.rawResizeR });
if (canBeRetrievedByOwner) {
const ownerKey = makeOwnerKey({
mediaId: input.sourceImage.mediaId,
mediaType: input.requestedVariant.mediaType,
ownerHandle,
rawResizeR: input.rawResizeR,
});
pending.ownerKeys.add(ownerKey);
}
return false;
}
// Create new task
const ownerKey = canBeRetrievedByOwner
? makeOwnerKey({
mediaId: input.sourceImage.mediaId,
mediaType: input.requestedVariant.mediaType,
ownerHandle,
rawResizeR: input.rawResizeR,
})
: undefined;
const task = {
variant: cacheItem.variant,
input,
owners: new Map([[ownerHandle, { ownerHandle, rawResizeR: input.rawResizeR }]]),
};
const pendingTask = {
...promiseToHandleSafely(),
task,
ownerKeys: new Set(),
};
engineContext.queue.push(input.taskKey);
engineContext.pendingTasks.set(input.taskKey, pendingTask);
if (ownerKey) {
pendingTask.ownerKeys.add(ownerKey);
engineContext.pendingTaskByOwnerKeys.set(ownerKey, pendingTask);
}
return true;
}
//# sourceMappingURL=make-t-image-available.js.map