UNPKG

@snap/camera-kit

Version:
139 lines 7.42 kB
import { __awaiter } from "tslib"; import { Injectable } from "@snap/ts-inject"; import { dispatchRequestCompleted, dispatchRequestErrored, dispatchRequestStarted, requestStateEventTargetFactory, } from "../../handlers/requestStateEmittingHandler"; import { LensAssetManifestItem_RequestTiming, LensAssetManifestItem_Type, } from "../../generated-proto/pb_schema/camera_kit/v3/lens"; import { assertUnreachable } from "../../common/assertions"; import { getLogger } from "../../logger/logger"; import { metricsEventTargetFactory } from "../../metrics/metricsEventTarget"; import { TypedCustomEvent } from "../../events/TypedCustomEvent"; import { lensCoreFactory } from "../../lens-core-module/loader/lensCoreFactory"; import { deviceDependentAssetLoaderFactory } from "./deviceDependentAssetLoader"; import { remoteMediaAssetLoaderFactory } from "./remoteMediaAssetLoaderFactory"; import { staticAssetLoaderFactory } from "./staticAssetLoader"; const logger = getLogger("LensAssetRepository"); function getCacheKey(asset) { return `${asset.assetId}_${asset.assetType.value}`; } export function mapManfiestItemToAssetType(lensCore, type) { switch (type) { case LensAssetManifestItem_Type.ASSET: return lensCore.AssetType.Static; case LensAssetManifestItem_Type.DEVICE_DEPENDENT_ASSET_UNSET: case LensAssetManifestItem_Type.UNRECOGNIZED: return lensCore.AssetType.DeviceDependent; default: return assertUnreachable(type); } } export class LensAssetRepository { constructor(lensCore, assetLoaders, metrics, requestStateEventTarget) { this.lensCore = lensCore; this.assetLoaders = assetLoaders; this.metrics = metrics; this.requestStateEventTarget = requestStateEventTarget; this.cachedAssetKeys = new Set(); } cacheAssets(assetManifest, lens, assetTimings = [LensAssetManifestItem_RequestTiming.REQUIRED], lowPriority = false) { return __awaiter(this, void 0, void 0, function* () { const assetTimingsToPreload = new Set([ LensAssetManifestItem_RequestTiming.PRELOAD_UNSET, ...assetTimings, ]); const assetDescriptors = assetManifest .filter((asset) => { return assetTimingsToPreload.has(asset.requestTiming); }) .map(({ id, type }) => ({ assetId: id, assetType: mapManfiestItemToAssetType(this.lensCore, type), })); if (assetDescriptors.length) { return this.cacheAssetsByDescriptor(assetDescriptors, lens, assetManifest, lowPriority); } }); } loadAsset(request) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const { assetDescriptor: { assetId, assetType }, lens, } = request; const [assetTypeName, assetLoader] = (_a = this.assetLoaders.get(assetType)) !== null && _a !== void 0 ? _a : []; const safeAssetTypeName = assetTypeName !== null && assetTypeName !== void 0 ? assetTypeName : "unknown"; const dimensions = { requestType: "asset", assetId: assetId, assetType: safeAssetTypeName, lensId: (_b = lens === null || lens === void 0 ? void 0 : lens.id) !== null && _b !== void 0 ? _b : "unknown", }; const { requestId } = dispatchRequestStarted(this.requestStateEventTarget, { dimensions }); try { if (!assetLoader) { throw new Error(`Cannot get asset ${assetId}. Asset type ${safeAssetTypeName} is not supported.`); } const assetResponse = yield assetLoader(request); const assetBuffer = "data" in assetResponse ? assetResponse.data : assetResponse; const assetChecksum = "checksum" in assetResponse ? assetResponse.checksum : undefined; if (assetBuffer.byteLength === 0) { throw new Error(`Got empty response for asset ${assetId} from ${safeAssetTypeName} loader.`); } dispatchRequestCompleted(this.requestStateEventTarget, { requestId, dimensions, status: 200, sizeByte: assetBuffer.byteLength, }); this.lensCore.provideRemoteAssetsResponse({ assetId, assetBuffer, assetType, assetChecksum, onFailure: (lensCoreError) => { if (/validation failed/.test(lensCoreError.message)) { this.metrics.dispatchEvent(new TypedCustomEvent("assetValidationFailed", { name: "assetValidationFailed", assetId, })); } logger.warn(`Failed to provide lens asset ${assetId}.`, lensCoreError); }, }); } catch (error) { const wrappedError = new Error(`Failed to load lens asset ${assetId}.`, { cause: error }); dispatchRequestErrored(this.requestStateEventTarget, { requestId, dimensions, error: wrappedError }); throw wrappedError; } }); } cacheAssetsByDescriptor(assetDescriptors, lens, assetManifest, lowPriority) { return __awaiter(this, void 0, void 0, function* () { yield Promise.all(assetDescriptors .filter((assetDescriptors) => !this.cachedAssetKeys.has(getCacheKey(assetDescriptors))) .map((assetDescriptor) => __awaiter(this, void 0, void 0, function* () { var _a; try { yield this.loadAsset({ assetDescriptor, lens, assetManifest, lowPriority }); this.cachedAssetKeys.add(getCacheKey(assetDescriptor)); } catch (error) { const { assetId, assetType } = assetDescriptor; const [assetTypeName] = (_a = this.assetLoaders.get(assetType)) !== null && _a !== void 0 ? _a : []; logger.warn(`Failed to cache asset ${assetId} of type ${assetTypeName !== null && assetTypeName !== void 0 ? assetTypeName : assetType.value}.`, error); } }))); }); } } export const lensAssetRepositoryFactory = Injectable("lensAssetRepository", [ lensCoreFactory.token, deviceDependentAssetLoaderFactory.token, remoteMediaAssetLoaderFactory.token, staticAssetLoaderFactory.token, metricsEventTargetFactory.token, requestStateEventTargetFactory.token, ], (lensCore, deviceDependentAssetLoader, remoteMediaAssetLoader, staticAssetLoader, metrics, requestStateEventTarget) => new LensAssetRepository(lensCore, new Map([ [lensCore.AssetType.DeviceDependent, ["DeviceDependent", deviceDependentAssetLoader]], [lensCore.AssetType.RemoteMediaByUrl, ["RemoteMediaByUrl", remoteMediaAssetLoader]], [lensCore.AssetType.URL, ["URL", remoteMediaAssetLoader]], [lensCore.AssetType.Static, ["Static", staticAssetLoader]], ]), metrics, requestStateEventTarget)); //# sourceMappingURL=LensAssetRepository.js.map