Application bundles are re-downloaded in full and ignore resourceUrl changes

Issue Description

The web application bundle cache is keyed on the application id alone, so
changing an application’s resourceUrl has no effect and the previously
downloaded bundle keeps being served. Separately, when the cached blob expires
it is deleted and re-fetched in full, with no If-Modified-Since, ETag or
version check, so a short autoUpdateFrequency repeatedly transfers an unchanged
~600 KB.

Expected Behavior

Changing resourceUrl should cause the new bundle to be fetched and served.
An expired but unchanged bundle should be revalidated rather than downloaded
again.

Actual Behavior

The old bundle is served until the blob expires or the “update applications”
action is run manually. On expiry the whole archive is downloaded again even
when the origin copy is unchanged.

Reproduction Steps

  1. Change the Web Interface application’s resourceUrl to a different bundle.
  2. Restart Stalwart.
  3. The previous bundle is still served.
  4. Set autoUpdateFrequency to 1 minute and restart repeatedly: each unpack
    downloads the full archive again, with no conditional request.

Relevant Log Output

GitHub honours conditional requests on the release asset:

If-Modified-Since: <current>  -> 304, 0 bytes
no header (current behaviour) -> 200, 614990 bytes

Stalwart Version

v0.16.x

Installation Method

Binary (macOS)

Database Backend

SQLite

Blob Storage

SQLite

Search Engine

Internal

Directory Backend

Internal

Additional Context

A possible implementation: Revalidate application bundles instead of re-downloading them - Pull Request #3307 - stalwartlabs/stalwart - GitHub

It also adds STALWART_APP_AUTO_UPDATE=false to skip the periodic check

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

Thanks for the detailed report and the reproduction steps. This does look like a real discrepancy between the documented behavior and what you’re observing.

The docs describe the intended update procedure as: on each autoUpdateFrequency tick, the server “fetches the bundle, compares it against the currently installed version, and applies it if a newer one is available. If the remote resource has not changed since the last successful check, the server leaves the unpacked files in place” (see Scheduled updates). That description implies a conditional/version check should prevent redundant downloads, and changing resourceUrl on an Application record should point subsequent refreshes at the new bundle since the bundle is looked up by that field (see resourceUrl).

Since your testing shows the cache is actually keyed only on application id (ignoring resourceUrl changes) and expired blobs are re-fetched with no conditional request, that’s a discrepancy from documented behavior worth investigating in the code itself rather than something I can resolve from docs alone. A staff or community member with visibility into the caching implementation will need to follow up on this one.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Fixed in v0.16.22 (yet to be released). When resourceUrl is changed now Stalwart fetches the bundle again.