Fingerprint frame layer previews - #427
Conversation
Deploying geodatalytics with
|
| Latest commit: |
390d799
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://2d2c5446.geodatalytics.pages.dev |
| Branch Preview URL: | https://fingerprint-frame-layer-prev.geodatalytics.pages.dev |
a201d66 to
bfcc7a3
Compare
423311a to
80aac5a
Compare
annehaley
left a comment
There was a problem hiding this comment.
As with #397, I'll probably do a few rounds of review on this. My first pass is more focused on server-side, I'll test it locally and take a closer look at client-side on my next pass.
Could you rebase this and ensure that your commit messages have semantic prefixes? Without them, a release won't be made upon merge.
| # Prefer a project that already includes this dataset so the analytics | ||
| # WebSocket (project-scoped) receives completion. Conversion-time tasks | ||
| # before a project link still fall back to the conversion channel. |
There was a problem hiding this comment.
If a frame preview generation task occurs as a consequence of a dataset conversion, we should run the generation synchronously within the conversion task so the conversion only appears complete once the previews are ready too (the same way you did for the flood simulation task).
There was a problem hiding this comment.
I don't think this is the correct referenced lines for this comment. But I made it so that any preview generation task started by the core/tasts/dataset.py and specifically create_layers_and_frames will default to using run_mode=Task.SYNC inside of the invalidate_and_enqueue_layer_previews so it will run inside of the current task instead of starting a new task.
I also fixed some bad merge history in the _dispatch_frame_preview_task function that was duplicating some functions.
Done in : 9b32957
There was a problem hiding this comment.
I had left this comment here because running the preview generation task synchronously within the dataset conversion task means that we don't need to pick an arbitrary project to associate with the task. The dataset conversion tasks are intentionally not associated with any project. If we spawn a preview generation task because a style object is updated, we can use the style's project.
Is there some other case wherein we need to pick an arbitrary project for the task result object? If not, I think _resolve_preview_task_project can be removed entirely and replaced with layer_style.project || project, which is allowed to be None.
80aac5a to
b859a2f
Compare
…ansaction.on_commit
… previews and tests
b38cc54 to
5479c16
Compare
Modifies #397 to not have a LayerStyle connection and rely only the fingerprint and layer foreign key for indentifying a preview.
New Models
RasterFramePreview: caches one rendered PNG per(layer_frame, style_fingerprint). Fields includestyle_fingerprint(sha256 ofraster_style_params),raster_style_params(render snapshot),status(creating/regenerating/complete/failed), S3image, pluswidth/height/bounds. Unique constraint on(layer_frame, style_fingerprint). Deleting a row also deletes its S3 image.LayerStyle.raster_style_params: JSONField holding the client-computed django-large-image style query used for tiles and previews.Layerhelpers:raster_frames()andis_multiframe_raster()(previews only apply when a layer has more than one raster frame).0025_raster_frame_preview.py.Frame Preview Workflow
Previews are content-addressed by a fingerprint of
raster_style_params(params_fingerprint/style_fingerprint).invalidate_and_enqueue_layer_previews:frame_previewTaskResultis already in flight for(layer_id, fingerprint).creating/regenerating), clear old images, create aTaskResult(task_type="frame_preview"), and rungenerate_frame_previews.generate_frame_previews): render a styled PNG thumbnail per frame with large-image, store on the preview row, markcomplete(orfailed), then complete theTaskResult(WebSocket notify).preview_statusis"ready"only when every raster frame has a complete image for the fingerprint; otherwise"notready".multiframe_previewsis only serialized when ready.How new styles update items
On style create/update, the client sends
raster_style_params(write-only). The serializer saves the style, then callsinvalidate_and_enqueue_previews(instance):preview_status: "notready"and omitsmultiframe_previewsuntil generation finishes.Also triggered after:
{}) previews for each multiframe layer.raster_style_paramsand regenerates sync so outputs are ready before the flood task completes.REST Endpoint Updates
layer_queryset_with_previews()loads raster frames + their preview rows in one go.LayerViewSet/ datasetlayers: use that queryset;LayerSerializerexposespreview_statusandmultiframe_previews(default fingerprint: default style params, else{}).LayerStyleViewSet: usesLayerStyleWithPreviewsSerializerwith the same fields keyed to the style’s fingerprint; create/update acceptraster_style_paramsand enqueue regeneration.Task Updates
Notification suppression
suppress_task_notifications()(ContextVar) silencesTaskResultWebSocket pushes during sync contexts (ingest, sync conversion, sync preview generation) where no client is listening. Failed pushes are also best-effort (logged, never abortsave()).asynchronous=True→run_mode(Ruff / boolean-trap)Boolean default args for async vs sync were replaced with an explicit enum.:
TaskRunMode.ASYNC/TaskRunMode.SYNC("async"/"sync")Dataset.spawn_conversion_task/convert_dataset,create_layers_and_frames, preview enqueue helpers, flood/geoai analytics, ingest sample scripts.Async preview jobs enqueue with
transaction.on_commit(...delay). Sync jobs run undersuppress_task_notifications()via.apply(), matching the surrounding conversion/ingest mode (no Celery worker required for ingest).Client Updates — How the Client Gets Information
preview_statusand (when ready)multiframe_previews(url,width,height,bounds). Selecting a layer copies those onto the active style and prefetches image URLs.raster_style_params, immediately marks local statenotready, clears stale previews, and dismisses the map overlay so real tiles show while regenerating.analysisstore).conversionstore).framePreviewStore.onPreviewTaskComplete, which re-fetches the layer or style and reattaches previews to selected copies still using that style.framePreviewstore +framePreviewLayerutils): show the current-frame PNG as a MapLibre image overlay, prefetch adjacent frames for scrubbing, then fade to real tiles once the tile source loads. Layers/legend panels indicate when a preview overlay is active. Style editing dismisses previews until edit mode ends.