DEV: Store details log entries in converter as JSON (#29778)
Plus small DB related fixes
This commit is contained in:
parent
75f4a14568
commit
a48af2f120
|
@ -4,5 +4,5 @@ CREATE TABLE log_entries
|
||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
message TEXT NOT NULL,
|
message TEXT NOT NULL,
|
||||||
exception TEXT,
|
exception TEXT,
|
||||||
details TEXT
|
details JSON_TEXT
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,23 +3,22 @@
|
||||||
require "date"
|
require "date"
|
||||||
require "extralite"
|
require "extralite"
|
||||||
require "ipaddr"
|
require "ipaddr"
|
||||||
|
require "oj"
|
||||||
|
|
||||||
module Migrations
|
module Migrations
|
||||||
module Database
|
module Database
|
||||||
INTERMEDIATE_DB_SCHEMA_PATH = File.join(::Migrations.root_path, "db", "intermediate_db_schema")
|
INTERMEDIATE_DB_SCHEMA_PATH = File.join(::Migrations.root_path, "db", "intermediate_db_schema")
|
||||||
UPLOADS_DB_SCHEMA_PATH = File.join(::Migrations.root_path, "db", "uploads_db_schema")
|
UPLOADS_DB_SCHEMA_PATH = File.join(::Migrations.root_path, "db", "uploads_db_schema")
|
||||||
|
|
||||||
module_function
|
def self.migrate(db_path, migrations_path:)
|
||||||
|
|
||||||
def migrate(db_path, migrations_path:)
|
|
||||||
Migrator.new(db_path).migrate(migrations_path)
|
Migrator.new(db_path).migrate(migrations_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset!(db_path)
|
def self.reset!(db_path)
|
||||||
Migrator.new(db_path).reset!
|
Migrator.new(db_path).reset!
|
||||||
end
|
end
|
||||||
|
|
||||||
def connect(path)
|
def self.connect(path)
|
||||||
connection = Connection.new(path:)
|
connection = Connection.new(path:)
|
||||||
return connection unless block_given?
|
return connection unless block_given?
|
||||||
|
|
||||||
|
@ -31,29 +30,34 @@ module Migrations
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_datetime(value)
|
def self.format_datetime(value)
|
||||||
value&.utc&.iso8601
|
value&.utc&.iso8601
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_date(value)
|
def self.format_date(value)
|
||||||
value&.to_date&.iso8601
|
value&.to_date&.iso8601
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_boolean(value)
|
def self.format_boolean(value)
|
||||||
return nil if value.nil?
|
return nil if value.nil?
|
||||||
value ? 1 : 0
|
value ? 1 : 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_ip_address(value)
|
def self.format_ip_address(value)
|
||||||
return nil if value.blank?
|
return nil if value.blank?
|
||||||
IPAddr.new(value).to_s
|
IPAddr.new(value).to_s
|
||||||
rescue ArgumentError
|
rescue ArgumentError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_blob(value)
|
def self.to_blob(value)
|
||||||
return nil if value.blank?
|
return nil if value.blank?
|
||||||
Extralite::Blob.new(value)
|
::Extralite::Blob.new(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.to_json(value)
|
||||||
|
return nil if value.nil?
|
||||||
|
::Oj.dump(value, mode: :compat)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "extralite"
|
require "extralite"
|
||||||
require "lru_redux"
|
|
||||||
|
|
||||||
module Migrations::Database
|
module Migrations::Database
|
||||||
class Connection
|
class Connection
|
||||||
|
@ -11,7 +10,7 @@ module Migrations::Database
|
||||||
def self.open_database(path:)
|
def self.open_database(path:)
|
||||||
FileUtils.mkdir_p(File.dirname(path))
|
FileUtils.mkdir_p(File.dirname(path))
|
||||||
|
|
||||||
db = Extralite::Database.new(path)
|
db = ::Extralite::Database.new(path)
|
||||||
db.pragma(
|
db.pragma(
|
||||||
busy_timeout: 60_000, # 60 seconds
|
busy_timeout: 60_000, # 60 seconds
|
||||||
journal_mode: "wal",
|
journal_mode: "wal",
|
||||||
|
@ -30,8 +29,6 @@ module Migrations::Database
|
||||||
@transaction_batch_size = transaction_batch_size
|
@transaction_batch_size = transaction_batch_size
|
||||||
@db = self.class.open_database(path:)
|
@db = self.class.open_database(path:)
|
||||||
@statement_counter = 0
|
@statement_counter = 0
|
||||||
|
|
||||||
# don't cache too many prepared statements
|
|
||||||
@statement_cache = PreparedStatementCache.new(PREPARED_STATEMENT_CACHE_SIZE)
|
@statement_cache = PreparedStatementCache.new(PREPARED_STATEMENT_CACHE_SIZE)
|
||||||
|
|
||||||
@fork_hooks = setup_fork_handling
|
@fork_hooks = setup_fork_handling
|
||||||
|
@ -46,7 +43,7 @@ module Migrations::Database
|
||||||
end
|
end
|
||||||
|
|
||||||
def closed?
|
def closed?
|
||||||
!@db || @db.closed?
|
@db.nil? || @db.closed?
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert(sql, parameters = [])
|
def insert(sql, parameters = [])
|
||||||
|
@ -76,7 +73,7 @@ module Migrations::Database
|
||||||
end
|
end
|
||||||
|
|
||||||
def close_connection(keep_path:)
|
def close_connection(keep_path:)
|
||||||
return if !@db
|
return if @db.nil?
|
||||||
|
|
||||||
commit_transaction
|
commit_transaction
|
||||||
@statement_cache.clear
|
@statement_cache.clear
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "singleton"
|
|
||||||
|
|
||||||
module Migrations::Database
|
module Migrations::Database
|
||||||
module IntermediateDB
|
module IntermediateDB
|
||||||
def self.setup(db_connection)
|
def self.setup(db_connection)
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Migrations::Database::IntermediateDB
|
||||||
type,
|
type,
|
||||||
message,
|
message,
|
||||||
exception&.full_message(highlight: false),
|
exception&.full_message(highlight: false),
|
||||||
details,
|
::Migrations::Database.to_json(details),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,12 +21,14 @@ module Migrations::Database
|
||||||
migrate_from_path(@migrations_path, performed_migrations)
|
migrate_from_path(@migrations_path, performed_migrations)
|
||||||
|
|
||||||
@db.close
|
@db.close
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset!
|
def reset!
|
||||||
[@db_path, "#{@db_path}-wal", "#{@db_path}-shm"].each do |path|
|
[@db_path, "#{@db_path}-wal", "#{@db_path}-shm"].each do |path|
|
||||||
FileUtils.remove_file(path, force: true) if File.exist?(path)
|
FileUtils.remove_file(path, force: true) if File.exist?(path)
|
||||||
end
|
end
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "lru_redux"
|
||||||
|
|
||||||
module Migrations::Database
|
module Migrations::Database
|
||||||
class PreparedStatementCache < LruRedux::Cache
|
class PreparedStatementCache < LruRedux::Cache
|
||||||
class PreparedStatementHash < Hash
|
class PreparedStatementHash < Hash
|
||||||
|
|
|
@ -140,4 +140,22 @@ RSpec.describe ::Migrations::Database do
|
||||||
expect(described_class.to_blob(nil)).to be_nil
|
expect(described_class.to_blob(nil)).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".to_json" do
|
||||||
|
it "returns a JSON string for objects" do
|
||||||
|
expect(described_class.to_json(123)).to eq("123")
|
||||||
|
expect(described_class.to_json("hello world")).to eq(%q|"hello world"|)
|
||||||
|
expect(
|
||||||
|
described_class.to_json(
|
||||||
|
text: "foo",
|
||||||
|
number: 123,
|
||||||
|
date: DateTime.new(2023, 10, 5, 17, 30, 0),
|
||||||
|
),
|
||||||
|
).to eq(%q|{"text":"foo","number":123,"date":"2023-10-05T17:30:00.000+00:00"}|)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nil for nil input" do
|
||||||
|
expect(described_class.to_json(nil)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue