1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-02 20:15:22 +02:00

Balance sheet cache layer, non-blocking sync UI (#2356)
Some checks are pending
Publish Docker image / ci (push) Waiting to run
Publish Docker image / Build docker image (push) Blocked by required conditions

* Balance sheet cache layer with cache-busting

* Update family cache timestamps during Sync

* Less blocking sync loaders

* Consolidate family data caching key logic

* Fix turbo stream broadcasts

* Remove dev delay

* Add back account group sorting
This commit is contained in:
Zach Gollwitzer 2025-06-10 18:20:06 -04:00 committed by GitHub
parent dab693d74f
commit 10ce2c8e23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 529 additions and 466 deletions

View file

@ -35,25 +35,6 @@ class Family < ApplicationRecord
validates :locale, inclusion: { in: I18n.available_locales.map(&:to_s) }
validates :date_format, inclusion: { in: DATE_FORMATS.map(&:last) }
# If any accounts or plaid items are syncing, the family is also syncing, even if a formal "Family Sync" is not running.
def syncing?
# Check for any in-progress syncs that belong directly to the family, to one of the
# family's accounts, or to one of the family's Plaid items. By moving the `visible`
# scope to the beginning we narrow down the candidate rows **before** performing the
# joins and by explicitly constraining the `syncable_type` for the direct Family
# match we allow Postgres to use the composite index on `(syncable_type, syncable_id)`.
Sync.visible
.joins("LEFT JOIN accounts ON accounts.id = syncs.syncable_id AND syncs.syncable_type = 'Account'")
.joins("LEFT JOIN plaid_items ON plaid_items.id = syncs.syncable_id AND syncs.syncable_type = 'PlaidItem'")
.where(
"(syncs.syncable_type = 'Family' AND syncs.syncable_id = :family_id) OR " \
"accounts.family_id = :family_id OR " \
"plaid_items.family_id = :family_id",
family_id: id
)
.exists?
end
def assigned_merchants
merchant_ids = transactions.where.not(merchant_id: nil).pluck(:merchant_id).uniq
Merchant.where(id: merchant_ids)
@ -110,13 +91,15 @@ class Family < ApplicationRecord
entries.order(:date).first&.date || Date.current
end
# Cache key that is invalidated when any of the family's entries are updated (which affect rollups and other calculations)
def build_cache_key(key)
def build_cache_key(key, invalidate_on_data_updates: false)
# Our data sync process updates this timestamp whenever any family account successfully completes a data update.
# By including it in the cache key, we can expire caches every time family account data changes.
data_invalidation_key = invalidate_on_data_updates ? latest_sync_completed_at : nil
[
"family",
id,
key,
entries.maximum(:updated_at)
data_invalidation_key
].compact.join("_")
end