Attachments

Lexxy uploads files using Active Storage’s Direct Upload protocol and renders previews for previewable blobs (images, PDFs, videos).

Upload response

After a Direct Upload completes, Lexxy reads the following fields from the blob JSON returned by the upload endpoint:

Field Description
signed_id The Active Storage signed ID for the blob.
attachable_sgid The signed Global ID used to embed the attachment in Action Text.
filename The file name.
content_type MIME type of the file.
byte_size File size in bytes.
previewable true if the blob can be previewed as an image (e.g., a PDF or video).
url The URL to load the preview image from. Required when previewable is true.
preview_status_url Optional. URL of a status endpoint Lexxy polls while the preview is being generated. See Deferred previews below.

Deferred previews

Generating a preview for a PDF or video is expensive. The default Active Storage path runs the transform (libvips, ffmpeg, etc.) on the request thread the first time the preview URL is hit — under load this becomes the dominant cost of a previewable upload, and concurrent hits to the same not-yet-generated variant can each pay the cost independently.

After upload, Lexxy shows a file icon for the attachment until the preview image is ready, then swaps it in. There are two ways to detect when the preview is ready — picked by what the host returns in the upload response:

Default: preload the preview image

When preview_status_url is not provided, Lexxy loads the preview URL once into an off-screen Image and swaps the figure to show the preview when the image loads. If the image fails to load, the file icon stays. There are no retries and no cache-busting — the preview URL is hit exactly once.

This works for backends that serve the preview bytes when the URL is hit (blocking until ready or 404’ing while processing). It does not work for backends that respond with a placeholder image while processing — the placeholder will be displayed as if it were the preview. Those hosts should use the status URL path below.

Opt-in: poll a status URL

If your backend can generate previews in the background (rather than on the request thread), supply a preview_status_url in the upload response. Lexxy will:

  1. Show a file icon while the preview is being generated.
  2. Poll the status URL with exponential backoff (up to 20 attempts).
  3. Replace the file icon with the preview image once the status URL signals that the preview is ready.

This lets the host kick off background preview generation immediately after upload (for example, from an Active Job triggered by an after_create_commit on the blob) while keeping the editor’s pending UI driven by a cheap status check. The preview URL itself is hit exactly once per upload — after the status endpoint says the preview is ready — so the expensive transform runs in the background, not on the polling path.

Status URL contract

Lexxy polls the status URL with fetch and interprets the response as follows:

  • 2xx — preview is still being generated. Lexxy will poll again after a backoff delay.
  • Any other status (3xx, 4xx, 5xx) — preview is ready (or won’t ever be ready). Lexxy stops polling and loads the preview URL.
  • Network error — counted as a retry, up to the maximum attempts.

A response body is not required; only the HTTP status matters. Cookies are sent with the request (credentials: "include"), so the endpoint can be authenticated.