mirror of
https://github.com/ryankazokas/turbovault-app.git
synced 2026-04-16 22:12:53 +00:00
139 lines
3.9 KiB
Ruby
139 lines
3.9 KiB
Ruby
class IgdbSyncJob < ApplicationJob
|
|
queue_as :default
|
|
|
|
# Ensure only one instance runs at a time
|
|
def self.running?
|
|
Rails.cache.exist?("igdb_sync_job:running")
|
|
end
|
|
|
|
def self.mark_running!
|
|
Rails.cache.write("igdb_sync_job:running", true, expires_in: 2.hours)
|
|
end
|
|
|
|
def self.mark_finished!
|
|
Rails.cache.delete("igdb_sync_job:running")
|
|
end
|
|
|
|
def perform
|
|
# Prevent multiple instances
|
|
if self.class.running?
|
|
Rails.logger.info("IgdbSyncJob already running, skipping...")
|
|
return
|
|
end
|
|
|
|
self.class.mark_running!
|
|
|
|
begin
|
|
sync_users_with_igdb
|
|
ensure
|
|
self.class.mark_finished!
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def sync_users_with_igdb
|
|
users = User.where(igdb_sync_enabled: true)
|
|
|
|
Rails.logger.info("Starting IGDB sync for #{users.count} users")
|
|
|
|
users.find_each do |user|
|
|
sync_user_games(user)
|
|
rescue => e
|
|
Rails.logger.error("Error syncing user #{user.id}: #{e.message}")
|
|
next
|
|
end
|
|
|
|
Rails.logger.info("IGDB sync completed")
|
|
end
|
|
|
|
def sync_user_games(user)
|
|
# Get games that need IGDB matching
|
|
games = user.games
|
|
.igdb_unmatched
|
|
.where(igdb_match_status: [nil, "failed"])
|
|
.includes(:platform)
|
|
|
|
return if games.empty?
|
|
|
|
Rails.logger.info("Syncing #{games.count} games for user #{user.id}")
|
|
|
|
igdb_service = IgdbService.new
|
|
games_synced = 0
|
|
|
|
games.find_each do |game|
|
|
process_game_matching(game, igdb_service)
|
|
games_synced += 1
|
|
|
|
# Rate limiting: Additional sleep every 10 games
|
|
sleep(1) if games_synced % 10 == 0
|
|
rescue => e
|
|
Rails.logger.error("Error processing game #{game.id}: #{e.message}")
|
|
game.update(igdb_match_status: "failed")
|
|
next
|
|
end
|
|
|
|
user.update(igdb_last_synced_at: Time.current)
|
|
end
|
|
|
|
def process_game_matching(game, igdb_service)
|
|
Rails.logger.info("Searching IGDB for: #{game.title} (#{game.platform.name})")
|
|
|
|
# Try searching WITH platform first
|
|
results = igdb_service.search_game(game.title, game.platform, 3)
|
|
|
|
# If no results, try WITHOUT platform (broader search)
|
|
if results.empty?
|
|
Rails.logger.info("No results with platform, trying without platform filter...")
|
|
results = igdb_service.search_game(game.title, nil, 3)
|
|
end
|
|
|
|
if results.empty?
|
|
Rails.logger.info("No IGDB matches found for game #{game.id}")
|
|
game.update(igdb_match_status: "no_results")
|
|
return
|
|
end
|
|
|
|
Rails.logger.info("Found #{results.count} potential matches for game #{game.id}")
|
|
|
|
# Create match suggestions for user review
|
|
results.each do |result|
|
|
create_match_suggestion(game, result)
|
|
end
|
|
|
|
# Update game status
|
|
if results.first[:confidence_score] >= 95.0
|
|
# Very high confidence - could auto-approve, but we'll let user review
|
|
game.update(igdb_match_status: "high_confidence")
|
|
elsif results.first[:confidence_score] >= 70.0
|
|
game.update(igdb_match_status: "medium_confidence")
|
|
else
|
|
game.update(igdb_match_status: "low_confidence")
|
|
end
|
|
end
|
|
|
|
def create_match_suggestion(game, result)
|
|
# Skip if suggestion already exists
|
|
existing = IgdbMatchSuggestion.find_by(game: game, igdb_id: result[:igdb_id])
|
|
return if existing
|
|
|
|
IgdbMatchSuggestion.create!(
|
|
game: game,
|
|
igdb_id: result[:igdb_id],
|
|
igdb_name: result[:name],
|
|
igdb_slug: result[:slug],
|
|
igdb_cover_url: result[:cover_url],
|
|
igdb_summary: result[:summary],
|
|
igdb_release_date: result[:release_date],
|
|
igdb_platform_name: result[:platform_name],
|
|
igdb_genres: result[:genres] || [],
|
|
confidence_score: result[:confidence_score],
|
|
status: "pending"
|
|
)
|
|
|
|
Rails.logger.info("Created match suggestion: #{result[:name]} (confidence: #{result[:confidence_score]}%)")
|
|
rescue ActiveRecord::RecordInvalid => e
|
|
Rails.logger.warn("Failed to create match suggestion: #{e.message}")
|
|
end
|
|
end
|