Fix stats calculation to recursively reduce H3 resolution when too many hexagons are generated

This commit is contained in:
Eugene Burmakin 2025-12-26 15:39:04 +01:00
parent 3c1d17b806
commit 45d4aa815f
3 changed files with 36 additions and 3 deletions

View file

@ -1 +1 @@
0.36.4
0.36.5

View file

@ -53,8 +53,8 @@ class Stats::HexagonCalculator
# Try with lower resolution (larger hexagons)
lower_resolution = [h3_resolution - 2, 0].max
Rails.logger.info "Recalculating with lower H3 resolution: #{lower_resolution}"
# Create a new instance with lower resolution for recursion
return self.class.new(user.id, year, month).calculate_hexagons(lower_resolution)
# Recursively call with lower resolution
return calculate_hexagons(lower_resolution)
end
Rails.logger.info "Generated #{h3_hash.size} H3 hexagons at resolution #{h3_resolution} for user #{user.id}"

View file

@ -62,6 +62,39 @@ RSpec.describe Stats::HexagonCalculator do
expect(total_points).to eq(2)
end
context 'when there are too many hexagons' do
let(:h3_resolution) { 15 } # Very high resolution to trigger MAX_HEXAGONS
before do
# Stub to simulate too many hexagons on first call, then acceptable on second
allow_any_instance_of(described_class).to receive(:calculate_h3_indexes).and_call_original
call_count = 0
allow_any_instance_of(described_class).to receive(:calculate_h3_indexes) do |instance, points, resolution|
call_count += 1
if call_count == 1
# First call: return too many hexagons
Hash.new.tap do |hash|
(described_class::MAX_HEXAGONS + 1).times do |i|
hash[i.to_s(16)] = [1, timestamp1, timestamp1]
end
end
else
# Second call with lower resolution: return acceptable amount
{ '8c2a1072b3f1fff' => [2, timestamp1, timestamp2] }
end
end
end
it 'recursively reduces resolution when too many hexagons are generated' do
result = calculate_hexagons
expect(result).to be_an(Array)
expect(result).not_to be_empty
# Should have successfully reduced the hexagon count
expect(result.size).to be < described_class::MAX_HEXAGONS
end
end
context 'when H3 raises an error' do
before do
allow(H3).to receive(:from_geo_coordinates).and_raise(StandardError, 'H3 error')