Summary
Api::V1::CheckinsController#index filters check-ins in Ruby instead of in MongoDB. When the date param is present, the endpoint loads every check-in the user has ever created into memory and then discards all but one day's worth.
Details
https://github.com/rubyforgood/Flaredown/blob/master/backend/app/controllers/api/v1/checkins_controller.rb#L10-L12
render json: current_user.checkins.includes([:harvey_bradshaw_index, :promotion_rate, :conditions, :symptoms, :treatments]).select { |x|
x.date.to_date == Date.parse(date)
}
.select here takes a block, so it is Enumerable#select, not Mongoid::Criteria#select. Calling it forces the criteria to load. The includes(...) call makes it worse by eager-loading the associated documents for the whole history, not just the matching day.
Impact
This is the endpoint the web and native clients hit to render a single day's check-in, so it is one of the hottest paths in the app. Cost scales linearly with account age: a user who has checked in daily for three years pulls ~1,100 documents plus their embedded conditions, symptoms and treatments on every day-view request, to render one. Since Flaredown is aimed at people tracking chronic conditions over long periods, the users hurt most are the most engaged ones.
Proposed fix
Checkin already has both pieces needed, and neither is being used here:
scope :by_date, ->(startkey, endkey) { where(:date.gte => startkey, :date.lte => endkey) } — backend/app/models/checkin.rb#L50
index(date: 1, encrypted_user_id: 1) — backend/app/models/checkin.rb#L39
Replace the in-Ruby filter with the existing scope over the parsed day's bounds so the query is served by the existing compound index.
Behaviour should be unchanged: the existing specs in spec/controllers/api/v1/checkins_controller_spec.rb cover multiple check-ins on the same calendar day and check-ins on neighbouring days, and must keep passing.
Note on indexes
Worth confirming separately that rake db:mongoid:create_indexes has actually been run against production. I could not find anything in the repo that invokes it — no Procfile release phase, and Rakefile deploy runs only rake db:migrate — so the declared indexes may not exist on the deployed cluster. That is a separate issue, but it affects how much this fix buys in practice.
Summary
Api::V1::CheckinsController#indexfilters check-ins in Ruby instead of in MongoDB. When thedateparam is present, the endpoint loads every check-in the user has ever created into memory and then discards all but one day's worth.Details
https://github.com/rubyforgood/Flaredown/blob/master/backend/app/controllers/api/v1/checkins_controller.rb#L10-L12
.selecthere takes a block, so it isEnumerable#select, notMongoid::Criteria#select. Calling it forces the criteria to load. Theincludes(...)call makes it worse by eager-loading the associated documents for the whole history, not just the matching day.Impact
This is the endpoint the web and native clients hit to render a single day's check-in, so it is one of the hottest paths in the app. Cost scales linearly with account age: a user who has checked in daily for three years pulls ~1,100 documents plus their embedded conditions, symptoms and treatments on every day-view request, to render one. Since Flaredown is aimed at people tracking chronic conditions over long periods, the users hurt most are the most engaged ones.
Proposed fix
Checkinalready has both pieces needed, and neither is being used here:scope :by_date, ->(startkey, endkey) { where(:date.gte => startkey, :date.lte => endkey) }—backend/app/models/checkin.rb#L50index(date: 1, encrypted_user_id: 1)—backend/app/models/checkin.rb#L39Replace the in-Ruby filter with the existing scope over the parsed day's bounds so the query is served by the existing compound index.
Behaviour should be unchanged: the existing specs in
spec/controllers/api/v1/checkins_controller_spec.rbcover multiple check-ins on the same calendar day and check-ins on neighbouring days, and must keep passing.Note on indexes
Worth confirming separately that
rake db:mongoid:create_indexeshas actually been run against production. I could not find anything in the repo that invokes it — no Procfile release phase, andRakefiledeploy runs onlyrake db:migrate— so the declared indexes may not exist on the deployed cluster. That is a separate issue, but it affects how much this fix buys in practice.