mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-03-24 17:04:43 +00:00
Upgraded to rails 8.0.2, moved from dalli to solid cache, moved from delayed_job to solid queue, and add solid cable. deploy/rails-dev-run.sh no longer needs to chmod. Fixed finished_at callback for matches. Migrated from Devise to built in rails auth. Added view tests for the bracket page testing that all bout numbers render for all matches in each bracket type.
This commit is contained in:
35
lib/tasks/auth_migration.rake
Normal file
35
lib/tasks/auth_migration.rake
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace :auth do
|
||||
desc "Migrate from Devise to Rails Authentication"
|
||||
task migrate: :environment do
|
||||
puts "Running Authentication Migration"
|
||||
puts "================================"
|
||||
|
||||
# Run the migrations
|
||||
Rake::Task["db:migrate"].invoke
|
||||
|
||||
# Ensure all existing users have a password_digest value
|
||||
users_without_digest = User.where(password_digest: nil)
|
||||
|
||||
if users_without_digest.any?
|
||||
puts "Setting password_digest for #{users_without_digest.count} users..."
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
users_without_digest.each do |user|
|
||||
if user.encrypted_password.present?
|
||||
# Copy Devise's encrypted_password to password_digest
|
||||
# This works because both use bcrypt in the same format
|
||||
user.update_column(:password_digest, user.encrypted_password)
|
||||
print "."
|
||||
else
|
||||
puts "\nWARNING: User #{user.id} (#{user.email}) has no encrypted_password!"
|
||||
end
|
||||
end
|
||||
end
|
||||
puts "\nDone!"
|
||||
else
|
||||
puts "All users already have a password_digest."
|
||||
end
|
||||
|
||||
puts "Migration complete."
|
||||
end
|
||||
end
|
||||
506
lib/tasks/job_testing.rake
Normal file
506
lib/tasks/job_testing.rake
Normal file
@@ -0,0 +1,506 @@
|
||||
namespace :jobs do
|
||||
desc "Create a test running job for the first tournament"
|
||||
task create_running: :environment do
|
||||
# Find the first tournament
|
||||
tournament = Tournament.first
|
||||
|
||||
unless tournament
|
||||
puts "No tournaments found. Please create a tournament first."
|
||||
exit 1
|
||||
end
|
||||
|
||||
# Create a process record
|
||||
process = SolidQueue::Process.create!(
|
||||
kind: 'worker',
|
||||
last_heartbeat_at: Time.now,
|
||||
pid: Process.pid,
|
||||
name: 'test_worker',
|
||||
created_at: Time.now,
|
||||
hostname: 'test'
|
||||
)
|
||||
|
||||
# Create a job for the tournament
|
||||
job = SolidQueue::Job.create!(
|
||||
queue_name: 'default',
|
||||
class_name: 'TournamentBackupJob',
|
||||
arguments: JSON.generate([tournament.id, "Test job", tournament.id, "Test running job"]),
|
||||
priority: 0,
|
||||
active_job_id: SecureRandom.uuid,
|
||||
created_at: Time.now,
|
||||
updated_at: Time.now,
|
||||
job_owner_id: tournament.id,
|
||||
job_owner_type: "Test running job"
|
||||
)
|
||||
|
||||
# Create a claimed execution to mark it as running
|
||||
SolidQueue::ClaimedExecution.create!(
|
||||
job_id: job.id,
|
||||
process_id: process.id,
|
||||
created_at: Time.now
|
||||
)
|
||||
|
||||
puts "Created running job for tournament #{tournament.id} - #{tournament.name}"
|
||||
puts "Job ID: #{job.id}"
|
||||
end
|
||||
|
||||
desc "Create a test completed job for the first tournament"
|
||||
task create_completed: :environment do
|
||||
# Find the first tournament
|
||||
tournament = Tournament.first
|
||||
|
||||
unless tournament
|
||||
puts "No tournaments found. Please create a tournament first."
|
||||
exit 1
|
||||
end
|
||||
|
||||
# Create a job for the tournament
|
||||
job = SolidQueue::Job.create!(
|
||||
queue_name: 'default',
|
||||
class_name: 'TournamentBackupJob',
|
||||
arguments: JSON.generate([tournament.id, "Test job", tournament.id, "Test completed job"]),
|
||||
priority: 0,
|
||||
active_job_id: SecureRandom.uuid,
|
||||
created_at: Time.now,
|
||||
updated_at: Time.now,
|
||||
finished_at: Time.now - 5.minutes,
|
||||
job_owner_id: tournament.id,
|
||||
job_owner_type: "Test completed job"
|
||||
)
|
||||
|
||||
puts "Created completed job for tournament #{tournament.id} - #{tournament.name}"
|
||||
puts "Job ID: #{job.id}"
|
||||
end
|
||||
|
||||
desc "Create a test failed job for the first tournament"
|
||||
task create_failed: :environment do
|
||||
# Find the first tournament
|
||||
tournament = Tournament.first
|
||||
|
||||
unless tournament
|
||||
puts "No tournaments found. Please create a tournament first."
|
||||
exit 1
|
||||
end
|
||||
|
||||
# Create a job for the tournament
|
||||
job = SolidQueue::Job.create!(
|
||||
queue_name: 'default',
|
||||
class_name: 'TournamentBackupJob',
|
||||
arguments: JSON.generate([tournament.id, "Test job", tournament.id, "Test failed job"]),
|
||||
priority: 0,
|
||||
active_job_id: SecureRandom.uuid,
|
||||
created_at: Time.now,
|
||||
updated_at: Time.now,
|
||||
finished_at: Time.now - 5.minutes,
|
||||
job_owner_id: tournament.id,
|
||||
job_owner_type: "Test failed job"
|
||||
)
|
||||
|
||||
# Create a failed execution record
|
||||
SolidQueue::FailedExecution.create!(
|
||||
job_id: job.id,
|
||||
error: "Test error message",
|
||||
created_at: Time.now
|
||||
)
|
||||
|
||||
puts "Created failed job for tournament #{tournament.id} - #{tournament.name}"
|
||||
puts "Job ID: #{job.id}"
|
||||
end
|
||||
|
||||
desc "Test job owner metadata persistence"
|
||||
task test_metadata: :environment do
|
||||
# Find the first tournament
|
||||
tournament = Tournament.first
|
||||
|
||||
unless tournament
|
||||
puts "No tournaments found. Please create a tournament first."
|
||||
exit 1
|
||||
end
|
||||
|
||||
# Create a job with the new method
|
||||
puts "Creating a test job with job_owner_id: #{tournament.id} and job_owner_type: 'Test metadata job'"
|
||||
|
||||
# Create a direct ActiveJob
|
||||
job = TournamentBackupJob.new(tournament, "Test metadata job")
|
||||
job.job_owner_id = tournament.id
|
||||
job.job_owner_type = "Test metadata job"
|
||||
|
||||
# Enqueue it
|
||||
job_id = job.enqueue
|
||||
|
||||
# Wait a moment for it to be saved
|
||||
sleep(1)
|
||||
|
||||
# Find the job in SolidQueue
|
||||
sq_job = SolidQueue::Job.find_by(active_job_id: job.job_id)
|
||||
|
||||
if sq_job
|
||||
puts "Job created and found in SolidQueue table:"
|
||||
puts " ID: #{sq_job.id}"
|
||||
puts " Active Job ID: #{sq_job.active_job_id}"
|
||||
|
||||
# Extract metadata
|
||||
begin
|
||||
job_data = JSON.parse(sq_job.serialized_arguments)
|
||||
puts " Raw serialized_arguments: #{sq_job.serialized_arguments}"
|
||||
|
||||
if job_data.is_a?(Hash) && job_data["job_data"]
|
||||
puts " Job data found:"
|
||||
puts " job_owner_id: #{job_data["job_data"]["job_owner_id"]}"
|
||||
puts " job_owner_type: #{job_data["job_data"]["job_owner_type"]}"
|
||||
else
|
||||
puts " No job_data found in serialized arguments"
|
||||
end
|
||||
rescue JSON::ParserError
|
||||
puts " Error parsing serialized arguments: #{sq_job.serialized_arguments}"
|
||||
end
|
||||
|
||||
# Test the metadata method
|
||||
metadata = SolidQueueJobExtensions.instance_methods.include?(:metadata) ?
|
||||
sq_job.metadata :
|
||||
"metadata method not available"
|
||||
puts " Metadata method result: #{metadata.inspect}"
|
||||
|
||||
# Test the individual accessors
|
||||
if SolidQueueJobExtensions.instance_methods.include?(:job_owner_id) &&
|
||||
SolidQueueJobExtensions.instance_methods.include?(:job_owner_type)
|
||||
puts " job_owner_id method: #{sq_job.job_owner_id}"
|
||||
puts " job_owner_type method: #{sq_job.job_owner_type}"
|
||||
else
|
||||
puts " Job owner accessor methods not available"
|
||||
end
|
||||
else
|
||||
puts "Job not found in SolidQueue table. Check for errors."
|
||||
end
|
||||
end
|
||||
|
||||
desc "Check existing job metadata"
|
||||
task check_jobs: :environment do
|
||||
puts "Checking existing jobs in SolidQueue table"
|
||||
|
||||
# Find recent jobs
|
||||
jobs = SolidQueue::Job.order(created_at: :desc).limit(5)
|
||||
|
||||
if jobs.empty?
|
||||
puts "No jobs found in SolidQueue table."
|
||||
exit 0
|
||||
end
|
||||
|
||||
puts "Found #{jobs.count} jobs:"
|
||||
|
||||
jobs.each_with_index do |job, index|
|
||||
puts "\nJob ##{index + 1}:"
|
||||
puts " ID: #{job.id}"
|
||||
puts " Class: #{job.class_name}"
|
||||
puts " Created at: #{job.created_at}"
|
||||
|
||||
# Display the raw serialized arguments
|
||||
puts " Raw arguments:"
|
||||
puts " #{job.arguments.to_s[0..200]}..."
|
||||
|
||||
# Parse the serialized arguments to extract relevant parts
|
||||
begin
|
||||
args_data = job.arguments.is_a?(Hash) ? job.arguments : JSON.parse(job.arguments)
|
||||
if args_data.is_a?(Hash) && args_data["arguments"].is_a?(Array)
|
||||
puts " Arguments array:"
|
||||
args_data["arguments"].each_with_index do |arg, i|
|
||||
puts " [#{i}]: #{arg.inspect}"
|
||||
end
|
||||
end
|
||||
rescue JSON::ParserError
|
||||
puts " Error: Could not parse arguments"
|
||||
rescue => e
|
||||
puts " Error: #{e.message}"
|
||||
end
|
||||
|
||||
# Test the metadata extraction method
|
||||
metadata = job.respond_to?(:metadata) ? job.metadata : nil
|
||||
puts " Extracted metadata: #{metadata.inspect}"
|
||||
|
||||
if job.respond_to?(:job_owner_id) && job.respond_to?(:job_owner_type)
|
||||
puts " job_owner_id: #{job.job_owner_id}"
|
||||
puts " job_owner_type: #{job.job_owner_type}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc "Test create a tournament backup job with metadata"
|
||||
task create_test_backup_job: :environment do
|
||||
puts "Creating a test TournamentBackupJob with job owner metadata"
|
||||
|
||||
# Find a tournament to use
|
||||
tournament = Tournament.first
|
||||
|
||||
if tournament.nil?
|
||||
puts "No tournament found in the database. Creating a test tournament."
|
||||
tournament = Tournament.create!(name: "Test Tournament", tournament_type: 0)
|
||||
end
|
||||
|
||||
puts "Using tournament ##{tournament.id}: #{tournament.name}"
|
||||
|
||||
# Set test job owner metadata
|
||||
job_owner_id = 999
|
||||
job_owner_type = "Test Backup Creation"
|
||||
|
||||
# Create the job with owner metadata
|
||||
job = TournamentBackupJob.perform_later(tournament, "Test backup", job_owner_id, job_owner_type)
|
||||
puts "Created job with ID: #{job.job_id}"
|
||||
|
||||
# Retrieve the job from the database to verify metadata
|
||||
puts "\nChecking job in the database:"
|
||||
sleep(1) # Give a moment for the job to be persisted
|
||||
|
||||
solid_job = SolidQueue::Job.order(created_at: :desc).first
|
||||
|
||||
if solid_job
|
||||
puts "Found job ##{solid_job.id} (#{solid_job.class_name})"
|
||||
|
||||
begin
|
||||
# Parse the arguments
|
||||
arg_data = solid_job.arguments
|
||||
if arg_data.is_a?(String)
|
||||
begin
|
||||
arg_data = JSON.parse(arg_data)
|
||||
rescue JSON::ParserError => e
|
||||
puts "Failed to parse arguments as JSON: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
if arg_data.is_a?(Hash) && arg_data["arguments"].is_a?(Array)
|
||||
puts "Arguments:"
|
||||
arg_data["arguments"].each_with_index do |arg, i|
|
||||
puts " [#{i}]: #{arg.inspect.truncate(100)}"
|
||||
end
|
||||
|
||||
# Check if we can extract metadata
|
||||
metadata = solid_job.metadata rescue nil
|
||||
if metadata
|
||||
puts "Extracted metadata: #{metadata.inspect}"
|
||||
puts "job_owner_id: #{metadata['job_owner_id']}"
|
||||
puts "job_owner_type: #{metadata['job_owner_type']}"
|
||||
else
|
||||
puts "No metadata method available"
|
||||
end
|
||||
else
|
||||
puts "No arguments array found in job data"
|
||||
end
|
||||
rescue => e
|
||||
puts "Error inspecting job: #{e.message}"
|
||||
end
|
||||
else
|
||||
puts "No job found in the database"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Debug tournament job detection for a specific tournament"
|
||||
task debug_tournament_jobs: :environment do
|
||||
tournament_id = ENV['TOURNAMENT_ID']
|
||||
|
||||
if tournament_id.blank?
|
||||
puts "Usage: rake jobs:debug_tournament_jobs TOURNAMENT_ID=123"
|
||||
exit 1
|
||||
end
|
||||
|
||||
tournament = Tournament.find_by(id: tournament_id)
|
||||
|
||||
if tournament.nil?
|
||||
puts "Tournament not found with id: #{tournament_id}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
puts "== Debugging job detection for Tournament ##{tournament.id}: #{tournament.name} =="
|
||||
|
||||
# Get all jobs
|
||||
all_jobs = SolidQueue::Job.all
|
||||
puts "Total jobs in system: #{all_jobs.count}"
|
||||
|
||||
# Test each condition independently to see which jobs match
|
||||
condition1_jobs = all_jobs.select do |job|
|
||||
if job.respond_to?(:job_owner_id) && job.job_owner_id.present?
|
||||
job.job_owner_id.to_s == tournament.id.to_s
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
condition2_jobs = all_jobs.select do |job|
|
||||
if job.respond_to?(:metadata)
|
||||
metadata = job.metadata
|
||||
metadata["job_owner_id"].present? && metadata["job_owner_id"].to_s == tournament.id.to_s
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
condition3_jobs = all_jobs.select do |job|
|
||||
if job.arguments.present?
|
||||
begin
|
||||
args_data = job.arguments.is_a?(Hash) ? job.arguments : JSON.parse(job.arguments.to_s)
|
||||
if args_data.is_a?(Hash) && args_data["arguments"].is_a?(Array) && args_data["arguments"][0].present?
|
||||
args_data["arguments"][0].to_s == tournament.id.to_s
|
||||
else
|
||||
false
|
||||
end
|
||||
rescue
|
||||
false
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
puts "Jobs matching condition 1 (direct job_owner_id): #{condition1_jobs.count}"
|
||||
puts "Jobs matching condition 2 (metadata method): #{condition2_jobs.count}"
|
||||
puts "Jobs matching condition 3 (first argument): #{condition3_jobs.count}"
|
||||
|
||||
# Test the actual method
|
||||
tournament_jobs = tournament.deferred_jobs
|
||||
puts "Jobs returned by tournament.deferred_jobs: #{tournament_jobs.count}"
|
||||
|
||||
# Show details about each job
|
||||
if tournament_jobs.any?
|
||||
puts "\nDetails of jobs found by tournament.deferred_jobs:"
|
||||
tournament_jobs.each_with_index do |job, index|
|
||||
puts "\nJob ##{index + 1} (ID: #{job.id}):"
|
||||
puts " Class: #{job.class_name}"
|
||||
|
||||
# Try to get metadata
|
||||
if job.respond_to?(:metadata)
|
||||
metadata = job.metadata
|
||||
puts " Metadata: #{metadata.inspect}"
|
||||
end
|
||||
|
||||
# Display raw arguments
|
||||
begin
|
||||
if job.arguments.is_a?(String) && job.arguments.present?
|
||||
parsed = JSON.parse(job.arguments)
|
||||
args = parsed["arguments"] if parsed.is_a?(Hash)
|
||||
puts " Arguments: #{args.inspect}" if args
|
||||
elsif job.arguments.is_a?(Hash) && job.arguments["arguments"].present?
|
||||
puts " Arguments: #{job.arguments["arguments"].inspect}"
|
||||
end
|
||||
rescue => e
|
||||
puts " Error parsing arguments: #{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc "Scan all jobs to detect job owner IDs"
|
||||
task scan_jobs: :environment do
|
||||
puts "Scanning all SolidQueue jobs to detect job owner information"
|
||||
|
||||
all_jobs = SolidQueue::Job.all.order(created_at: :desc)
|
||||
puts "Found #{all_jobs.count} total jobs"
|
||||
|
||||
# Group by job type
|
||||
job_types = all_jobs.group_by(&:class_name)
|
||||
puts "\nJobs by type:"
|
||||
job_types.each do |type, jobs|
|
||||
puts " #{type}: #{jobs.count} jobs"
|
||||
end
|
||||
|
||||
# Go through each job and extract job owner info
|
||||
owner_info = {}
|
||||
|
||||
all_jobs.each do |job|
|
||||
owner_id = nil
|
||||
owner_type = nil
|
||||
tournament_id = nil
|
||||
|
||||
# Method 1: Check direct job_owner_id attribute
|
||||
if job.respond_to?(:job_owner_id) && job.job_owner_id.present?
|
||||
owner_id = job.job_owner_id
|
||||
end
|
||||
|
||||
# Method 2: Check metadata method
|
||||
if job.respond_to?(:metadata)
|
||||
metadata = job.metadata
|
||||
if metadata.is_a?(Hash) && metadata["job_owner_id"].present?
|
||||
owner_id ||= metadata["job_owner_id"]
|
||||
owner_type = metadata["job_owner_type"]
|
||||
end
|
||||
end
|
||||
|
||||
# Method 3: Extract tournament ID from the arguments
|
||||
if job.arguments.present?
|
||||
arg_data = job.arguments
|
||||
|
||||
# Handle hash arguments
|
||||
if arg_data.is_a?(Hash) && arg_data["arguments"].is_a?(Array) && arg_data["arguments"].first.present?
|
||||
first_arg = arg_data["arguments"].first
|
||||
|
||||
# Check if the first argument is a Tournament global ID
|
||||
if first_arg.is_a?(Hash) && first_arg["_aj_globalid"].present?
|
||||
global_id = first_arg["_aj_globalid"]
|
||||
if global_id.to_s.include?("/Tournament/")
|
||||
tournament_id = global_id.to_s.split("/Tournament/").last
|
||||
end
|
||||
else
|
||||
# Direct ID - assume it's a tournament ID
|
||||
tournament_id = first_arg.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# If it's a string, try to parse
|
||||
if arg_data.is_a?(String)
|
||||
begin
|
||||
parsed = JSON.parse(arg_data)
|
||||
if parsed.is_a?(Hash) && parsed["arguments"].is_a?(Array) && parsed["arguments"].first.present?
|
||||
first_arg = parsed["arguments"].first
|
||||
|
||||
# Check if the first argument is a Tournament global ID
|
||||
if first_arg.is_a?(Hash) && first_arg["_aj_globalid"].present?
|
||||
global_id = first_arg["_aj_globalid"]
|
||||
if global_id.to_s.include?("/Tournament/")
|
||||
tournament_id = global_id.to_s.split("/Tournament/").last
|
||||
end
|
||||
else
|
||||
# Direct ID - assume it's a tournament ID
|
||||
tournament_id = first_arg.to_s
|
||||
end
|
||||
end
|
||||
rescue
|
||||
# Ignore parsing errors
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Record what we found
|
||||
owner_info[job.id] = {
|
||||
job_id: job.id,
|
||||
class_name: job.class_name,
|
||||
owner_id: owner_id,
|
||||
owner_type: owner_type,
|
||||
tournament_id: tournament_id,
|
||||
created_at: job.created_at
|
||||
}
|
||||
end
|
||||
|
||||
# Group by tournament ID
|
||||
tournament_groups = owner_info.values.group_by { |info| info[:tournament_id] }
|
||||
|
||||
puts "\nJobs by tournament ID:"
|
||||
tournament_groups.each do |tournament_id, jobs|
|
||||
next if tournament_id.nil?
|
||||
tournament = Tournament.find_by(id: tournament_id) rescue nil
|
||||
tournament_name = tournament ? tournament.name : "Unknown"
|
||||
puts " Tournament ##{tournament_id} (#{tournament_name}): #{jobs.count} jobs"
|
||||
|
||||
# Sample job details
|
||||
sample = jobs.first
|
||||
puts " Sample job: #{sample[:class_name]} (ID: #{sample[:job_id]})"
|
||||
puts " Created at: #{sample[:created_at]}"
|
||||
puts " Owner ID: #{sample[:owner_id]}"
|
||||
puts " Owner Type: #{sample[:owner_type]}"
|
||||
end
|
||||
|
||||
# Orphaned jobs
|
||||
orphaned = owner_info.values.select { |info| info[:tournament_id].nil? }
|
||||
if orphaned.any?
|
||||
puts "\nOrphaned jobs (no tournament ID detected): #{orphaned.count} jobs"
|
||||
orphaned.first(5).each do |job|
|
||||
puts " #{job[:class_name]} (ID: #{job[:job_id]}) created at #{job[:created_at]}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user