Skip to content

fix(cache): Add new @version data to cache key - #3506

Open
joshlarson wants to merge 1 commit into
mainfrom
jdl/fix/put-version-in-cache-key
Open

joshlarson wants to merge 1 commit into
mainfrom
jdl/fix/put-version-in-cache-key

Conversation

@joshlarson

Copy link
Copy Markdown
Contributor

Scope

We've run into a number of issues where bugs happen because we introduce a new field, or make some other kind of change, to a struct representing our parsed understanding of some API response, add code that assumes that the new field is there, and then either crash the page or display the wrong thing when the old struct (without the field) is returned from the cache.

The most recent instance of this was #3501, which added a vehicle_type field to our %Stops.Stop{} struct, and started using that to determine whether to show the stop ID at the top of the screen. That led to the following scenario (fortunately only in dev - we haven't release that feature to prod yet, and hopefully won't until this PR is also merged):

  • Load a stop page while the old version of the code is deployed, caching a %Stops.Stop{} struct that doesn't have a vehicle_type field.
  • Deploy the new version of the code.
  • Check the cached %Stops.Stop{} for stop ID 853 (or whatever). See that its vehicle_type is nil (by virtue of not existing), and determine that we should not show the stop ID.
Screenshot 2026-09-17 at 12 56 05 PM

Asana Ticket: 🛠️ Automatically invalidate the cache on each deploy

Implementation

Now that we have the currently-deployed version available to us, we can add that ID (which will change any time the code changes) to the cache key.

Screenshots

Screenshot 2026-09-17 at 1 29 06 PM

How to test

This is a bit arduous to check, especially because @version is set at compile-time, so changing it when running locally can be a bit annoying (you'll get errors if you change SENTRY_RELEASE in your .env without also running mix clean).

But you can do the following...

To see the bug:

  • Checkout commit 0a569c4.
  • Start dotcom with iex -S mix phx.server.
  • Clear the cache by running Dotcom.Cache.Multilevel.flush in that iEX shell.
  • Visit a stop page. This will correctly show the stop ID.
  • Stop dotcom and checkout commit 7f20e3d.
  • Start dotcom again with iex -S mix phx.server. (Do not clear the cache)
  • Refresh the stop page. This will now show the missing stop ID.

To see the fix:

  • Do all of the steps above.
  • Stop dotcom and check out this branch (jdl/fix/put-version-in-cache-key).
  • Start dotcom again with iex -S mix phx.server. (Do not clear the cache)
  • Refresh the stop page. The stop ID should be back!

To see how this fix will resolve this type of issue moving forward:

  • Checkout commit 0a569c4.
  • Apply the changes from this branch with git show origin/main...jdl/fix/put-version-in-cache-key | git apply.
  • Ensure that SENTRY_RELEASE is set to something like local or local-0 in your .env file.
  • Start dotcom with iex -S mix phx.server.
  • Clear the cache by running Dotcom.Cache.Multilevel.flush in that iEX shell.
  • Visit a stop page. This will correctly show the stop ID.
  • Stop dotcom, discard the changes, and check out this branch (jdl/fix/put-version-in-cache-key).
  • Start dotcom again with iex -S mix phx.server. (Do not clear the cache)
  • Refresh the stop page. The stop ID will be missing. This is because the fix here relies on SENTRY_RELEASE changing, and you haven't changed it in your .env file
    • While that's annoying locally, in deployed environments, SENTRY_RELEASE will always change during deploys, unless you redeploy the same version (which wouldn't need a cache-bust anyway).
  • Stop dotcom, change SENTRY_RELEASE to literally any other value (e.g. local-1), run mix clean, and restart.
  • Refresh the stop page. The stop ID will be back!

Generate a readable cache key based on the module, function, and arguments.
"""

@version Application.compile_env(:dotcom, :version)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: I believe a default is provided elsewhere, but.. should we supply a default value here in case this ends up nil for whatever reason?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev-blue Deploy to dev-blue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants