-
Notifications
You must be signed in to change notification settings - Fork 0
New feature - Callbacks #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
lib/generators/iron_trail/templates/create_irontrail_support_tables.rb.erb
Outdated
Show resolved
Hide resolved
mhfs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @VGasparini 🤌,
@andrepiske and I are discussing it but we're still not fully decided on the direction.
Please hold on this PR. These are just some initial comments from our convo.
| @@ -0,0 +1,26 @@ | |||
| class CreateIrontrailChangeCallbacks < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>] | |||
| def up | |||
| create_table :irontrail_change_callbacks, id: :bigserial do |t| | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd call the feature Iron Trail Extensions instead of callbacks.
| create_table :irontrail_change_callbacks, id: :bigserial do |t| | ||
| t.column :rec_table, :text, null: false | ||
| t.column :function_name, :text, null: false | ||
| t.column :enabled, :boolean, default: true, null: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for enable. Record can be created/deleted as needed to serve the same purpose.
| "create_irontrail_trigger_function.rb.erb", | ||
| "db/migrate/create_irontrail_trigger_function.rb" | ||
| ) | ||
| unless self.class.migration_exists?(migration_dir, "create_irontrail_changes") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't think these unlesss are necessary.
| path = File.expand_path("#{function_name}.sql", __dir__) | ||
| sql = File.read(path) | ||
| connection.execute(sql) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this new method and a new irontrail_log_row_function_with_callbacks.sql file duplicating the function that already exists on irontrail_log_row_function.sql?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason to create this file instead of using the existing one?
| operation_char = 'd'; | ||
| END IF; | ||
|
|
||
| IF (change_id IS NOT NULL) THEN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was this if necessary in your tests? it seems to be checking something that should always be satisfied
| 'Extension: ' || ext_func_name || E'\n' || err_ctx, | ||
| TG_OP, TG_TABLE_NAME, row_to_json(OLD), row_to_json(NEW), | ||
| 'Extension function: ' || ext_func_name || ' for change_id: ' || change_id, | ||
| STATEMENT_TIMESTAMP()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should add some sort of indication that this error is from an extension (and which one in a structured way) and not the irontrail core.
|
|
||
| OWN_TRACKABLE_TABLES = %w[ | ||
| irontrail_change_callbacks | ||
| ].freeze |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this constant and declare table on OWN_TABLES above
|
We decided to not introduce features that adds unknown performance implications to the trigger/function loop. |
Add Callbacks support to IronTrail
Overview
This PR adds a callback system to IronTrail, allowing users to execute custom PostgreSQL functions automatically after each change is logged. This enables use cases like real-time notifications, data pipelines, custom auditing, and business logic hooks without modifying the gem or application code.
Changes
irontrail_change_callbackstable to register custom PostgreSQL functionsIrontrailChangeCallbackmodel includesIronTrail::Modelfor tracking changes to the callbacks themselvesHow It Works
Callbacks are PostgreSQL functions that receive three parameters:
change_id(BIGINT) - The ID of the newly createdirontrail_changesrecordrec_table(TEXT) - The name of the table that was changedoperation(TEXT) - The operation type ('i','u', or'd')Callback functions can query the
irontrail_changestable using thechange_idto access full record data (rec_old,rec_new,rec_delta,metadata, etc.).Use Cases
1. Real-Time Notifications
Trigger external notifications when sensitive data changes:
2. Data Pipeline Triggers
Queue data for external processing:
3. Custom Compliance Logging
Log specific changes to a separate compliance table:
Managing Callbacks
Disable an Callback Temporarily
Enable Multiple Callbacks for a Table
Multiple callbacks can be registered for the same table - they will all execute in order:
Important Notes
irontrail_trigger_errorswithout affecting the change or other callbacksIrontrailChangeCallbackmodel itself is tracked by IronTrailTesting
Comprehensive test coverage included:
See CONTRIBUTING.md for detailed testing instructions.
Migration
Users upgrading to v0.2.0 will need to run the new migration generator:
This creates the
irontrail_change_callbackstable required for the feature.Breaking Changes
None - this is a purely additive feature that doesn't affect existing functionality.