* 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>
75 lines
1.7 KiB
Ruby
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
|