mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-04-09 07:39:06 +00:00
Added a daily recurring job to cleanup tournaments .
This commit is contained in:
36
app/jobs/tournament_cleanup_job.rb
Normal file
36
app/jobs/tournament_cleanup_job.rb
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
class TournamentCleanupJob < ApplicationJob
|
||||||
|
queue_as :default
|
||||||
|
|
||||||
|
def perform
|
||||||
|
# Remove or clean up tournaments based on age and match status
|
||||||
|
process_old_tournaments
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def process_old_tournaments
|
||||||
|
# Get all tournaments older than 1 week that have a user_id
|
||||||
|
old_tournaments = Tournament.where('date < ? AND user_id IS NOT NULL', 1.week.ago.to_date)
|
||||||
|
|
||||||
|
old_tournaments.each do |tournament|
|
||||||
|
# Check if it has any non-BYE finished matches
|
||||||
|
has_real_matches = tournament.matches.where(finished: 1).where.not(win_type: 'BYE').exists?
|
||||||
|
|
||||||
|
if has_real_matches
|
||||||
|
|
||||||
|
# 1. Remove all school delegates
|
||||||
|
tournament.schools.each do |school|
|
||||||
|
school.delegates.destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
# 2. Remove all tournament delegates
|
||||||
|
tournament.delegates.destroy_all
|
||||||
|
|
||||||
|
# 3. Set user_id to null
|
||||||
|
tournament.update(user_id: nil)
|
||||||
|
else
|
||||||
|
tournament.destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -17,4 +17,6 @@ docker build -t $1 -f ${project_dir}/deploy/rails-dev-Dockerfile \
|
|||||||
|
|
||||||
docker run --rm -it -p 3000:3000 \
|
docker run --rm -it -p 3000:3000 \
|
||||||
-v ${project_dir}:/rails \
|
-v ${project_dir}:/rails \
|
||||||
|
-v /etc/localtime:/etc/localtime:ro \
|
||||||
|
-v /etc/timezone:/etc/timezone:ro \
|
||||||
$1 /bin/bash
|
$1 /bin/bash
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
# production:
|
production:
|
||||||
# periodic_cleanup:
|
tournament_cleanup_job:
|
||||||
# class: CleanSoftDeletedRecordsJob
|
class: TournamentCleanupJob
|
||||||
# queue: background
|
schedule: every day at 3am
|
||||||
# args: [ 1000, { batch_size: 500 } ]
|
queue: default
|
||||||
# schedule: every hour
|
|
||||||
# periodic_command:
|
development:
|
||||||
# command: "SoftDeletedRecord.due.delete_all"
|
tournament_cleanup_job:
|
||||||
# priority: 2
|
class: TournamentCleanupJob
|
||||||
# schedule: at 5am every day
|
schedule: every day at 3am
|
||||||
|
queue: default
|
||||||
@@ -27,7 +27,13 @@ describe('Create a tournament', () => {
|
|||||||
cy.get('input[name="tournament[address]"]').type('123 Wrestling Way');
|
cy.get('input[name="tournament[address]"]').type('123 Wrestling Way');
|
||||||
cy.get('input[name="tournament[director]"]').type('John Doe');
|
cy.get('input[name="tournament[director]"]').type('John Doe');
|
||||||
cy.get('input[name="tournament[director_email]"]').type('john.doe@example.com');
|
cy.get('input[name="tournament[director_email]"]').type('john.doe@example.com');
|
||||||
cy.get('input[name="tournament[date]"]').type('2024-12-31');
|
|
||||||
|
// Set date to 1 month from today dynamically
|
||||||
|
const futureDate = new Date();
|
||||||
|
futureDate.setMonth(futureDate.getMonth() + 1);
|
||||||
|
const formattedDate = futureDate.toISOString().split('T')[0]; // Format as YYYY-MM-DD
|
||||||
|
cy.get('input[name="tournament[date]"]').type(formattedDate);
|
||||||
|
|
||||||
cy.get('select[name="tournament[tournament_type]"]').select('Pool to bracket');
|
cy.get('select[name="tournament[tournament_type]"]').select('Pool to bracket');
|
||||||
// cy.get('input[name="tournament[is_public]"]').check();
|
// cy.get('input[name="tournament[is_public]"]').check();
|
||||||
|
|
||||||
|
|||||||
13
db/seeds.rb
13
db/seeds.rb
@@ -30,8 +30,11 @@
|
|||||||
|
|
||||||
User.create(id: 1, email: 'test@test.com', password: 'password', password_confirmation: 'password')
|
User.create(id: 1, email: 'test@test.com', password: 'password', password_confirmation: 'password')
|
||||||
|
|
||||||
|
# Set tournament date to a month from today
|
||||||
|
future_date = 1.month.from_now.to_date
|
||||||
|
|
||||||
# Pool to bracket
|
# Pool to bracket
|
||||||
tournament = Tournament.create(id: 200, name: 'Pool to bracket', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Pool to bracket', user_id: 1, date: Date.today, is_public: true)
|
tournament = Tournament.create(id: 200, name: 'Pool to bracket', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Pool to bracket', user_id: 1, date: future_date, is_public: true)
|
||||||
create_schools(tournament, 24)
|
create_schools(tournament, 24)
|
||||||
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
||||||
tournament.create_pre_defined_weights(weight_classes)
|
tournament.create_pre_defined_weights(weight_classes)
|
||||||
@@ -58,7 +61,7 @@
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Modified 16 Man Double Elimination 1-6
|
# Modified 16 Man Double Elimination 1-6
|
||||||
tournament = Tournament.create(id: 201, name: 'Modified 16 Man Double Elimination 1-6', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Modified 16 Man Double Elimination 1-6', user_id: 1, date: Date.today, is_public: true)
|
tournament = Tournament.create(id: 201, name: 'Modified 16 Man Double Elimination 1-6', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Modified 16 Man Double Elimination 1-6', user_id: 1, date: future_date, is_public: true)
|
||||||
create_schools(tournament, 16)
|
create_schools(tournament, 16)
|
||||||
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
||||||
tournament.create_pre_defined_weights(weight_classes)
|
tournament.create_pre_defined_weights(weight_classes)
|
||||||
@@ -69,7 +72,7 @@
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Modified 16 Man Double Elimination 1-8
|
# Modified 16 Man Double Elimination 1-8
|
||||||
tournament = Tournament.create(id: 202, name: 'Modified 16 Man Double Elimination 1-8', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Modified 16 Man Double Elimination 1-8', user_id: 1, date: Date.today, is_public: true)
|
tournament = Tournament.create(id: 202, name: 'Modified 16 Man Double Elimination 1-8', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Modified 16 Man Double Elimination 1-8', user_id: 1, date: future_date, is_public: true)
|
||||||
create_schools(tournament, 16)
|
create_schools(tournament, 16)
|
||||||
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
||||||
tournament.create_pre_defined_weights(weight_classes)
|
tournament.create_pre_defined_weights(weight_classes)
|
||||||
@@ -86,7 +89,7 @@
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Regular Double Elimination 1-6
|
# Regular Double Elimination 1-6
|
||||||
tournament = Tournament.create(id: 203, name: 'Regular Double Elimination 1-6', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Regular Double Elimination 1-6', user_id: 1, date: Date.today, is_public: true)
|
tournament = Tournament.create(id: 203, name: 'Regular Double Elimination 1-6', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Regular Double Elimination 1-6', user_id: 1, date: future_date, is_public: true)
|
||||||
create_schools(tournament, 32)
|
create_schools(tournament, 32)
|
||||||
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
||||||
tournament.create_pre_defined_weights(weight_classes)
|
tournament.create_pre_defined_weights(weight_classes)
|
||||||
@@ -109,7 +112,7 @@
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Regular Double Elimination 1-8
|
# Regular Double Elimination 1-8
|
||||||
tournament = Tournament.create(id: 204, name: 'Regular Double Elimination 1-8', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Regular Double Elimination 1-8', user_id: 1, date: Date.today, is_public: true)
|
tournament = Tournament.create(id: 204, name: 'Regular Double Elimination 1-8', address: 'some place', director: 'some guy', director_email: 'their@email.com', tournament_type: 'Regular Double Elimination 1-8', user_id: 1, date: future_date, is_public: true)
|
||||||
create_schools(tournament, 32)
|
create_schools(tournament, 32)
|
||||||
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
weight_classes=Weight::HS_WEIGHT_CLASSES.split(",")
|
||||||
tournament.create_pre_defined_weights(weight_classes)
|
tournament.create_pre_defined_weights(weight_classes)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ docker-compose -f ${project_dir}/deploy/docker-compose-test.yml up -d
|
|||||||
|
|
||||||
# DISABLE_DATABASE_ENVIRONMENT_CHECK=1 is needed because this is "destructive" action on production
|
# DISABLE_DATABASE_ENVIRONMENT_CHECK=1 is needed because this is "destructive" action on production
|
||||||
echo Resetting the db with seed data
|
echo Resetting the db with seed data
|
||||||
docker-compose -f ${project_dir}/deploy/docker-compose-test.yml exec -T app bash -c "DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rake db:reset"
|
docker-compose -f ${project_dir}/deploy/docker-compose-test.yml run --rm app bash -c "DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rake db:reset"
|
||||||
|
|
||||||
# echo Simulating tournament 204
|
# echo Simulating tournament 204
|
||||||
# docker-compose -f ${project_dir}/deploy/docker-compose-test.yml exec -T app rails tournament:assign_random_wins
|
# docker-compose -f ${project_dir}/deploy/docker-compose-test.yml exec -T app rails tournament:assign_random_wins
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ services:
|
|||||||
- "443:443"
|
- "443:443"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: curl http://127.0.0.1/
|
test: curl http://127.0.0.1/
|
||||||
|
volumes:
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: mariadb:10.10
|
image: mariadb:10.10
|
||||||
@@ -43,6 +46,8 @@ services:
|
|||||||
- "3306:3306"
|
- "3306:3306"
|
||||||
volumes:
|
volumes:
|
||||||
- mysql:/var/lib/mysql
|
- mysql:/var/lib/mysql
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_ROOT_PASSWORD=password
|
- MYSQL_ROOT_PASSWORD=password
|
||||||
restart: always
|
restart: always
|
||||||
@@ -65,3 +70,5 @@ services:
|
|||||||
metrics:
|
metrics:
|
||||||
volumes:
|
volumes:
|
||||||
- influxdb:/var/lib/influxdb
|
- influxdb:/var/lib/influxdb
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
|||||||
11
test/fixtures/tournaments.yml
vendored
11
test/fixtures/tournaments.yml
vendored
@@ -9,4 +9,15 @@ one:
|
|||||||
tournament_type: Pool to bracket
|
tournament_type: Pool to bracket
|
||||||
user_id: 1
|
user_id: 1
|
||||||
date: 2015-12-30
|
date: 2015-12-30
|
||||||
|
is_public: true
|
||||||
|
|
||||||
|
two:
|
||||||
|
id: 2
|
||||||
|
name: Test Tournament 2
|
||||||
|
address: Some Place
|
||||||
|
director: Jacob Cody Wimer
|
||||||
|
director_email: jacob.wimer@gmail.com
|
||||||
|
tournament_type: Pool to bracket
|
||||||
|
user_id: 1
|
||||||
|
date: 2015-12-30
|
||||||
is_public: true
|
is_public: true
|
||||||
83
test/jobs/tournament_cleanup_job_test.rb
Normal file
83
test/jobs/tournament_cleanup_job_test.rb
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class TournamentCleanupJobTest < ActiveJob::TestCase
|
||||||
|
setup do
|
||||||
|
# Create an old empty tournament (1 week old, 0 finished matches)
|
||||||
|
@old_empty_tournament = tournaments(:one)
|
||||||
|
@old_empty_tournament.update(date: 2.weeks.ago.to_date)
|
||||||
|
|
||||||
|
# Create an old active tournament (1 week old, with finished matches)
|
||||||
|
@old_active_tournament = tournaments(:two)
|
||||||
|
@old_active_tournament.update(date: 2.weeks.ago.to_date)
|
||||||
|
|
||||||
|
# Add a finished match to the active tournament using create instead of fixtures
|
||||||
|
weight = Weight.create(max: 120, tournament: @old_active_tournament)
|
||||||
|
wrestler = Wrestler.create(name: "Test Wrestler", weight: weight, school: schools(:one))
|
||||||
|
|
||||||
|
@match = Match.create(
|
||||||
|
tournament: @old_active_tournament,
|
||||||
|
weight: weight,
|
||||||
|
bracket_position: "Pool",
|
||||||
|
round: 1,
|
||||||
|
finished: 1,
|
||||||
|
win_type: "Decision",
|
||||||
|
score: "10-5",
|
||||||
|
w1: wrestler.id,
|
||||||
|
winner_id: wrestler.id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add delegates to test removal
|
||||||
|
tournament_delegate = TournamentDelegate.create(tournament: @old_active_tournament, user: users(:one))
|
||||||
|
school = schools(:one)
|
||||||
|
school.update(tournament_id: @old_active_tournament.id)
|
||||||
|
school_delegate = SchoolDelegate.create(school: school, user: users(:one))
|
||||||
|
end
|
||||||
|
|
||||||
|
test "removes old empty tournaments" do
|
||||||
|
# In this test, only the empty tournament should be deleted
|
||||||
|
@match.update!(win_type: "Decision") # Ensure this tournament has a non-BYE match
|
||||||
|
|
||||||
|
assert_difference 'Tournament.count', -1 do
|
||||||
|
TournamentCleanupJob.perform_now
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raises(ActiveRecord::RecordNotFound) { @old_empty_tournament.reload }
|
||||||
|
assert_nothing_raised { @old_active_tournament.reload }
|
||||||
|
end
|
||||||
|
|
||||||
|
test "removes old empty tournaments with only a bye finished match" do
|
||||||
|
# Update the win_type to BYE and score to empty as required by validation
|
||||||
|
@match.update!(win_type: "BYE", score: "")
|
||||||
|
assert_equal "BYE", @match.reload.win_type
|
||||||
|
assert_equal "", @match.score
|
||||||
|
|
||||||
|
# Both tournaments should be deleted (the empty one and the one with only BYE matches)
|
||||||
|
assert_difference 'Tournament.count', -2 do
|
||||||
|
TournamentCleanupJob.perform_now
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raises(ActiveRecord::RecordNotFound) { @old_empty_tournament.reload }
|
||||||
|
assert_raises(ActiveRecord::RecordNotFound) { @old_active_tournament.reload }
|
||||||
|
end
|
||||||
|
|
||||||
|
test "cleans up old active tournaments" do
|
||||||
|
# Ensure this tournament has a non-BYE match
|
||||||
|
@match.update!(win_type: "Decision")
|
||||||
|
|
||||||
|
TournamentCleanupJob.perform_now
|
||||||
|
|
||||||
|
# Tournament should still exist
|
||||||
|
@old_active_tournament.reload
|
||||||
|
|
||||||
|
# User association should be removed
|
||||||
|
assert_nil @old_active_tournament.user_id
|
||||||
|
|
||||||
|
# Tournament delegates should be removed
|
||||||
|
assert_equal 0, @old_active_tournament.delegates.count
|
||||||
|
|
||||||
|
# School delegates should be removed
|
||||||
|
@old_active_tournament.schools.each do |school|
|
||||||
|
assert_equal 0, school.delegates.count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user