[backport cloud/1.43] fix: use hash lookup for missing asset detection (#11873)#11891
[backport cloud/1.43] fix: use hash lookup for missing asset detection (#11873)#11891jaeone94 wants to merge 1 commit intocloud/1.43from
Conversation
Use exact BLAKE3 hash lookups first for missing model/media detection,
and add a separate public-inclusive input asset cache so public input
assets are considered missing-detection candidates without changing the
user-only input assets shown in the UI.
- **What**:
- Added `assetService.checkAssetHash()` for `HEAD
/api/assets/hash/{hash}` status-only existence checks.
- Added strict BLAKE3 hash helpers so only `blake3:<64 hex>` media
values and raw 64-hex BLAKE3 model metadata are sent to the hash
endpoint.
- Updated missing media detection to group BLAKE3 candidates by hash,
resolve them through the hash endpoint, and fall back to the legacy
asset list path for invalid/unverifiable/non-hash values.
- Updated missing model detection to use hash lookup for BLAKE3-backed
asset-supported candidates before falling back to the existing node-type
asset matching path.
- Added `assetService.getInputAssetsIncludingPublic()` backed by a
dedicated cache that fetches input assets with `include_public=true` for
missing media fallback checks.
- Kept `assetsStore.inputAssets` user-only for widget/UI display, while
invalidating the public-inclusive missing-detection cache when input
assets may change.
- Added abort handling for paginated asset fetches and shared
public-input cache callers so one aborted caller does not cancel the
shared fetch for other callers.
- Added regression coverage for hash lookup, fallback behavior, abort
paths, public input fallback detection, and cache invalidation.
- **Dependencies**: None.
- **Change size**:
- Production code: 4 files, 400 insertions, 24 deletions, net +376.
- Test code: 4 files, 806 insertions, 59 deletions, net +747.
- Total: 8 files, 1206 insertions, 83 deletions, net +1123.
- The public-inclusive input asset cache is intentionally separate from
`assetsStore.inputAssets`. The existing store data is user-only and
drives the asset widgets/sidebar, so using it for missing input
detection misses public assets. Making that store public-inclusive would
change UI data semantics; this PR instead keeps the UI dataset unchanged
and adds a missing-detection-specific cache in `assetService`.
- Hash lookup is only used when the workflow exposes a valid BLAKE3
hash. Filename-like values and invalid hash values still use the legacy
fallback path.
- Missing model detection keeps the existing fallback behavior for
non-hash candidates and for hash checks that are invalid or fail
transiently.
- Async model download cache refresh behavior is left unchanged; this PR
avoids coupling model download completion to input asset cache
invalidation.
- No browser/e2e test was added because this changes the missing asset
detection data path, not UI interaction or rendering. The behavioral
coverage is in unit tests for the asset service and the missing
media/model scanners.
- Fix `assetsStore.updateAssetTags()` partial-failure recovery. If
`removeAssetTags()` succeeds and `addAssetTags()` fails, the local model
asset cache can roll back to tags that the backend has already removed;
this should be handled in a focused model asset cache PR.
- Consider extracting shared hash-verification flow used by missing
media and missing model scans after this behavior stabilizes.
- Consider adding a concurrency cap or short-lived request cache for
large workflows with many unique hash lookups.
- Consider splitting `assetService.ts` further, e.g. hash helpers, abort
utilities, and the public-inclusive input asset cache.
- Consider tightening the asset hash service API shape so callers do not
directly depend on HTTP-oriented statuses such as `invalid`.
- Consider adding broader mutation-path coverage for public-inclusive
input cache invalidation once the cache has more consumers.
Linear: FE-534
Before <false positive / missing image / public asset>
https://github.com/user-attachments/assets/db7ce2a9-b169-4fae-bf9f-98bb93d3ee6d
After
https://github.com/user-attachments/assets/29af9f9e-b536-4fcd-a426-3add40bcb165
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11873-Use-hash-lookup-for-missing-asset-detection-3556d73d36508165babafb16614be0d8)
by [Unito](https://www.unito.io)
(cherry picked from commit 0491836)
|
Important Review skippedIgnore keyword(s) in the title. ⛔ Ignored keywords (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🎨 Storybook: ✅ Built — View Storybook |
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## cloud/1.43 #11891 +/- ##
=============================================
Coverage ? 44.89%
=============================================
Files ? 1348
Lines ? 69333
Branches ? 18404
=============================================
Hits ? 31124
Misses ? 37614
Partials ? 595
🚀 New features to boost your workflow:
|
📦 Bundle Size
⚡ Performance Report
No baseline found — showing absolute values.
Raw data{
"timestamp": "2026-05-04T07:01:18.973Z",
"gitSha": "0165b3b7a729ba8b35da62fc6d3e175a02ae3121",
"branch": "codex/backport-11873-cloud-1.43",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2016.9709999999554,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.771,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 372.95300000000003,
"heapDeltaBytes": 20291032,
"heapUsedBytes": 63343616,
"domNodes": 22,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 22.272,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "canvas-idle",
"durationMs": 2004.150999999979,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.177999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 355.086,
"heapDeltaBytes": 20698332,
"heapUsedBytes": 63701664,
"domNodes": 20,
"jsHeapTotalBytes": 22806528,
"scriptDurationMs": 23.929,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-idle",
"durationMs": 2020.3369999999268,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.017000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 379.216,
"heapDeltaBytes": 20333848,
"heapUsedBytes": 63359264,
"domNodes": 19,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 25.582,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1801.4179999999556,
"styleRecalcs": 74,
"styleRecalcDurationMs": 38.994,
"layouts": 12,
"layoutDurationMs": 3.2579999999999996,
"taskDurationMs": 737.126,
"heapDeltaBytes": 16629648,
"heapUsedBytes": 59667708,
"domNodes": 57,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 119.167,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1706.7409999999654,
"styleRecalcs": 72,
"styleRecalcDurationMs": 33.401,
"layouts": 12,
"layoutDurationMs": 3.279,
"taskDurationMs": 691.078,
"heapDeltaBytes": 16651480,
"heapUsedBytes": 59560600,
"domNodes": 55,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 116.27900000000001,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.799999999999727
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1715.494999999919,
"styleRecalcs": 72,
"styleRecalcDurationMs": 31.86,
"layouts": 12,
"layoutDurationMs": 3.2079999999999997,
"taskDurationMs": 682.721,
"heapDeltaBytes": 17991692,
"heapUsedBytes": 67085304,
"domNodes": 55,
"jsHeapTotalBytes": 24379392,
"scriptDurationMs": 119.08099999999999,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1728.859,
"styleRecalcs": 30,
"styleRecalcDurationMs": 16.953999999999997,
"layouts": 6,
"layoutDurationMs": 0.727,
"taskDurationMs": 332.12300000000005,
"heapDeltaBytes": 25078876,
"heapUsedBytes": 67931968,
"domNodes": 79,
"jsHeapTotalBytes": 20971520,
"scriptDurationMs": 29.401999999999997,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.799999999999727
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1746.6380000000754,
"styleRecalcs": 29,
"styleRecalcDurationMs": 16.853,
"layouts": 6,
"layoutDurationMs": 0.6689999999999999,
"taskDurationMs": 295.79100000000005,
"heapDeltaBytes": 25090024,
"heapUsedBytes": 67994696,
"domNodes": 77,
"jsHeapTotalBytes": 21233664,
"scriptDurationMs": 28.28900000000001,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1752.5410000000647,
"styleRecalcs": 31,
"styleRecalcDurationMs": 17.974999999999998,
"layouts": 6,
"layoutDurationMs": 0.725,
"taskDurationMs": 298.60200000000003,
"heapDeltaBytes": 25128372,
"heapUsedBytes": 68015320,
"domNodes": 79,
"jsHeapTotalBytes": 21233664,
"scriptDurationMs": 28.089000000000002,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 528.790000000015,
"styleRecalcs": 12,
"styleRecalcDurationMs": 10.993,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 314.06199999999995,
"heapDeltaBytes": 6765800,
"heapUsedBytes": 49564296,
"domNodes": 20,
"jsHeapTotalBytes": 13631488,
"scriptDurationMs": 60.51199999999999,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 570.8789999999908,
"styleRecalcs": 14,
"styleRecalcDurationMs": 10.289000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 356.21500000000003,
"heapDeltaBytes": -2555008,
"heapUsedBytes": 49247648,
"domNodes": 24,
"jsHeapTotalBytes": 17039360,
"scriptDurationMs": 67.07400000000001,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 556.3649999999143,
"styleRecalcs": 12,
"styleRecalcDurationMs": 9.019,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 319.08099999999996,
"heapDeltaBytes": 7653196,
"heapUsedBytes": 50502944,
"domNodes": 19,
"jsHeapTotalBytes": 12582912,
"scriptDurationMs": 59.054,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999727
},
{
"name": "large-graph-idle",
"durationMs": 2022.9870000000005,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.853,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 560.9269999999999,
"heapDeltaBytes": 4171940,
"heapUsedBytes": 55136100,
"domNodes": -257,
"jsHeapTotalBytes": 16969728,
"scriptDurationMs": 98.657,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-idle",
"durationMs": 2030.7279999999537,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.440000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 517.4929999999999,
"heapDeltaBytes": 5006160,
"heapUsedBytes": 56075576,
"domNodes": -260,
"jsHeapTotalBytes": 16445440,
"scriptDurationMs": 88.34400000000001,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2041.3369999999986,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.819,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 553.9079999999999,
"heapDeltaBytes": 17397696,
"heapUsedBytes": 69710428,
"domNodes": -256,
"jsHeapTotalBytes": 15192064,
"scriptDurationMs": 95.641,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2092.886999999962,
"styleRecalcs": 68,
"styleRecalcDurationMs": 15.402,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 964.437,
"heapDeltaBytes": -322744,
"heapUsedBytes": 53191004,
"domNodes": -261,
"jsHeapTotalBytes": 17698816,
"scriptDurationMs": 325.616,
"eventListeners": -123,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2117.6519999999073,
"styleRecalcs": 69,
"styleRecalcDurationMs": 15.524,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 968.18,
"heapDeltaBytes": 1910440,
"heapUsedBytes": 55305160,
"domNodes": -258,
"jsHeapTotalBytes": 17436672,
"scriptDurationMs": 324.553,
"eventListeners": -123,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2092.35799999999,
"styleRecalcs": 69,
"styleRecalcDurationMs": 16.240000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 979.0000000000001,
"heapDeltaBytes": 16250536,
"heapUsedBytes": 68298576,
"domNodes": -260,
"jsHeapTotalBytes": 17960960,
"scriptDurationMs": 336.082,
"eventListeners": -123,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3128.213999999957,
"styleRecalcs": 66,
"styleRecalcDurationMs": 18.072,
"layouts": 60,
"layoutDurationMs": 7.911999999999999,
"taskDurationMs": 1257.6580000000001,
"heapDeltaBytes": 7618224,
"heapUsedBytes": 62402640,
"domNodes": -262,
"jsHeapTotalBytes": 17494016,
"scriptDurationMs": 471.478,
"eventListeners": -123,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3103.8039999999683,
"styleRecalcs": 67,
"styleRecalcDurationMs": 17.864000000000004,
"layouts": 60,
"layoutDurationMs": 7.543,
"taskDurationMs": 1200.5370000000003,
"heapDeltaBytes": 7210488,
"heapUsedBytes": 61696408,
"domNodes": -259,
"jsHeapTotalBytes": 16969728,
"scriptDurationMs": 428.50100000000003,
"eventListeners": -123,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3051.296000000093,
"styleRecalcs": 65,
"styleRecalcDurationMs": 16.215000000000003,
"layouts": 60,
"layoutDurationMs": 7.779000000000001,
"taskDurationMs": 1204.099,
"heapDeltaBytes": 5864216,
"heapUsedBytes": 61743468,
"domNodes": -264,
"jsHeapTotalBytes": 16445440,
"scriptDurationMs": 437.531,
"eventListeners": -121,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2012.943000000007,
"styleRecalcs": 10,
"styleRecalcDurationMs": 7.856,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 462.08700000000005,
"heapDeltaBytes": 4300364,
"heapUsedBytes": 56992548,
"domNodes": -259,
"jsHeapTotalBytes": 15921152,
"scriptDurationMs": 78.04700000000001,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2027.5229999999738,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.073,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 553.899,
"heapDeltaBytes": 4453944,
"heapUsedBytes": 56996232,
"domNodes": -260,
"jsHeapTotalBytes": 15921152,
"scriptDurationMs": 95.771,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2039.6200000000135,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.262000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 547.0540000000001,
"heapDeltaBytes": 3728784,
"heapUsedBytes": 57943132,
"domNodes": -261,
"jsHeapTotalBytes": 16289792,
"scriptDurationMs": 89.179,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 570.5619999999954,
"styleRecalcs": 48,
"styleRecalcDurationMs": 11.996999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 334.64,
"heapDeltaBytes": 6436700,
"heapUsedBytes": 50815120,
"domNodes": 22,
"jsHeapTotalBytes": 13893632,
"scriptDurationMs": 115.53399999999999,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 525.8230000000594,
"styleRecalcs": 49,
"styleRecalcDurationMs": 12.005,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 329.02699999999993,
"heapDeltaBytes": 6520708,
"heapUsedBytes": 49860532,
"domNodes": 22,
"jsHeapTotalBytes": 13369344,
"scriptDurationMs": 110.016,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.669999999999998,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 520.7080000000133,
"styleRecalcs": 47,
"styleRecalcDurationMs": 10.841,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 322.774,
"heapDeltaBytes": 6158812,
"heapUsedBytes": 49441844,
"domNodes": 18,
"jsHeapTotalBytes": 13631488,
"scriptDurationMs": 108.551,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-idle",
"durationMs": 1997.507999999982,
"styleRecalcs": 13,
"styleRecalcDurationMs": 11.554000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 357.20700000000005,
"heapDeltaBytes": 20070112,
"heapUsedBytes": 62892068,
"domNodes": 25,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 21.224999999999994,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2012.8609999999298,
"styleRecalcs": 11,
"styleRecalcDurationMs": 8.841999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 337.102,
"heapDeltaBytes": 19999212,
"heapUsedBytes": 63162472,
"domNodes": 21,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 21.115000000000002,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-idle",
"durationMs": 2014.6270000000186,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.414,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 342.368,
"heapDeltaBytes": 20023576,
"heapUsedBytes": 63277004,
"domNodes": 21,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 20.462,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1683.3609999999908,
"styleRecalcs": 77,
"styleRecalcDurationMs": 35.429,
"layouts": 16,
"layoutDurationMs": 4.252,
"taskDurationMs": 619.1869999999999,
"heapDeltaBytes": 12206972,
"heapUsedBytes": 55393464,
"domNodes": 63,
"jsHeapTotalBytes": 23330816,
"scriptDurationMs": 92.703,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1683.6260000000038,
"styleRecalcs": 75,
"styleRecalcDurationMs": 33.935,
"layouts": 16,
"layoutDurationMs": 4.497999999999999,
"taskDurationMs": 606.644,
"heapDeltaBytes": 11896288,
"heapUsedBytes": 54747460,
"domNodes": 61,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 89.48599999999999,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666682,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1679.3480000000045,
"styleRecalcs": 76,
"styleRecalcDurationMs": 35.738,
"layouts": 16,
"layoutDurationMs": 4.527,
"taskDurationMs": 628.576,
"heapDeltaBytes": 2481844,
"heapUsedBytes": 54782244,
"domNodes": 63,
"jsHeapTotalBytes": 25427968,
"scriptDurationMs": 91.01800000000001,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "viewport-pan-sweep",
"durationMs": 8178.178000000003,
"styleRecalcs": 251,
"styleRecalcDurationMs": 46.607,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3583.256,
"heapDeltaBytes": 24053808,
"heapUsedBytes": 74771472,
"domNodes": -254,
"jsHeapTotalBytes": 19533824,
"scriptDurationMs": 1169.248,
"eventListeners": -107,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8166.287000000011,
"styleRecalcs": 250,
"styleRecalcDurationMs": 45.667,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3460.9030000000002,
"heapDeltaBytes": 22284092,
"heapUsedBytes": 73007808,
"domNodes": -256,
"jsHeapTotalBytes": 19271680,
"scriptDurationMs": 1064.6470000000002,
"eventListeners": -105,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8198.655000000032,
"styleRecalcs": 251,
"styleRecalcDurationMs": 46.142999999999994,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3678.086,
"heapDeltaBytes": 18292896,
"heapUsedBytes": 70283292,
"domNodes": -254,
"jsHeapTotalBytes": 18251776,
"scriptDurationMs": 1250.254,
"eventListeners": -121,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 11068.307000000004,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 11058.019999999999,
"heapDeltaBytes": -46819576,
"heapUsedBytes": 166011504,
"domNodes": -8331,
"jsHeapTotalBytes": 26828800,
"scriptDurationMs": 488.393,
"eventListeners": -16470,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333358,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 11191.173999999934,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 11179.646,
"heapDeltaBytes": -28007312,
"heapUsedBytes": 166496532,
"domNodes": -8333,
"jsHeapTotalBytes": 24993792,
"scriptDurationMs": 509.17400000000004,
"eventListeners": -16466,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333338,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 11447.639999999978,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 11434.122000000001,
"heapDeltaBytes": -32749476,
"heapUsedBytes": 166480880,
"domNodes": -8333,
"jsHeapTotalBytes": 25518080,
"scriptDurationMs": 512.386,
"eventListeners": -16470,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 12715.426999999978,
"styleRecalcs": 64,
"styleRecalcDurationMs": 14.920000000000016,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12697.470999999998,
"heapDeltaBytes": -10063192,
"heapUsedBytes": 185808608,
"domNodes": -8331,
"jsHeapTotalBytes": 24645632,
"scriptDurationMs": 704.6869999999999,
"eventListeners": -16461,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666763,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 12979.980999999952,
"styleRecalcs": 64,
"styleRecalcDurationMs": 15.41400000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12962.563999999998,
"heapDeltaBytes": -35069904,
"heapUsedBytes": 174856456,
"domNodes": -8329,
"jsHeapTotalBytes": 25956352,
"scriptDurationMs": 728.6290000000001,
"eventListeners": -16462,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333358,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 12883.185000000027,
"styleRecalcs": 64,
"styleRecalcDurationMs": 14.871999999999996,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12868.662000000002,
"heapDeltaBytes": -6288268,
"heapUsedBytes": 188033948,
"domNodes": -8329,
"jsHeapTotalBytes": 25956352,
"scriptDurationMs": 743.1260000000001,
"eventListeners": -16462,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 97.54800000007435,
"styleRecalcs": 10,
"styleRecalcDurationMs": 16.844,
"layouts": 4,
"layoutDurationMs": 1.6309999999999998,
"taskDurationMs": 78.987,
"heapDeltaBytes": 2865420,
"heapUsedBytes": 46854492,
"domNodes": 145,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 21.500999999999998,
"eventListeners": 37,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "workflow-execution",
"durationMs": 439.65800000000854,
"styleRecalcs": 19,
"styleRecalcDurationMs": 24.495,
"layouts": 5,
"layoutDurationMs": 1.3579999999999999,
"taskDurationMs": 109.69199999999998,
"heapDeltaBytes": 4375852,
"heapUsedBytes": 48436848,
"domNodes": 158,
"jsHeapTotalBytes": 262144,
"scriptDurationMs": 21.553,
"eventListeners": 71,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "workflow-execution",
"durationMs": 428.9330000000291,
"styleRecalcs": 17,
"styleRecalcDurationMs": 19.808,
"layouts": 5,
"layoutDurationMs": 1.3380000000000003,
"taskDurationMs": 101.14600000000002,
"heapDeltaBytes": 4386848,
"heapUsedBytes": 49830364,
"domNodes": 158,
"jsHeapTotalBytes": 262144,
"scriptDurationMs": 21.241999999999997,
"eventListeners": 69,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
}
]
} |
Manual backport of #11873 to
cloud/1.43.Cherry-picked squash merge commit
04918360ebcf69adffdf5d8ff6603c24c7a2809a.Why
#11873 moves missing asset detection to use exact BLAKE3 hash lookups first when a workflow exposes a valid hash, then falls back to the legacy asset-list matching path for non-hash, invalid, or transiently unverifiable candidates.
For media inputs, the legacy fallback now reads from a separate public-inclusive input asset cache in
assetServiceinstead of reusingassetsStore.inputAssets. That keeps the UI/widget asset list user-only while allowing missing input detection to account for public cloud assets loaded by templates, avoiding false-positive missing media on initial workflow load.Conflict resolution
src/platform/assets/services/assetService.test.ts:cloud/1.43only had the existingshouldUseAssetBrowsercoverage, while Use hash lookup for missing asset detection #11873 adds asset hash, upload validation, pagination, and public-inclusive input cache tests. Kept the Use hash lookup for missing asset detection #11873 test expansion; the existing test coverage is preserved in the incoming file.src/stores/assetsStore.test.ts: expanded the mockedassetServicesurface and kept Use hash lookup for missing asset detection #11873's appended store tests for asset metadata/tag updates, deletion state, input name mapping, and input cache invalidation. The runtimeassetsStore.tschanges auto-merged cleanly.Validation
pnpm test:unit -- run src/platform/assets/services/assetService.test.ts src/stores/assetsStore.test.ts✅ (91/91 passing)pnpm typecheck✅pnpm exec oxfmt --check src/platform/assets/services/assetService.ts src/platform/assets/services/assetService.test.ts src/platform/missingMedia/missingMediaScan.ts src/platform/missingMedia/missingMediaScan.test.ts src/platform/missingModel/missingModelScan.ts src/platform/missingModel/missingModelScan.test.ts src/stores/assetsStore.ts src/stores/assetsStore.test.ts✅git diff --check✅oxfmt,oxlint,eslint, andpnpm typecheckon the changed files ✅pnpm knip --cache✅Original PR: #11873
Original commit:
04918360ebcf69adffdf5d8ff6603c24c7a2809a┆Issue is synchronized with this Notion page by Unito