Skip to content

Commit 05e5b1c

Browse files
committed
Fix sitemap ranking generation
1 parent 87e8bab commit 05e5b1c

4 files changed

Lines changed: 24 additions & 117 deletions

File tree

lib/polish_open_source_rank/web/composition.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,10 @@ def package_ranking_read_model
7878
def sitemap_ranking_catalog
7979
contexts[:sitemap_ranking_catalog] ||= SitemapRankingCatalog.new(
8080
catalogs: [
81-
PublicRankingSitemapCatalog.new(show_ranking_detail: publication.show_ranking_detail),
82-
LanguageRankingSitemapCatalog.new(
83-
show_language_ranking_detail: languages.show_language_ranking_detail
84-
),
81+
PublicRankingSitemapCatalog.new,
82+
LanguageRankingSitemapCatalog.new,
8583
PackageRankingSitemapCatalog.new(
86-
package_ranking_read_model: package_ranking_read_model,
87-
show_package_ranking_detail: packages.show_package_ranking_detail
84+
package_ranking_read_model: package_ranking_read_model
8885
)
8986
]
9087
)

lib/polish_open_source_rank/web/composition/sitemap_ranking_catalog.rb

Lines changed: 11 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,6 @@
33
module PolishOpenSourceRank
44
module Web
55
class Composition
6-
# Expands one canonical ranking path into every non-empty paginated URL.
7-
module SitemapPageSeries
8-
module_function
9-
10-
def paths(path)
11-
paths = [path]
12-
2.upto(Presentation::RankingPaginator::MAX_PAGE) do |page|
13-
break if yield((page - 1) * Presentation::RankingPaginator::PER_PAGE).empty?
14-
15-
paths << "#{path}/page/#{page}"
16-
end
17-
paths
18-
end
19-
end
20-
21-
# Couples one canonical path with the query that determines its non-empty pages.
22-
class SitemapQuerySeries
23-
def initialize(path, query)
24-
@path = path
25-
@query = query
26-
end
27-
28-
def paths(reader)
29-
SitemapPageSeries.paths(path) do |offset|
30-
reader.call(**query, limit: 1, offset: offset)
31-
end
32-
end
33-
34-
private
35-
36-
attr_reader :path, :query
37-
end
38-
396
# Combines independently owned ranking URL inventories.
407
class SitemapRankingCatalog
418
def initialize(catalogs:)
@@ -57,16 +24,6 @@ class PublicRankingSitemapCatalog
5724
Route = Data.define(:kind, :metric, :suffix)
5825
# Binds a ranking route to its public prefix, geographic scope, and snapshot.
5926
Scope = Data.define(:prefix, :slug, :period_start) do
60-
def series(route)
61-
SitemapQuerySeries.new(
62-
"#{prefix}/#{route.suffix}",
63-
scope: slug,
64-
kind: route.kind,
65-
metric: route.metric,
66-
period_start: period_start
67-
)
68-
end
69-
7027
def people_prefix
7128
slug == 'poland' ? '/people' : "/people/locations/#{slug}"
7229
end
@@ -105,18 +62,12 @@ def ranking_scopes
10562
%w[organization-repositories trending repositories/trending]
10663
].map { |values| Route.new(*values) }.freeze
10764

108-
def initialize(show_ranking_detail:)
109-
@show_ranking_detail = show_ranking_detail
110-
end
111-
11265
def paths(latest_period:, period_slugs:)
11366
latest_paths(latest_period) + period_slugs.flat_map { |slug| historical_paths(slug) }
11467
end
11568

11669
private
11770

118-
attr_reader :show_ranking_detail
119-
12071
def latest_paths(period_start)
12172
latest_scope_paths(Scope.new(nil, 'poland', period_start)) +
12273
city_slugs.flat_map do |slug|
@@ -149,11 +100,7 @@ def historical_city_indexes(prefix)
149100
end
150101

151102
def route_paths(scope, routes)
152-
routes.flat_map { |route| route_page_paths(scope, route) }
153-
end
154-
155-
def route_page_paths(scope, route)
156-
scope.series(route).paths(show_ranking_detail)
103+
routes.map { |route| "#{scope.prefix}/#{route.suffix}" }
157104
end
158105

159106
def city_slugs
@@ -165,27 +112,17 @@ def city_slugs
165112
class LanguageRankingSitemapCatalog
166113
# Binds language ranking metrics to a public period prefix and snapshot.
167114
Period = Data.define(:prefix, :start) do
168-
def series(metric)
169-
SitemapQuerySeries.new(
170-
"#{prefix}/languages/#{metric.slug}",
171-
metric: metric.key,
172-
period_start: start
173-
)
115+
def path(metric)
116+
"#{prefix}/languages/#{metric.slug}"
174117
end
175118
end
176119

177-
def initialize(show_language_ranking_detail:)
178-
@show_language_ranking_detail = show_language_ranking_detail
179-
end
180-
181120
def paths(latest_period:, period_slugs:)
182121
current_paths(latest_period) + period_slugs.flat_map { |slug| historical_paths(slug) }
183122
end
184123

185124
private
186125

187-
attr_reader :show_language_ranking_detail
188-
189126
def current_paths(latest_period)
190127
latest_period ? period_paths(Period.new('', latest_period)) : []
191128
end
@@ -201,7 +138,7 @@ def period_paths(period)
201138
end
202139

203140
def metric_paths(period, metric)
204-
period.series(metric).paths(show_language_ranking_detail)
141+
period.path(metric)
205142
end
206143
end
207144

