Index devices.site_id and coalesce the outage refresh on status flips (large-fleet performance) - #47
Open
coreyhauer wants to merge 2 commits into
Open
coreyhauer wants to merge 2 commits into
coreyhauer wants to merge 2 commits into
Conversation
…ll devices scan per site devices.site_id was added as a constrained foreign key but never indexed, and Postgres does not index FK columns automatically. SiteController@index counts devices (and down devices) per site with two correlated subqueries, so on a 25k-device / 2.7k-site fleet each call seq-scanned devices 2,722 times: ~60 s, and it tripped the 120 s proxy timeout about two thirds of the time. The geo map's site markers wait on this call, so the map sat empty after login. With the composite index the same call takes 0.2 s. Guarded with hasIndex so a live CREATE INDEX CONCURRENTLY under the same name does not fail the migration.
ca330ee refreshes the outage timeline on every real up<->down flip so it lands ahead of the 15 s poll. On a large fleet that is not a rare event: hundreds of devices can flap per minute, and one invalidateQueries per flip made every open tab fetch /api/outages ~100 times a second, starving php-fpm for the requests that actually draw the map. Keep the intent (fresh within seconds of a flip) but coalesce: at most one refresh per 5 s window, trailing-edge so the last flip in a burst still shows.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two small fixes from running My Mate against a ~25k-device / 2.7k-site fleet. Both are independent of each other.
1. Index
devices (site_id, status)devices.site_id(2026_07_23_000002) was added as a constrained foreign key but never indexed, and Postgres does not index FK columns automatically.SiteController@indexcounts devices and down devices per site with two correlated subqueries, so eachGET /api/sitescall was a full scan ofdevicesper site.Measured on our box (25,423 devices, 2,722 sites): 61 s per call, tripping the reverse proxy's 120 s timeout about two thirds of the time. The geo map's site markers wait on this call, so the map sat empty after login. With the composite index the same call takes 0.2 s.
The migration is guarded with
Schema::hasIndexso an operator who already built the index live (CREATE INDEX CONCURRENTLY, same name) is not failed by it.2. Coalesce the outage-timeline refresh on status flips
ca330ee invalidates the outages query on every real up/down flip so the timeline lands ahead of its 15 s poll. On a large fleet that is not a rare event: we see several hundred flips per minute during weather, and one
invalidateQueriesper flip turned every open browser tab into a ~100 req/s client of/api/outages(about 850k requests per hour from two tabs), starving php-fpm for the requests that actually draw the map.This keeps the intent (fresh within seconds of a flip) but coalesces to at most one refresh per 5 s window, trailing-edge so the last flip in a burst is still reflected. The timer is cleared on unmount.
tscis clean; no behaviour change for small fleets beyond the outage list refreshing at most every 5 s instead of instantly.