1
0
mirror of https://github.com/jcwimer/wrestlingApp synced 2026-03-25 01:14:43 +00:00

Added a separate table to record background job status for tournaments and fixed migrations/schemas for solid dbs. Foreign key constraints are now added to the migrations where we do belongs_to.

This commit is contained in:
2025-04-15 16:16:44 -04:00
parent 4828d9b876
commit 6e61a7245a
37 changed files with 678 additions and 1169 deletions

View File

@@ -9,8 +9,31 @@ class AdvanceWrestlerJob < ApplicationJob
end
def perform(wrestler, match)
# Execute the job
service = AdvanceWrestler.new(wrestler, match)
service.advance_raw
# Get tournament from wrestler
tournament = wrestler.tournament
# Create job status record
job_name = "Advancing wrestler #{wrestler.name}"
job_status = TournamentJobStatus.create!(
tournament: tournament,
job_name: job_name,
status: "Running",
details: "Match ID: #{match&.bout_number || 'No match'}"
)
begin
# Execute the job
service = AdvanceWrestler.new(wrestler, match)
service.advance_raw
# Remove the job status record on success
TournamentJobStatus.complete_job(tournament.id, job_name)
rescue => e
# Update status to errored
job_status.update(status: "Errored", details: "Error: #{e.message}")
# Re-raise the error for SolidQueue to handle
raise e
end
end
end

View File

@@ -11,7 +11,28 @@ class CalculateSchoolScoreJob < ApplicationJob
# Log information about the job
Rails.logger.info("Calculating score for school ##{school.id} (#{school.name})")
# Execute the calculation
school.calculate_score_raw
# Create job status record
tournament = school.tournament
job_name = "Calculating team score for #{school.name}"
job_status = TournamentJobStatus.create!(
tournament: tournament,
job_name: job_name,
status: "Running",
details: "School ID: #{school.id}"
)
begin
# Execute the calculation
school.calculate_score_raw
# Remove the job status record on success
TournamentJobStatus.complete_job(tournament.id, job_name)
rescue => e
# Update status to errored
job_status.update(status: "Errored", details: "Error: #{e.message}")
# Re-raise the error for SolidQueue to handle
raise e
end
end
end

View File

@@ -12,8 +12,28 @@ class TournamentBackupJob < ApplicationJob
# Log information about the job
Rails.logger.info("Creating backup for tournament ##{tournament.id} (#{tournament.name}), reason: #{reason || 'manual'}")
# Execute the backup
service = TournamentBackupService.new(tournament, reason)
service.create_backup_raw
# Create job status record
job_name = "Backing up tournament"
job_status = TournamentJobStatus.create!(
tournament: tournament,
job_name: job_name,
status: "Running",
details: "Reason: #{reason || 'manual'}"
)
begin
# Execute the backup
service = TournamentBackupService.new(tournament, reason)
service.create_backup_raw
# Remove the job status record on success
TournamentJobStatus.complete_job(tournament.id, job_name)
rescue => e
# Update status to errored
job_status.update(status: "Errored", details: "Error: #{e.message}")
# Re-raise the error for SolidQueue to handle
raise e
end
end
end

View File

@@ -13,9 +13,29 @@ class WrestlingdevImportJob < ApplicationJob
# Log information about the job
Rails.logger.info("Starting import for tournament ##{tournament.id} (#{tournament.name})")
# Execute the import
importer = WrestlingdevImporter.new(tournament)
importer.import_data = import_data if import_data
importer.import_raw
# Create job status record
job_name = "Importing tournament"
job_status = TournamentJobStatus.create!(
tournament: tournament,
job_name: job_name,
status: "Running",
details: "Processing backup data"
)
begin
# Execute the import
importer = WrestlingdevImporter.new(tournament)
importer.import_data = import_data if import_data
importer.import_raw
# Remove the job status record on success
TournamentJobStatus.complete_job(tournament.id, job_name)
rescue => e
# Update status to errored
job_status.update(status: "Errored", details: "Error: #{e.message}")
# Re-raise the error for SolidQueue to handle
raise e
end
end
end

View File

@@ -1,6 +1,6 @@
class Mat < ApplicationRecord
belongs_to :tournament
has_many :matches
has_many :matches, dependent: :destroy
has_many :mat_assignment_rules, dependent: :destroy
validates :name, presence: true

View File

@@ -1,8 +1,8 @@
class School < ApplicationRecord
belongs_to :tournament, touch: true
has_many :wrestlers, dependent: :destroy
has_many :deductedPoints, class_name: "Teampointadjust"
has_many :delegates, class_name: "SchoolDelegate"
has_many :deductedPoints, class_name: "Teampointadjust", dependent: :destroy
has_many :delegates, class_name: "SchoolDelegate", dependent: :destroy
validates :name, presence: true

View File

@@ -6,9 +6,10 @@ class Tournament < ApplicationRecord
has_many :mats, dependent: :destroy
has_many :wrestlers, through: :weights
has_many :matches, dependent: :destroy
has_many :delegates, class_name: "TournamentDelegate"
has_many :delegates, class_name: "TournamentDelegate", dependent: :destroy
has_many :mat_assignment_rules, dependent: :destroy
has_many :tournament_backups, dependent: :destroy
has_many :tournament_job_statuses, dependent: :destroy
validates :date, :name, :tournament_type, :address, :director, :director_email , presence: true
@@ -263,6 +264,16 @@ class Tournament < ApplicationRecord
return error_string.blank?
end
# Check if there are any active jobs for this tournament
def has_active_jobs?
tournament_job_statuses.active.exists?
end
# Get all active jobs for this tournament
def active_jobs
tournament_job_statuses.active
end
private
def connection_adapter

View File

@@ -0,0 +1,22 @@
class TournamentJobStatus < ApplicationRecord
belongs_to :tournament, optional: false
# Validations
validates :job_name, presence: true
validates :status, presence: true
validates_inclusion_of :status, in: ["Queued", "Running", "Errored"], allow_nil: false
validates :tournament, presence: true
# Scopes
scope :active, -> { where.not(status: "Errored") }
# Class methods to find jobs for a tournament
def self.for_tournament(tournament)
where(tournament_id: tournament.id)
end
# Clean up completed jobs (should be called when job finishes successfully)
def self.complete_job(tournament_id, job_name)
where(tournament_id: tournament_id, job_name: job_name).destroy_all
end
end

View File

@@ -4,8 +4,8 @@ class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
has_many :tournaments
has_many :delegated_tournament_permissions, class_name: "TournamentDelegate"
has_many :delegated_school_permissions, class_name: "SchoolDelegate"
has_many :delegated_tournament_permissions, class_name: "TournamentDelegate", dependent: :destroy
has_many :delegated_school_permissions, class_name: "SchoolDelegate", dependent: :destroy
# Replace Devise with has_secure_password
has_secure_password

View File

@@ -3,7 +3,7 @@ class Wrestler < ApplicationRecord
belongs_to :weight, touch: true
has_one :tournament, through: :weight
has_many :matches, through: :weight
has_many :deductedPoints, class_name: "Teampointadjust"
has_many :deductedPoints, class_name: "Teampointadjust", dependent: :destroy
attr_accessor :poolAdvancePoints, :originalId, :swapId
validates :name, :weight_id, :school_id, presence: true

View File

@@ -31,14 +31,19 @@ class WrestlingdevImporter
end
def destroy_all
@tournament.mat_assignment_rules.destroy_all
@tournament.mats.destroy_all
# These depend directly on @tournament and will cascade deletes
# due to `dependent: :destroy` in the Tournament model
@tournament.schools.destroy_all # Cascades to Wrestlers, Teampointadjusts, SchoolDelegates
@tournament.weights.destroy_all # Cascades to Wrestlers, Matches
@tournament.mats.destroy_all # Cascades to Matches, MatAssignmentRules
# Explicitly destroy matches again just in case some aren't linked via mats/weights? Unlikely but safe.
# Also handles matches linked directly to tournament if that's possible.
@tournament.matches.destroy_all
@tournament.schools.each do |school|
school.wrestlers.destroy_all
school.destroy
end
@tournament.weights.destroy_all
@tournament.mat_assignment_rules.destroy_all # Explicitly destroy rules (might be redundant if Mat cascades)
@tournament.delegates.destroy_all
@tournament.tournament_backups.destroy_all
@tournament.tournament_job_statuses.destroy_all
# Note: Teampointadjusts are deleted via School/Wrestler cascade
end
def parse_data

View File

@@ -9,6 +9,19 @@
</div>
<% end %>
<% if (can? :manage, @tournament) && @tournament.has_active_jobs? %>
<div class="alert alert-info">
<strong>Background Jobs In Progress</strong>
<p>The following background jobs are currently running:</p>
<ul>
<% @tournament.active_jobs.each do |job| %>
<li><%= job.job_name %> - <%= job.status %> <%= "(#{job.details})" if job.details.present? %></li>
<% end %>
</ul>
<p>Please refresh the page to check progress.</p>
</div>
<% end %>
<p>
<strong>Address:</strong>
<%= @tournament.address %>