Class: Seo::VisitPageDailyCountsQuery
- Inherits:
-
Object
- Object
- Seo::VisitPageDailyCountsQuery
- Defined in:
- app/queries/seo/visit_page_daily_counts_query.rb
Overview
Builds and reads the bounded daily visit aggregate used by the SEO page
metrics sync. Raw SQL is intentional here: path normalization and a grouped
INSERT are database work, and expressing them as per-record Ruby objects is
the allocation/query pattern this class replaces.
Defined Under Namespace
Classes: RefreshAlreadyRunning
Constant Summary collapse
- BACKFILL_DAYS =
90- RECHECK_DAYS =
2- BUSINESS_TIME_ZONE =
'America/Chicago'
Instance Attribute Summary collapse
-
#period_end ⇒ Object
readonly
Returns the value of attribute period_end.
Instance Method Summary collapse
-
#coverage_complete? ⇒ Boolean
Whether every day needed by the 90-day window has a durable completion marker.
-
#initialize(period_end: Date.current) ⇒ VisitPageDailyCountsQuery
constructor
A new instance of VisitPageDailyCountsQuery.
-
#refresh_date!(visit_date) ⇒ Hash
Rebuild one date in a transaction.
-
#refresh_dates ⇒ Array<Date>
Dates needed for a complete rolling window.
-
#totals(paths:) ⇒ Hash{String => Hash}
Return rolling counts for the supplied canonical SiteMap paths.
Constructor Details
#initialize(period_end: Date.current) ⇒ VisitPageDailyCountsQuery
Returns a new instance of VisitPageDailyCountsQuery.
17 18 19 |
# File 'app/queries/seo/visit_page_daily_counts_query.rb', line 17 def initialize(period_end: Date.current) @period_end = period_end.to_date end |
Instance Attribute Details
#period_end ⇒ Object (readonly)
Returns the value of attribute period_end.
15 16 17 |
# File 'app/queries/seo/visit_page_daily_counts_query.rb', line 15 def period_end @period_end end |
Instance Method Details
#coverage_complete? ⇒ Boolean
Returns whether every day needed by the 90-day window has a
durable completion marker.
35 36 37 |
# File 'app/queries/seo/visit_page_daily_counts_query.rb', line 35 def coverage_complete? VisitPageDailyRefresh.where(visit_date: coverage_range).count == BACKFILL_DAYS end |
#refresh_date!(visit_date) ⇒ Hash
Rebuild one date in a transaction. The non-blocking advisory lock keeps a
duplicate job from interleaving its delete/insert with the active owner;
raising makes Sidekiq retry instead of falsely completing its batch slot.
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'app/queries/seo/visit_page_daily_counts_query.rb', line 45 def refresh_date!(visit_date) visit_date = visit_date.to_date lock = VisitPageDailyCount.with_advisory_lock_result( "seo|visit_page_daily_counts|#{visit_date}", timeout_seconds: 0 ) do rebuild_date!(visit_date) end raise RefreshAlreadyRunning, "Visit aggregate refresh already running for #{visit_date}" unless lock.lock_was_acquired? lock.result end |
#refresh_dates ⇒ Array<Date>
Dates needed for a complete rolling window. Missing dates are rebuilt
first; the latest two dates are then recomputed for late-arriving visits.
25 26 27 28 29 30 31 |
# File 'app/queries/seo/visit_page_daily_counts_query.rb', line 25 def refresh_dates required_dates = coverage_range.to_a completed_dates = VisitPageDailyRefresh.where(visit_date: coverage_range).pluck(:visit_date).to_set missing_dates = required_dates.reject { completed_dates.include?(it) } (missing_dates + required_dates.last(RECHECK_DAYS)).uniq.sort end |
#totals(paths:) ⇒ Hash{String => Hash}
Return rolling counts for the supplied canonical SiteMap paths.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'app/queries/seo/visit_page_daily_counts_query.rb', line 62 def totals(paths:) paths = paths.compact_blank.uniq return {} if paths.empty? thirty_day_start = period_end - 29.days quoted_start = VisitPageDailyCount.lease_connection.quote(thirty_day_start) rows = VisitPageDailyCount .where(path: paths, visit_date: coverage_range) .group(:path) .pluck( :path, Arel.sql("SUM(visits_count) FILTER (WHERE visit_date >= #{quoted_start})"), Arel.sql('SUM(visits_count)') ) rows.to_h do |path, visits_30d, visits_90d| [path, { visits_30d: visits_30d.to_i, visits_90d: visits_90d.to_i }] end end |