@@ -215,27 +152,21 @@ def ecosystem(name)
215152
end
216153
# Owns package metric URL generation for one ecosystem and snapshot.
217154
Ecosystem = Data.define(:path, :name, :period_start) do
218-
def paths(reader)
155+
def paths
219156
[path] + Contexts::Packages::Domain::PackageRankingMetric.all(ecosystem: name).flat_map do |metric|
220-
metric_paths(metric, reader)
157+
metric_path(metric)
221158
end
222159
end
223160

224161
private
225162

226-
def metric_paths(metric, reader)
227-
SitemapQuerySeries.new(
228-
"#{path}/#{metric.slug}",
229-
ecosystem: name,
230-
metric: metric.key,
231-
period_start: period_start
232-
).paths(reader)
163+
def metric_path(metric)
164+
"#{path}/#{metric.slug}"
233165
end
234166
end
235167

236-
def initialize(package_ranking_read_model:, show_package_ranking_detail:)
168+
def initialize(package_ranking_read_model:)
237169
@package_ranking_read_model = package_ranking_read_model
238-
@show_package_ranking_detail = show_package_ranking_detail
239170
end
240171

241172
def paths(latest_period:, period_slugs:)
@@ -244,7 +175,7 @@ def paths(latest_period:, period_slugs:)
244175

245176
private
246177

247-
attr_reader :package_ranking_read_model, :show_package_ranking_detail
178+
attr_reader :package_ranking_read_model
248179

249180
def current_paths(latest_period)
250181
latest_period ? period_paths(Period.new('', latest_period)) : []
@@ -265,7 +196,7 @@ def ecosystems(period)
265196
end
266197

267198
def ecosystem_paths(period, ecosystem)
268-
period.ecosystem(ecosystem).paths(show_package_ranking_detail)
199+
period.ecosystem(ecosystem).paths
269200
end
270201

271202
def package_ranking_ecosystem?(ecosystem)

spec/polish_open_source_rank/web/app_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@ def user(_access_token)
11851185
expect(sitemap.content_type).to include('application/xml')
11861186
sitemap_locations = REXML::XPath.match(xml_document(sitemap.body), '//url/loc').map(&:text)
11871187
expect(sitemap_locations).to include('https://rank.example/people')
1188-
expect(sitemap_locations).to include('https://rank.example/people/users/top/page/2')
1188+
expect(sitemap_locations).not_to include('https://rank.example/people/users/top/page/2')
11891189
expect(sitemap_locations).to include('https://rank.example/organizations')
11901190
expect(sitemap_locations).to include('https://rank.example/organizations/active')
11911191
expect(sitemap_locations).to include('https://rank.example/organizations/locations/krakow')

spec/polish_open_source_rank/web/composition/sitemap_ranking_catalog_spec.rb

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,13 @@
99
ecosystems: ['npm']
1010
)
1111
end
12-
let(:show_ranking_detail) do
13-
lambda do |scope:, kind:, metric:, offset:, **|
14-
next [] unless scope == 'poland' && kind == 'users' && metric == 'top'
15-
16-
offset <= 200 ? [{ login: 'alice' }] : []
17-
end
18-
end
19-
let(:show_language_ranking_detail) do
20-
lambda do |metric:, offset:, **|
21-
metric == 'repository_count' && offset == 100 ? [{ language: 'Ruby' }] : []
22-
end
23-
end
24-
let(:show_package_ranking_detail) do
25-
lambda do |ecosystem:, metric:, offset:, **|
26-
ecosystem == 'npm' && metric == 'downloads_30d' && offset == 100 ? [{ package_name: 'rack' }] : []
27-
end
28-
end
2912
let(:catalog) do
3013
described_class.new(
3114
catalogs: [
32-
PolishOpenSourceRank::Web::Composition::PublicRankingSitemapCatalog.new(
33-
show_ranking_detail: show_ranking_detail
34-
),
35-
PolishOpenSourceRank::Web::Composition::LanguageRankingSitemapCatalog.new(
36-
show_language_ranking_detail: show_language_ranking_detail
37-
),
15+
PolishOpenSourceRank::Web::Composition::PublicRankingSitemapCatalog.new,
16+
PolishOpenSourceRank::Web::Composition::LanguageRankingSitemapCatalog.new,
3817
PolishOpenSourceRank::Web::Composition::PackageRankingSitemapCatalog.new(
39-
package_ranking_read_model: package_ranking_read_model,
40-
show_package_ranking_detail: show_package_ranking_detail
18+
package_ranking_read_model: package_ranking_read_model
4119
)
4220
]
4321
)
@@ -47,17 +25,18 @@
4725
allow(PolishOpenSourceRank::Contexts::Ranking::Domain::LocationCatalog).to receive(:city_slugs).and_return([])
4826
end
4927

50-
it 'adds every non-empty ranking page and stops at the first empty page', :aggregate_failures do
28+
it 'adds canonical ranking pages without probing paginated result sets', :aggregate_failures do
5129
expect(paths).to include(
5230
'/people/users/top',
31+
'/languages/top',
32+
'/packages/npm/top'
33+
)
34+
expect(paths).not_to include(
5335
'/people/users/top/page/2',
5436
'/people/users/top/page/3',
5537
'/languages/top/page/2',
56-
'/packages/npm/top/page/2'
57-
)
58-
expect(paths).not_to include(
59-
'/people/users/top/page/4',
6038
'/languages/top/page/3',
39+
'/packages/npm/top/page/2',
6140
'/packages/npm/top/page/3'
6241
)
6342
end

0 commit comments

Comments
 (0)