Skip to content

Commit

Permalink
Merge pull request #2641 from MushroomObserver/nimmo-recurring-cron
Browse files Browse the repository at this point in the history
Use SolidQueue to run a cron job repopulating Location and Observation center_lat/center_lng
  • Loading branch information
nimmolo authored Jan 10, 2025
2 parents 372af50 + 384a1bd commit ffe6866
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 7 deletions.
29 changes: 29 additions & 0 deletions app/jobs/update_box_area_and_center_columns_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

class UpdateBoxAreaAndCenterColumnsJob < ApplicationJob
queue_as :default

def perform(**args)
args ||= {}
log("Starting UpdateBoxAreaAndCenterColumnsJob.perform")
# This should be zero, but count just in case.
loc_count = Location.where(box_area: nil).count
log("Found #{loc_count} locations without a box_area.")
# Count the observations associated with locations that are under the
# max area, but haven't got a center lat/lng, and log what we're updating.
obs_count = Observation.in_box_of_max_area.where(location_lat: nil).count
log("Found #{obs_count} observations where the associated location was " \
"small enough, but the obs didn't have a location_lat/lng.")
return [loc_count, obs_count] if args[:dry_run]

# Do the update. This returns counts of locations/observations updated.
loc_updated, obs_centered, obs_center_nulled =
Location.update_box_area_and_center_columns

log("Updated #{loc_updated} locations' box_area and center_lat/lng.")
log("Updated #{obs_centered} observations' location_lat/lng.")
log("Nulled #{obs_center_nulled} observations' location_lat/lng.")
# Return the values for debugging
[loc_updated, obs_centered, obs_center_nulled]
end
end
19 changes: 12 additions & 7 deletions app/models/location.rb
Original file line number Diff line number Diff line change
Expand Up @@ -311,17 +311,22 @@ def update_observation_center_columns
# Can populate columns after migration, or be run as part of a recurring job.
def self.update_box_area_and_center_columns
# update the locations
update_all(update_center_and_area_sql)
loc_updated = update_all(update_center_and_area_sql)
# give center points to associated observations in batches by location_id
# Observation must be unscoped in order to join to locations.
# (removing default_scope)
Observation.unscoped.in_box_of_max_area.group(:location_id).update_all(
location_lat: Location[:center_lat], location_lng: Location[:center_lng]
)
obs_centered = Observation.unscoped.
in_box_of_max_area.group(:location_id).update_all(
location_lat: Location[:center_lat],
location_lng: Location[:center_lng]
)
# null center points where area is above the threshold
Observation.unscoped.in_box_gt_max_area.group(:location_id).update_all(
location_lat: nil, location_lng: nil
)
obs_center_nulled = Observation.unscoped.
in_box_gt_max_area.group(:location_id).update_all(
location_lat: nil, location_lng: nil
)
# Return counts
[loc_updated, obs_centered, obs_center_nulled]
end

# Let attached observations update their cache if these fields changed.
Expand Down
4 changes: 4 additions & 0 deletions config/recurring.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@
# a_cleanup_task:
# command: "DeletedStuff.clear_all"
# schedule: every day at 9am
production:
repopulate_location_and_observation_center_lat_lng:
class: UpdateBoxAreaAndCenterColumnsJob
schedule: every day at midnight
30 changes: 30 additions & 0 deletions test/jobs/update_box_area_and_center_columns_job_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require "test_helper"

class UpdateBoxAreaAndCenterColumnsJobTest < ActiveJob::TestCase
def test_update_box_area_and_center_columns
# Check that we have some obs that need updating
assert_not_empty(Observation.in_box_of_max_area.where(location_lat: nil))

job = UpdateBoxAreaAndCenterColumnsJob.new
job.perform

assert_empty(Observation.in_box_of_max_area.where(location_lat: nil))
# NOTE: All locations may already have a box_area, so probably nil before
assert_empty(Location.where(box_area: nil))
end

def test_update_box_area_dry_run
# Check that we have some obs that need updating
assert_not_empty(Observation.in_box_of_max_area.where(location_lat: nil))

job = UpdateBoxAreaAndCenterColumnsJob.new
_loc_count, obs_count = job.perform(dry_run: true)

# check it again and be sure it did NOT update the obs
needs_update = Observation.in_box_of_max_area.where(location_lat: nil)
assert_not_empty(needs_update)
assert_equal(obs_count, needs_update.count)
end
end

0 comments on commit ffe6866

Please sign in to comment.