diff --git a/app/jobs/auto_upgrade_job.rb b/app/jobs/auto_upgrade_job.rb index 30c10bc7e..34a0f3dc3 100644 --- a/app/jobs/auto_upgrade_job.rb +++ b/app/jobs/auto_upgrade_job.rb @@ -1,5 +1,5 @@ class AutoUpgradeJob < ApplicationJob - queue_as :default + queue_as :latency_low def perform(*args) raise_if_disabled diff --git a/app/jobs/destroy_job.rb b/app/jobs/destroy_job.rb index 2296c45f8..8ea120f65 100644 --- a/app/jobs/destroy_job.rb +++ b/app/jobs/destroy_job.rb @@ -1,5 +1,5 @@ class DestroyJob < ApplicationJob - queue_as :default + queue_as :latency_low def perform(model) model.destroy diff --git a/app/jobs/enrich_data_job.rb b/app/jobs/enrich_data_job.rb index 97286b823..f20875c82 100644 --- a/app/jobs/enrich_data_job.rb +++ b/app/jobs/enrich_data_job.rb @@ -1,5 +1,5 @@ class EnrichDataJob < ApplicationJob - queue_as :default + queue_as :latency_high def perform(account) account.enrich_data diff --git a/app/jobs/fetch_security_info_job.rb b/app/jobs/fetch_security_info_job.rb index 7dff6d0f0..5eaafa434 100644 --- a/app/jobs/fetch_security_info_job.rb +++ b/app/jobs/fetch_security_info_job.rb @@ -1,5 +1,5 @@ class FetchSecurityInfoJob < ApplicationJob - queue_as :default + queue_as :latency_low def perform(security_id) return unless Security.security_info_provider.present? diff --git a/app/jobs/import_job.rb b/app/jobs/import_job.rb index f7fc2c015..8a7c490ec 100644 --- a/app/jobs/import_job.rb +++ b/app/jobs/import_job.rb @@ -1,5 +1,5 @@ class ImportJob < ApplicationJob - queue_as :default + queue_as :latency_medium def perform(import) import.publish diff --git a/app/jobs/sync_job.rb b/app/jobs/sync_job.rb index c6f062536..187d18f73 100644 --- a/app/jobs/sync_job.rb +++ b/app/jobs/sync_job.rb @@ -1,5 +1,5 @@ class SyncJob < ApplicationJob - queue_as :default + queue_as :latency_medium def perform(sync) sync.perform diff --git a/app/jobs/user_purge_job.rb b/app/jobs/user_purge_job.rb index ff9978078..2f173f7a1 100644 --- a/app/jobs/user_purge_job.rb +++ b/app/jobs/user_purge_job.rb @@ -1,5 +1,5 @@ class UserPurgeJob < ApplicationJob - queue_as :default + queue_as :latency_low def perform(user) user.purge diff --git a/app/models/time_series.rb b/app/models/time_series.rb index 09091e8fd..f9ef3ffbf 100644 --- a/app/models/time_series.rb +++ b/app/models/time_series.rb @@ -37,6 +37,14 @@ class TimeSeries series: self end + def empty? + values.empty? + end + + def has_current_day_value? + values.any? { |v| v.date == Date.current } + end + # `as_json` returns the data shape used by D3 charts def as_json { diff --git a/app/views/accounts/chart.html.erb b/app/views/accounts/chart.html.erb index 67eee6fb4..329edba27 100644 --- a/app/views/accounts/chart.html.erb +++ b/app/views/accounts/chart.html.erb @@ -17,15 +17,19 @@
- <% if series %> + <% if series.has_current_day_value? %>
+ <% elsif series.empty? %> +
+

No data available for the selected period.

+
<% else %>
-

No data available for the selected period.

+

Calculating latest balance data...

<% end %>
diff --git a/app/views/pages/dashboard/_net_worth_chart.html.erb b/app/views/pages/dashboard/_net_worth_chart.html.erb index f6bc9b5ea..56d1adf76 100644 --- a/app/views/pages/dashboard/_net_worth_chart.html.erb +++ b/app/views/pages/dashboard/_net_worth_chart.html.erb @@ -1,12 +1,16 @@ <%# locals: (series:) %> -<% if series %> +<% if series.has_current_day_value? %>
+<% elsif series.empty? %> +
+

No data available for the selected period.

+
<% else %>
-

No data available for the selected period.

+

Calculating latest balance data...

<% end %> diff --git a/config/database.yml b/config/database.yml index 221e19e8f..6e0652c41 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,7 +1,8 @@ default: &default adapter: postgresql encoding: unicode - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + # 3 connections for Puma, 8 for GoodJob (in async mode, the default for self-hosters) = 11 connections + pool: <%= ENV.fetch("DB_POOL_SIZE") { 11 } %> host: <%= ENV.fetch("DB_HOST") { "127.0.0.1" } %> port: <%= ENV.fetch("DB_PORT") { "5432" } %> user: <%= ENV.fetch("POSTGRES_USER") { nil } %> diff --git a/config/initializers/good_job.rb b/config/initializers/good_job.rb index 9ca92c0f9..7649e5af8 100644 --- a/config/initializers/good_job.rb +++ b/config/initializers/good_job.rb @@ -11,6 +11,14 @@ Rails.application.configure do } end + # 5 queue threads + 3 for job listener, cron, executor = 8 threads allocated + config.queues = { + "latency_low" => { max_threads: 1, priority: 10 }, # ~30s jobs + "latency_low,latency_medium" => { max_threads: 2, priority: 5 }, # ~1-2 min jobs + "latency_low,latency_medium,latency_high" => { max_threads: 1, priority: 1 }, # ~5+ min jobs + "*" => { max_threads: 1, priority: 0 } # fallback queue + } + # Auth for jobs admin dashboard ActiveSupport.on_load(:good_job_application_controller) do before_action do