Nobody has started this yet — be first.
Business impact
When a city's entry is stale, the dashboard response currently just says "status": "stale" with a human-readable warning string embedded in prose -- a client can't tell programmatically whether that data is 2 minutes old (barely stale, basically fine) or 2 days old (seriously outdated, maybe worth hiding). Every consumer of this API is stuck parsing English out of the warning field if they want to show "as of 12 minutes ago" instead of a bare "stale" badge.
Problem
weather.CurrentWeather already carries a FetchedAt timestamp (correctly populated and already serialized as fetched_at in JSON) -- a client can compute staleness itself by diffing fetched_at against the current time. But dashboard.CityResult has no server-computed "how old is this" convenience field, so every client has to redo that same diff-against-now arithmetic itself instead of just reading a number.
Current behavior
A CityResult carrying weather data has no age_seconds field at all; clients wanting to show "as of N minutes ago" have to re-derive it themselves from fetched_at.
Expected behavior
Every CityResult that carries weather data (fresh or stale) also includes a server-computed age_seconds integer field -- how many seconds old the data was at the moment the response was built -- so a client can show "as of 12 minutes ago" (or decide to hide data past some threshold) by reading one field, not by parsing a human-readable warning string or re-deriving the diff itself.
Steps to reproduce
curl http://localhost:8083/dashboard -H 'X-User-ID: alice'
Why this matters
The raw ingredient (FetchedAt) already flows correctly through both the fresh and stale-fallback paths -- this ticket is about deriving and exposing one new field from it (time.Now().Sub(FetchedAt), in seconds) at the point a CityResult is built, not about fixing broken timestamp plumbing.
Suggested approach
Add an AgeSeconds int64 field (tagged json:"age_seconds") to dashboard.CityResult, and compute it (from the now-current time minus the relevant Weather.FetchedAt) everywhere a CityResult carrying Weather is constructed in fetchOne (both the fresh-fetch branch and the stale-fallback branch).
Acceptance criteria
Verification
go test ./practicetickets/... -run TestTicket07 -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b feat/cache-age-metadataFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/cache-age-metadataSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inweather_dashboarddbappmockweatherWEATHER_API_BASE_URL=https://api.openweathermap.orgWEATHER_API_KEYdocker-compose.prod.ymlRun the project's own test suite:
make test # go test ./...
make test-race # go test -race ./... (includes the concurrency/partial-failure test)
Work the tickets in PRACTICE_TICKETS.md (TICKET-01 through TICKET-10); each names one Go test in practicetickets/:
./practice_tickets_run.sh # all 10, pass/fail summary
go test ./practicetickets/... -run TestTicket01 -v # a single ticket
go test -race ./practicetickets/... -run TestTicket10 -v # ticket 10 needs -race to observe its bug
Tickets 03, 04, 05, and 06 touch the saved-cities Postgres store and need a reachable test database, set via WD_TEST_DATABASE_URL (defaults to postgres://postgres:postgres@localhost:5436/weather_dashboard_test if unset). Tickets 01, 02, 07, 08, 09, and 10 need no database at all.
Level 2
Implement a feature
Extend the system within its own patterns.