Three fixes found while verifying the 1.10.0/1.11.0 deploy in production. No configuration change is required.
Fixed
-
A slow Redis start left replicas permanently without a cache. Redis replays its RDB before it will answer commands, so on a cold start of the whole stack the API pings while Redis is still loading and gets back
LOADING Redis is loading the dataset in memory.NewCacheServicereturned an error for that, and the caller responded by discarding the client and setting the service tonil. Nothing ever retried, so a few seconds of startup became the state of the process until somebody restarted it.Discarding the client was never necessary: go-redis dials lazily per command and reconnects on its own, so a client whose first ping failed still works the moment Redis accepts connections.
NewCacheServicenow pings up to three times with backoff and, if that still fails, returns the usable service alongside the error. A nil service is now reserved for aREDIS_URLthat cannot be parsed, which is configuration that can never work.Verified by booting with Redis stopped and starting it afterwards: the cache reports healthy within a second, with no restart.
-
/healthreturned 500 with no explanation when the cache was missing.CacheServiceis an interface, so thenilabove was not caught by any check; the health handler dereferenced it and panicked, and the recover middleware turned that into a bare 500. It now reportsunhealthy: cache not configured, which still fails the core health check but says why. -
POST /resizedid the work and threw the result away. It decoded the upload, resized it, checked the output was not nil, discarded it, and answered with a JSONImage processed successfullycarrying no image. Bothdocs/api.mdand the OpenAPI spec already documented the endpoint as returning the resized image directly, so this was the code drifting from its own contract rather than an undocumented design. The handler now sends the resized bytes with a sniffed, inertContent-Type.
Upgrading
Drop-in. The only externally visible change is /resize, which now returns the image its documentation always promised instead of a JSON acknowledgement. A caller that was parsing that JSON was not receiving an image before either, so nothing that worked stops working.