docbrown/app/models/data_update_script.rb
Ridhwana 530e927060
Add ability to re-run a data script from the the data update script page (#12424)
* feat: add an error column to the data update script

* feat: save the error to the error field

* feat: save the error when the script fails

* feat: show the script error on the data update script page

* chore: pass the error to mark_as_failed instead of having its own function

* refactor: use presence

* test: ensure that we test an error case of a data update script

* chore: rename errorneous to failing

* test: update some specs, working on the others

* chore: update tests now that there are two files

* chore: change error from a string to a text to allow for more char

* feat: order the data update scripts by the latest script that ran

* feat: when the script has succeeded reset error to nil

* feat: create a model function that will allow the script to be force run

* chore: oops remove the functions form the worker to the model so it can be re-used

* feat: create an endpoint that will call the model method force run when we hit the api by clicking the button

* feat: ensure that the we add an ajax call that calls the controller endpoint

* chore: remove newline

* refactor: change to a more Restful route

* refactor: use Stimulus

* fix: move the code from the model back into the worker so that we can reuse it in the controller

* feat:call the worker in the force_run action and create a show route

* feat: very first draft of using a polling mechanism on the show method after we kickoff the sidekiq job (still need to error handle)

* chore: some syntax changes and unused variables

* fix: call the method correctly with the paramters

* feat: do some error handling

* feat: error handing on the frontend

* chore: use e instead of err

* refactor: just pass the id instead of the whole script

* chore: remove the button

* fix: allow the id to be passed

* feat: handle errors better

* feat: limit the filename column width

* refactor: use a common function to set the banner error

* test: add a test fro rerun button

* test: v1 of the data update script request

* test: write some specs for the js controller

* Update app/controllers/admin/data_update_scripts_controller.rb

Co-authored-by: Michael Kohl <me@citizen428.net>

* tests: update the data worker spec

* chore: clean up the js controller and its tests

* chore: remove whitespaces

* chore: swap the functions based on the controller

* chore: updates to the UI

* chore: remove the standard error catch

* chore: update the alert and error messages

* chore: remove test for error handling for sidekiq run

Co-authored-by: Michael Kohl <me@citizen428.net>
2021-02-02 17:24:39 +02:00

75 lines
1.7 KiB
Ruby

class DataUpdateScript < ApplicationRecord
DIRECTORY = Rails.root.join("lib/data_update_scripts").freeze
NAMESPACE = "DataUpdateScripts".freeze
STATUSES = { enqueued: 0, working: 1, succeeded: 2, failed: 3 }.freeze
enum status: STATUSES
validates :file_name, presence: true, uniqueness: true
validates :status, presence: true
class << self
def scripts_to_run
insert_new_scripts
enqueued.order(file_name: :asc)
end
# true if there are more files on disk or any scripts to run, false otherwise
def scripts_to_run?
db_scripts = DataUpdateScript.pluck(:file_name, :status).to_h
return true if filenames.size > db_scripts.size
return true if db_scripts.values.any? { |s| s.to_sym == :enqueued }
false
end
private
def filenames
Dir.glob("*.rb", base: DIRECTORY).map do |f|
File.basename(f, ".rb")
end
end
def insert_new_scripts
now = Time.current
scripts_params = filenames.map do |fn|
{ file_name: fn, created_at: now, updated_at: now }
end
DataUpdateScript.insert_all(scripts_params)
end
end
def mark_as_run!
update!(run_at: Time.current, status: :working)
end
def mark_as_finished!
update!(finished_at: Time.current, status: :succeeded, error: nil)
end
def mark_as_failed!(err)
update!(
finished_at: Time.current,
status: :failed,
error: "#{err.class}: #{err.message}",
)
end
def file_path
"#{self.class::DIRECTORY}/#{file_name}.rb"
end
def file_class
"#{self.class::NAMESPACE}::#{parsed_file_name.camelcase}".safe_constantize
end
private
def parsed_file_name
file_name.match(/\d{14}_(.*)/)[1]
end
end