Migrate Lapse hbs + concurrent index on heartbeats' user_agent (#1056)

* Add concurrent index on heartbeats user_agent

* whoops, forgot to commit :skulk:
This commit is contained in:
Mahad Kalam 2026-03-11 17:08:38 +00:00 committed by GitHub
parent 606bdaed01
commit cda06a30be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 1 deletions

View file

@ -0,0 +1,7 @@
class AddIndexHeartbeatsOnUserAgent < ActiveRecord::Migration[8.1]
disable_ddl_transaction!
def change
add_index :heartbeats, :user_agent, algorithm: :concurrently
end
end

View file

@ -0,0 +1,31 @@
class UpdateLapseHeartbeatLanguage < ActiveRecord::Migration[8.1]
disable_ddl_transaction!
BATCH_SIZE = 10_000
def up
loop do
result = execute(<<-SQL.squish)
UPDATE heartbeats
SET language = 'Lapse', updated_at = NOW()
WHERE id IN (
SELECT id FROM heartbeats
WHERE user_agent IN (
'wakatime/lapse (lapse) lapse/2.0.0 lapse/2.0.0',
'wakatime/lapse (lapse) lapse/0.1.0 lapse/0.1.0'
)
AND language IS DISTINCT FROM 'Lapse'
LIMIT #{BATCH_SIZE}
)
SQL
break if result.cmd_tuples == 0
sleep(0.1)
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

3
db/schema.rb generated
View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 2026_03_11_162930) do
ActiveRecord::Schema[8.1].define(version: 2026_03_11_170528) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
enable_extension "pg_stat_statements"
@ -290,6 +290,7 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_11_162930) do
t.index ["project"], name: "index_heartbeats_on_project"
t.index ["raw_heartbeat_upload_id"], name: "index_heartbeats_on_raw_heartbeat_upload_id"
t.index ["source_type", "time", "user_id", "project"], name: "index_heartbeats_on_source_type_time_user_project"
t.index ["user_agent"], name: "index_heartbeats_on_user_agent"
t.index ["user_id", "category", "time"], name: "idx_heartbeats_user_category_time", where: "(deleted_at IS NULL)"
t.index ["user_id", "editor", "time"], name: "idx_heartbeats_user_editor_time", where: "(deleted_at IS NULL)"
t.index ["user_id", "id"], name: "index_heartbeats_on_user_id_with_ip", order: { id: :desc }, where: "((ip_address IS NOT NULL) AND (deleted_at IS NULL))"