mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-07 22:45:20 +02:00
Improve account sync performance, handle concurrent market data syncing (#2236)
* PlaidConnectable concern * Remove bad abstraction * Put sync implementations in own concerns * Sync strategies * Move sync orchestration to Sync class * Clean up sync class, add state machine * Basic market data sync cron * Fix price sync * Improve sync window column names, add timestamps * 30 day syncs by default * Clean up market data methods * Report high duplicate sync counts to Sentry * Add sync states throughout app * account tab session * Persistent account tab selections * Remove manual sleep * Add migration to clear stale syncs on self hosted apps * Tweak sync states * Sync completion event broadcasts * Fix timezones in tests * Cleanup * More cleanup * Plaid item UI broadcasts for sync * Fix account ID namespace conflict * Sync broadcasters * Smoother account sync refreshes * Remove test sync delay
This commit is contained in:
parent
9793cc74f9
commit
10dd9e061a
97 changed files with 1837 additions and 949 deletions
|
@ -25,11 +25,14 @@
|
|||
|
||||
<div class="w-full space-y-6 pb-24">
|
||||
<% if Current.family.accounts.any? %>
|
||||
<section class="bg-container py-4 rounded-xl shadow-border-xs px-0.5">
|
||||
<%= render partial: "pages/dashboard/net_worth_chart", locals: { series: @balance_sheet.net_worth_series(period: @period), period: @period } %>
|
||||
<section class="bg-container py-4 rounded-xl shadow-border-xs">
|
||||
<%= render partial: "pages/dashboard/net_worth_chart", locals: {
|
||||
balance_sheet: @balance_sheet,
|
||||
period: @period
|
||||
} %>
|
||||
</section>
|
||||
<% else %>
|
||||
<section class="p-0.5">
|
||||
<section>
|
||||
<%= render "pages/dashboard/no_accounts_graph_placeholder" %>
|
||||
</section>
|
||||
<% end %>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<%# locals: (balance_sheet:) %>
|
||||
<%# locals: (balance_sheet:, **args) %>
|
||||
|
||||
<div class="space-y-4 overflow-x-auto p-0.5">
|
||||
<div class="space-y-4" id="balance-sheet">
|
||||
<% balance_sheet.classification_groups.each do |classification_group| %>
|
||||
<div class="bg-container shadow-border-xs rounded-xl space-y-4 p-4">
|
||||
<h2 class="text-lg font-medium inline-flex items-center gap-1.5">
|
||||
|
@ -11,26 +11,38 @@
|
|||
<% if classification_group.account_groups.any? %>
|
||||
<span class="text-secondary">·</span>
|
||||
|
||||
<span class="text-secondary font-medium text-lg"><%= classification_group.total_money.format(precision: 0) %></span>
|
||||
<% if classification_group.syncing? %>
|
||||
<div class="flex items-center w-8 h-4 ml-auto">
|
||||
<div class="bg-loader w-full h-full rounded-md"></div>
|
||||
</div>
|
||||
<% else %>
|
||||
<span class="text-secondary font-medium text-lg"><%= classification_group.total_money.format(precision: 0) %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</h2>
|
||||
|
||||
<% if classification_group.account_groups.any? %>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="flex gap-1">
|
||||
<% classification_group.account_groups.each do |account_group| %>
|
||||
<div class="h-1.5 rounded-sm" style="width: <%= account_group.weight %>%; background-color: <%= account_group.color %>;"></div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<% classification_group.account_groups.each do |account_group| %>
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<div class="h-2.5 w-2.5 rounded-full" style="background-color: <%= account_group.color %>;"></div>
|
||||
<p class="text-secondary"><%= account_group.name %></p>
|
||||
<p class="text-primary font-mono"><%= number_to_percentage(account_group.weight, precision: 0) %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if classification_group.syncing? %>
|
||||
<p class="text-xs text-subdued animate-pulse">Calculating latest balance data...</p>
|
||||
<% else %>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<% classification_group.account_groups.each do |account_group| %>
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<div class="h-2.5 w-2.5 rounded-full" style="background-color: <%= account_group.color %>;"></div>
|
||||
<p class="text-secondary"><%= account_group.name %></p>
|
||||
<p class="text-primary font-mono"><%= number_to_percentage(account_group.weight, precision: 0) %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="bg-surface rounded-xl p-1 space-y-1 overflow-x-auto">
|
||||
|
@ -56,15 +68,27 @@
|
|||
<p><%= account_group.name %></p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between text-right gap-6">
|
||||
<div class="w-28 shrink-0 flex items-center justify-end gap-2">
|
||||
<%= render "pages/dashboard/group_weight", weight: account_group.weight, color: account_group.color %>
|
||||
</div>
|
||||
<% if account_group.syncing? %>
|
||||
<div class="flex items-center justify-between text-right gap-6">
|
||||
<div class="w-28 shrink-0 flex items-center justify-end gap-2">
|
||||
<div class="bg-loader rounded-md h-4 w-12"></div>
|
||||
</div>
|
||||
|
||||
<div class="w-40 shrink-0">
|
||||
<p><%= format_money(account_group.total_money) %></p>
|
||||
<div class="w-40 shrink-0 flex justify-end">
|
||||
<div class="bg-loader rounded-md h-4 w-12"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="flex items-center justify-between text-right gap-6">
|
||||
<div class="w-28 shrink-0 flex items-center justify-end gap-2">
|
||||
<%= render "pages/dashboard/group_weight", weight: account_group.weight, color: account_group.color %>
|
||||
</div>
|
||||
|
||||
<div class="w-40 shrink-0">
|
||||
<p><%= format_money(account_group.total_money) %></p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</summary>
|
||||
|
||||
<div>
|
||||
|
@ -76,15 +100,27 @@
|
|||
<%= link_to account.name, account_path(account) %>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto flex items-center text-right gap-6">
|
||||
<div class="w-28 shrink-0 flex items-center justify-end gap-2">
|
||||
<%= render "pages/dashboard/group_weight", weight: account.weight, color: account_group.color %>
|
||||
</div>
|
||||
<% if account.syncing? %>
|
||||
<div class="ml-auto flex items-center text-right gap-6">
|
||||
<div class="w-28 shrink-0 flex items-center justify-end gap-2">
|
||||
<div class="bg-loader rounded-md h-4 w-12"></div>
|
||||
</div>
|
||||
|
||||
<div class="w-40 shrink-0">
|
||||
<p><%= format_money(account.balance_money) %></p>
|
||||
<div class="w-40 shrink-0 flex justify-end">
|
||||
<div class="bg-loader rounded-md h-4 w-12"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="ml-auto flex items-center text-right gap-6">
|
||||
<div class="w-28 shrink-0 flex items-center justify-end gap-2">
|
||||
<%= render "pages/dashboard/group_weight", weight: account.weight, color: account_group.color %>
|
||||
</div>
|
||||
|
||||
<div class="w-40 shrink-0">
|
||||
<p><%= format_money(account.balance_money) %></p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if idx < account_group.accounts.size - 1 %>
|
||||
|
|
|
@ -1,37 +1,55 @@
|
|||
<%# locals: (series:, period:) %>
|
||||
<%# locals: (balance_sheet:, period:, **args) %>
|
||||
|
||||
<div class="flex justify-between gap-4 px-4">
|
||||
<div class="space-y-2">
|
||||
<div id="net-worth-chart">
|
||||
<% series = balance_sheet.net_worth_series(period: period) %>
|
||||
<div class="flex justify-between gap-4 px-4">
|
||||
<div class="space-y-2">
|
||||
<p class="text-sm text-secondary font-medium"><%= t(".title") %></p>
|
||||
<p class="text-primary -space-x-0.5 text-3xl font-medium">
|
||||
<%= series.current.format %>
|
||||
</p>
|
||||
<% if series.trend.nil? %>
|
||||
<p class="text-sm text-secondary"><%= t(".data_not_available") %></p>
|
||||
<% else %>
|
||||
<%= render partial: "shared/trend_change", locals: { trend: series.trend, comparison_label: period.comparison_label } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<p class="text-sm text-secondary font-medium"><%= t(".title") %></p>
|
||||
|
||||
<%= form_with url: root_path, method: :get, data: { controller: "auto-submit-form" } do |form| %>
|
||||
<%= form.select :period,
|
||||
<% if balance_sheet.syncing? %>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="bg-loader rounded-md h-7 w-20"></div>
|
||||
<div class="bg-loader rounded-md h-5 w-32"></div>
|
||||
</div>
|
||||
<% else %>
|
||||
<p class="text-primary -space-x-0.5 text-3xl font-medium">
|
||||
<%= series.current.format %>
|
||||
</p>
|
||||
|
||||
<% if series.trend.nil? %>
|
||||
<p class="text-sm text-secondary"><%= t(".data_not_available") %></p>
|
||||
<% else %>
|
||||
<%= render partial: "shared/trend_change", locals: { trend: series.trend, comparison_label: period.comparison_label } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= form_with url: root_path, method: :get, data: { controller: "auto-submit-form" } do |form| %>
|
||||
<%= form.select :period,
|
||||
Period.as_options,
|
||||
{ selected: period.key },
|
||||
data: { "auto-submit-form-target": "auto" },
|
||||
class: "bg-container border border-secondary font-medium rounded-lg px-3 py-2 text-sm pr-7 cursor-pointer text-primary focus:outline-hidden focus:ring-0" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if series.any? %>
|
||||
<div
|
||||
<% if balance_sheet.syncing? %>
|
||||
<div class="w-full flex items-center justify-center p-4 h-52">
|
||||
<div class="bg-loader rounded-md h-full w-full"></div>
|
||||
</div>
|
||||
<% else %>
|
||||
<% if series.any? %>
|
||||
<div
|
||||
id="netWorthChart"
|
||||
class="w-full flex-1 min-h-52"
|
||||
data-controller="time-series-chart"
|
||||
data-time-series-chart-data-value="<%= series.to_json %>"></div>
|
||||
<% else %>
|
||||
<div class="w-full h-full flex items-center justify-center">
|
||||
<p class="text-secondary text-sm"><%= t(".data_not_available") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="w-full h-full flex items-center justify-center">
|
||||
<p class="text-secondary text-sm"><%= t(".data_not_available") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue