Class: PgSqlTriggers::TriggerRegistry
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- PgSqlTriggers::TriggerRegistry
- Defined in:
- app/models/pg_sql_triggers/trigger_registry.rb
Overview
ActiveRecord model representing a trigger in the registry.
This model tracks all triggers managed by pg_sql_triggers, including their state, version, checksum, and drift status.
rubocop:disable Metrics/ClassLength – core AR model: groups lifecycle operations (enable!/disable!/drop!/re_execute!), drift helpers, audit hooks, and SQL builders. Splitting further would fragment tightly-coupled state and audit concerns.
Instance Method Summary collapse
-
#disable!(confirmation: nil, actor: nil) ⇒ PgSqlTriggers::TriggerRegistry
Disables this trigger in the database and updates the registry.
-
#drift_result ⇒ Hash
Returns detailed drift detection result for this trigger.
-
#drift_state ⇒ String
Returns the current drift state of this trigger.
-
#drifted? ⇒ Boolean
Checks if this trigger has drifted from its expected state.
-
#drop!(reason:, confirmation: nil, actor: nil) ⇒ true
Drops this trigger from the database and removes it from the registry.
-
#dropped? ⇒ Boolean
Checks if this trigger has been dropped from the database.
-
#enable!(confirmation: nil, actor: nil) ⇒ PgSqlTriggers::TriggerRegistry
Enables this trigger in the database and updates the registry.
-
#in_sync? ⇒ Boolean
Checks if this trigger is in sync with its expected state.
-
#re_execute!(reason:, confirmation: nil, actor: nil) ⇒ PgSqlTriggers::TriggerRegistry
Re-executes this trigger by dropping and recreating it.
Instance Method Details
#disable!(confirmation: nil, actor: nil) ⇒ PgSqlTriggers::TriggerRegistry
Disables this trigger in the database and updates the registry.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 148 def disable!(confirmation: nil, actor: nil) actor ||= { type: "Console", id: "TriggerRegistry#disable!" } before_state = capture_state # Check kill switch before disabling trigger # Use Rails.env for kill switch check, not the trigger's environment field PgSqlTriggers::SQL::KillSwitch.check!( operation: :trigger_disable, environment: Rails.env, confirmation: confirmation, actor: actor ) # Check if trigger exists in database before trying to disable it trigger_exists = false begin introspection = PgSqlTriggers::DatabaseIntrospection.new trigger_exists = introspection.trigger_exists?(trigger_name) rescue StandardError => e # If checking fails, assume trigger doesn't exist and continue Rails.logger.warn("Could not check if trigger exists: #{e.}") if defined?(Rails.logger) end if trigger_exists begin # Disable the trigger in PostgreSQL quoted_table = quote_identifier(table_name) quoted_trigger = quote_identifier(trigger_name) sql = "ALTER TABLE #{quoted_table} DISABLE TRIGGER #{quoted_trigger};" ActiveRecord::Base.connection.execute(sql) rescue ActiveRecord::StatementInvalid, StandardError => e # If trigger doesn't exist or can't be disabled, continue to update registry Rails.logger.warn("Could not disable trigger: #{e.}") if defined?(Rails.logger) log_audit_failure(:trigger_disable, actor, e., before_state: before_state) raise end end # Update the registry record (always update, even if trigger doesn't exist). # If persistence fails for any reason, fall back to the in-memory attribute so # callers/observers still see a consistent state for this request. persist_enabled_state(false) after_state = capture_state log_audit_success(:trigger_disable, actor, before_state: before_state, after_state: after_state) end |
#drift_result ⇒ Hash
Returns detailed drift detection result for this trigger.
65 66 67 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 65 def drift_result PgSqlTriggers::Drift::Detector.detect(trigger_name) end |
#drift_state ⇒ String
Returns the current drift state of this trigger.
57 58 59 60 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 57 def drift_state result = PgSqlTriggers::Drift.detect(trigger_name) result[:state] end |
#drifted? ⇒ Boolean
Checks if this trigger has drifted from its expected state.
72 73 74 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 72 def drifted? drift_state == PgSqlTriggers::DRIFT_STATE_DRIFTED end |
#drop!(reason:, confirmation: nil, actor: nil) ⇒ true
Drops this trigger from the database and removes it from the registry.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 202 def drop!(reason:, confirmation: nil, actor: nil) actor ||= { type: "Console", id: "TriggerRegistry#drop!" } before_state = capture_state # Check kill switch before dropping trigger PgSqlTriggers::SQL::KillSwitch.check!( operation: :trigger_drop, environment: Rails.env, confirmation: confirmation, actor: actor ) # Validate reason is provided raise ArgumentError, "Reason is required" if reason.nil? || reason.to_s.strip.empty? log_drop_attempt(reason) # Execute DROP TRIGGER in transaction ActiveRecord::Base.transaction do drop_trigger_from_database destroy! log_drop_success log_audit_success(:trigger_drop, actor, reason: reason, confirmation_text: confirmation, before_state: before_state, after_state: { status: "dropped" }) end rescue StandardError => e log_audit_failure(:trigger_drop, actor, e., reason: reason, confirmation_text: confirmation, before_state: before_state) raise end |
#dropped? ⇒ Boolean
Checks if this trigger has been dropped from the database.
86 87 88 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 86 def dropped? drift_state == PgSqlTriggers::DRIFT_STATE_DROPPED end |
#enable!(confirmation: nil, actor: nil) ⇒ PgSqlTriggers::TriggerRegistry
Enables this trigger in the database and updates the registry.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 96 def enable!(confirmation: nil, actor: nil) actor ||= { type: "Console", id: "TriggerRegistry#enable!" } before_state = capture_state # Check kill switch before enabling trigger # Use Rails.env for kill switch check, not the trigger's environment field PgSqlTriggers::SQL::KillSwitch.check!( operation: :trigger_enable, environment: Rails.env, confirmation: confirmation, actor: actor ) # Check if trigger exists in database before trying to enable it trigger_exists = false begin introspection = PgSqlTriggers::DatabaseIntrospection.new trigger_exists = introspection.trigger_exists?(trigger_name) rescue StandardError => e # If checking fails, assume trigger doesn't exist and continue Rails.logger.warn("Could not check if trigger exists: #{e.}") if defined?(Rails.logger) end if trigger_exists begin # Enable the trigger in PostgreSQL quoted_table = quote_identifier(table_name) quoted_trigger = quote_identifier(trigger_name) sql = "ALTER TABLE #{quoted_table} ENABLE TRIGGER #{quoted_trigger};" ActiveRecord::Base.connection.execute(sql) rescue ActiveRecord::StatementInvalid, StandardError => e # If trigger doesn't exist or can't be enabled, continue to update registry Rails.logger.warn("Could not enable trigger: #{e.}") if defined?(Rails.logger) log_audit_failure(:trigger_enable, actor, e., before_state: before_state) raise end end # Update the registry record (always update, even if trigger doesn't exist). # If persistence fails for any reason, fall back to the in-memory attribute so # callers/observers still see a consistent state for this request. persist_enabled_state(true) after_state = capture_state log_audit_success(:trigger_enable, actor, before_state: before_state, after_state: after_state) end |
#in_sync? ⇒ Boolean
Checks if this trigger is in sync with its expected state.
79 80 81 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 79 def in_sync? drift_state == PgSqlTriggers::DRIFT_STATE_IN_SYNC end |
#re_execute!(reason:, confirmation: nil, actor: nil) ⇒ PgSqlTriggers::TriggerRegistry
Re-executes this trigger by dropping and recreating it.
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'app/models/pg_sql_triggers/trigger_registry.rb', line 242 def re_execute!(reason:, confirmation: nil, actor: nil) actor ||= { type: "Console", id: "TriggerRegistry#re_execute!" } before_state = capture_state drift_info = begin drift_result rescue StandardError nil end # Check kill switch before re-executing trigger PgSqlTriggers::SQL::KillSwitch.check!( operation: :trigger_re_execute, environment: Rails.env, confirmation: confirmation, actor: actor ) # Validate reason is provided raise ArgumentError, "Reason is required" if reason.nil? || reason.to_s.strip.empty? log_re_execute_attempt(reason) # Execute the trigger creation/update in transaction ActiveRecord::Base.transaction do drop_existing_trigger_for_re_execute recreate_trigger update_registry_after_re_execute after_state = capture_state diff = drift_info ? "#{drift_info[:expected_sql]} -> #{after_state[:function_body]}" : nil log_audit_success(:trigger_re_execute, actor, reason: reason, confirmation_text: confirmation, before_state: before_state, after_state: after_state, diff: diff) end rescue StandardError => e log_audit_failure( :trigger_re_execute, actor, e., reason: reason, confirmation_text: confirmation, before_state: before_state ) raise end |