Add raw heartbeat request storing

This commit is contained in:
Max Wofford 2025-05-13 14:48:24 -04:00
parent 764bf24e4d
commit 1db16233cb
6 changed files with 44 additions and 2 deletions

View file

@ -1,6 +1,7 @@
class Api::Hackatime::V1::HackatimeController < ApplicationController
before_action :set_user, except: [ :index ]
skip_before_action :verify_authenticity_token
before_action :set_raw_heartbeat_upload, only: [ :push_heartbeats ]
def index
redirect_to root_path
@ -28,7 +29,7 @@ class Api::Hackatime::V1::HackatimeController < ApplicationController
# {
# ...heartbeat_data
# }
heartbeat_array = [ heartbeat_params ]
heartbeat_array = Array(heartbeat_params)
new_heartbeat = handle_heartbeat(heartbeat_array)&.first&.first
render json: new_heartbeat, status: :accepted
end
@ -51,6 +52,13 @@ class Api::Hackatime::V1::HackatimeController < ApplicationController
private
def set_raw_heartbeat_upload
@raw_heartbeat_upload = RawHeartbeatUpload.create!(
request_headers: request.headers,
request_body: params
)
end
def handle_heartbeat(heartbeat_array)
results = []
heartbeat_array.each do |heartbeat|
@ -72,6 +80,8 @@ class Api::Hackatime::V1::HackatimeController < ApplicationController
machine: request.headers["X-Machine"]
})
new_heartbeat = Heartbeat.find_or_create_by(attrs)
new_heartbeat.raw_heartbeat_upload = @raw_heartbeat_upload
new_heartbeat.save!
queue_project_mapping(heartbeat[:project])
results << [ new_heartbeat.attributes, 201 ]
rescue => e

View file

@ -87,6 +87,7 @@ class Heartbeat < ApplicationRecord
self.inheritance_column = nil
belongs_to :user
belongs_to :raw_heartbeat_upload, optional: true
has_many :wakatime_mirrors, dependent: :destroy
validates :time, presence: true

View file

@ -0,0 +1,6 @@
class RawHeartbeatUpload < ApplicationRecord
has_many :heartbeats
validates :request_headers, presence: true
validates :request_body, presence: true
end

View file

@ -0,0 +1,10 @@
class CreateRawHeartbeatUploads < ActiveRecord::Migration[8.0]
def change
create_table :raw_heartbeat_uploads do |t|
t.jsonb :request_headers, null: false
t.jsonb :request_body, null: false
t.timestamps
end
end
end

View file

@ -0,0 +1,5 @@
class AddRawHeartbeatUploadToHeartbeats < ActiveRecord::Migration[8.0]
def change
add_reference :heartbeats, :raw_heartbeat_upload, null: true, foreign_key: true
end
end

12
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.0].define(version: 2025_05_12_205858) do
ActiveRecord::Schema[8.0].define(version: 2025_05_13_184040) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@ -209,8 +209,10 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_12_205858) do
t.integer "ysws_program", default: 0, null: false
t.datetime "deleted_at"
t.jsonb "raw_data"
t.bigint "raw_heartbeat_upload_id"
t.index ["category", "time"], name: "index_heartbeats_on_category_and_time"
t.index ["fields_hash"], name: "index_heartbeats_on_fields_hash_when_not_deleted", unique: true, where: "(deleted_at IS NULL)"
t.index ["raw_heartbeat_upload_id"], name: "index_heartbeats_on_raw_heartbeat_upload_id"
t.index ["user_id", "time"], name: "idx_heartbeats_user_time_active", where: "(deleted_at IS NULL)"
t.index ["user_id"], name: "index_heartbeats_on_user_id"
end
@ -261,6 +263,13 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_12_205858) do
t.index ["user_id"], name: "index_project_repo_mappings_on_user_id"
end
create_table "raw_heartbeat_uploads", force: :cascade do |t|
t.jsonb "request_headers", null: false
t.jsonb "request_body", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "sailors_log_leaderboards", force: :cascade do |t|
t.string "slack_channel_id"
t.string "slack_uid"
@ -358,6 +367,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_12_205858) do
add_foreign_key "api_keys", "users"
add_foreign_key "email_addresses", "users"
add_foreign_key "email_verification_requests", "users"
add_foreign_key "heartbeats", "raw_heartbeat_uploads"
add_foreign_key "heartbeats", "users"
add_foreign_key "leaderboard_entries", "leaderboards"
add_foreign_key "leaderboard_entries", "users"