Skip to content

Commit 0b817d6

Browse files
committed
fix: solve setlocal mismatch and upsert
SET LOCAL só vale dentro de uma transação explícita, fora dela o Postgres ignora silenciosamente, SET sem LOCAL altera o timeout para toda a conexão (que volta ao pool depois do job, mas connections do Sidekiq são dedicadas, então o efeito é o esperado)
1 parent 12e6edb commit 0b817d6

3 files changed

Lines changed: 23 additions & 28 deletions

File tree

app/modules/ai_intelligence/jobs/rebuild_champion_matrix_job.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def perform(scope: :all, league: nil)
1919
# 31k+ records with per-row upserts exceed the default 10s statement_timeout.
2020
# Scope this to the current session only — the connection returns to the pool
2121
# with its normal timeout restored after the job finishes.
22-
ActiveRecord::Base.connection.execute('SET LOCAL statement_timeout = 0')
22+
ActiveRecord::Base.connection.execute('SET statement_timeout = 0')
2323
rebuild_matrices(scope:, league:)
2424
ensure
2525
Sidekiq.redis { |r| r.call('DEL', lock_key) } if acquired

app/modules/ai_intelligence/models/ai_champion_matrix.rb

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,18 @@ class AiChampionMatrix < ApplicationRecord
88

99
scope :with_sufficient_sample, -> { where('total_games >= ?', 10) }
1010

11+
UPSERT_WIN_SQL = <<~SQL.squish.freeze
12+
INSERT INTO ai_champion_matrices
13+
(champion_a, champion_b, patch, league, wins_a, total_games, updated_at, created_at)
14+
VALUES (?, ?, ?, ?, 1, 1, NOW(), NOW())
15+
ON CONFLICT (champion_a, champion_b) WHERE patch IS NULL AND league IS NULL
16+
DO UPDATE SET wins_a = ai_champion_matrices.wins_a + 1,
17+
total_games = ai_champion_matrices.total_games + 1,
18+
updated_at = NOW()
19+
SQL
20+
1121
def self.upsert_win(winner, loser, patch: nil, league: nil)
12-
# Two separate partial indexes cover the two cases:
13-
# - both null → index_ai_champion_matrices_null_pair
14-
# - both present → index_ai_champion_matrices_unique
15-
index = if patch.nil? && league.nil?
16-
:index_ai_champion_matrices_null_pair
17-
else
18-
:index_ai_champion_matrices_unique
19-
end
20-
upsert(
21-
{ champion_a: winner, champion_b: loser, patch: patch, league: league,
22-
wins_a: 1, total_games: 1, updated_at: Time.current },
23-
unique_by: index,
24-
on_duplicate: Arel.sql(
25-
'wins_a = ai_champion_matrices.wins_a + 1, ' \
26-
'total_games = ai_champion_matrices.total_games + 1, ' \
27-
'updated_at = excluded.updated_at'
28-
)
29-
)
22+
connection.execute(sanitize_sql_array([UPSERT_WIN_SQL, winner, loser, patch, league]))
3023
end
3124

3225
def win_rate

app/modules/ai_intelligence/services/champion_matrix_builder.rb

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ def build
2828
end
2929
end
3030

31+
RECORD_APPEARANCE_SQL = <<~SQL.squish.freeze
32+
INSERT INTO ai_champion_matrices
33+
(champion_a, champion_b, patch, league, wins_a, total_games, updated_at, created_at)
34+
VALUES (?, ?, NULL, NULL, 0, 1, NOW(), NOW())
35+
ON CONFLICT (champion_a, champion_b) WHERE patch IS NULL AND league IS NULL
36+
DO UPDATE SET total_games = ai_champion_matrices.total_games + 1,
37+
updated_at = NOW()
38+
SQL
39+
3140
private
3241

3342
def register_matchups(winner_picks, loser_picks)
@@ -43,14 +52,7 @@ def register_matchups(winner_picks, loser_picks)
4352
end
4453

4554
def record_appearance(champion_a, champion_b)
46-
AiChampionMatrix.upsert(
47-
{ champion_a: champion_a, champion_b: champion_b, patch: nil, league: nil,
48-
wins_a: 0, total_games: 1, updated_at: Time.current },
49-
unique_by: :index_ai_champion_matrices_null_pair,
50-
on_duplicate: Arel.sql(
51-
'total_games = ai_champion_matrices.total_games + 1, ' \
52-
'updated_at = excluded.updated_at'
53-
)
54-
)
55+
sql = AiChampionMatrix.sanitize_sql_array([RECORD_APPEARANCE_SQL, champion_a, champion_b])
56+
AiChampionMatrix.connection.execute(sql)
5557
end
5658
end

0 commit comments

Comments
 (0)