Class: HTM::SequelConfig
- Inherits:
-
Object
- Object
- HTM::SequelConfig
- Defined in:
- lib/htm/sequel_config.rb
Overview
Sequel database configuration and model loading
Uses HTM::Config for database settings. Configuration can come from:
-
Environment variables (HTM_DATABASE__URL, HTM_DATABASE__HOST, etc.)
-
Programmatic configuration via HTM.configure
Sequel is fiber-safe by design, making it ideal for async/fiber-based concurrency patterns used in HTM’s job processing.
Class Attribute Summary collapse
-
.db ⇒ Sequel::Database?
readonly
Database connection instance.
Class Method Summary collapse
-
.build_connection_string(config) ⇒ String
Build connection string from config hash.
-
.connected? ⇒ Boolean
Check if connection is established and active.
-
.connection_stats ⇒ Hash
Get connection pool statistics.
-
.disconnect! ⇒ void
Close all database connections.
-
.ensure_models_loaded! ⇒ void
Ensure models are loaded.
-
.establish_connection!(load_models: true) ⇒ Sequel::Database
Establish database connection from HTM::Config.
-
.execute(sql) ⇒ void
Run raw SQL.
-
.load_database_config ⇒ Hash
Load database configuration from HTM::Config.
-
.models_loadable? ⇒ Boolean
Check if models can be loaded (tables exist).
-
.select_value(sql) ⇒ Object
Select a single value.
-
.verify_extensions! ⇒ true
Verify required extensions are available.
Class Attribute Details
.db ⇒ Sequel::Database? (readonly)
Database connection instance
19 20 21 |
# File 'lib/htm/sequel_config.rb', line 19 def db @db end |
Class Method Details
.build_connection_string(config) ⇒ String
Build connection string from config hash
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/htm/sequel_config.rb', line 90 def build_connection_string(config) # If we have a URL already, use it if config[:url] return config[:url] end user = config[:username] || config[:user] password = config[:password] host = config[:host] || 'localhost' port = config[:port] || 5432 database = config[:database] if password && !password.empty? "postgres://#{user}:#{password}@#{host}:#{port}/#{database}" elsif user "postgres://#{user}@#{host}:#{port}/#{database}" else "postgres://#{host}:#{port}/#{database}" end end |
.connected? ⇒ Boolean
Check if connection is established and active
115 116 117 118 119 120 121 |
# File 'lib/htm/sequel_config.rb', line 115 def connected? return false unless @db @db.test_connection rescue Sequel::DatabaseError false end |
.connection_stats ⇒ Hash
Get connection pool statistics
160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/htm/sequel_config.rb', line 160 def connection_stats pool = @db.pool { size: pool.max_size, available: pool.available_connections.size, allocated: pool.allocated.size } rescue NoMethodError # Fallback for connection pools that don't support these methods { size: @db.pool.max_size } end |
.disconnect! ⇒ void
This method returns an undefined value.
Close all database connections
127 128 129 130 |
# File 'lib/htm/sequel_config.rb', line 127 def disconnect! @db&.disconnect @db = nil end |
.ensure_models_loaded! ⇒ void
This method returns an undefined value.
Ensure models are loaded
Call this after migrations to ensure models are available
73 74 75 |
# File 'lib/htm/sequel_config.rb', line 73 def ensure_models_loaded! require_models unless @models_loaded end |
.establish_connection!(load_models: true) ⇒ Sequel::Database
Establish database connection from HTM::Config
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/htm/sequel_config.rb', line 27 def establish_connection!(load_models: true) return @db if @db config = load_database_config connection_string = build_connection_string(config) # Configure Sequel with fiber-safe settings @db = Sequel.connect(connection_string, { max_connections: config[:pool] || 5, pool_timeout: (config[:checkout_timeout] || 5).to_i, # Fiber-safe settings - important for async gem compatibility preconnect: :concurrently, # Use threaded mode which works well with fibers single_threaded: false }) # Load PostgreSQL-specific extensions for JSONB and array handling @db.extension :pg_json @db.extension :pg_array # Set search path and statement timeout @db.run("SET search_path TO public") @db.run("SET statement_timeout = #{config[:statement_timeout] || 30_000}") # Load models after connection is established (unless disabled for migrations) require_models if load_models && models_loadable? @db end |
.execute(sql) ⇒ void
This method returns an undefined value.
Run raw SQL
177 178 179 |
# File 'lib/htm/sequel_config.rb', line 177 def execute(sql) @db.run(sql) end |
.load_database_config ⇒ Hash
Load database configuration from HTM::Config
81 82 83 |
# File 'lib/htm/sequel_config.rb', line 81 def load_database_config HTM.config.database_config end |
.models_loadable? ⇒ Boolean
Check if models can be loaded (tables exist)
61 62 63 64 65 66 |
# File 'lib/htm/sequel_config.rb', line 61 def models_loadable? return false unless @db @db.table_exists?(:robots) rescue Sequel::DatabaseError false end |
.select_value(sql) ⇒ Object
Select a single value
186 187 188 |
# File 'lib/htm/sequel_config.rb', line 186 def select_value(sql) @db[sql].first&.values&.first end |
.verify_extensions! ⇒ true
Verify required extensions are available
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/htm/sequel_config.rb', line 137 def verify_extensions! required_extensions = { 'vector' => 'pgvector extension', 'pg_trgm' => 'PostgreSQL trigram extension' } missing = [] required_extensions.each do |ext, name| result = @db["SELECT COUNT(*) AS cnt FROM pg_extension WHERE extname = ?", ext].first missing << name if result[:cnt].to_i.zero? end if missing.any? raise "Missing required PostgreSQL extensions: #{missing.join(', ')}" end true end |