Two mechanisms, easy to mix up.
Filename callbacks are SQL (or Python) files in the migrations directory. They run at a named point in migrate / validate / undo / clean. They are not history rows.
-- migrations/beforeMigrate__set_pragma.sql
PRAGMA foreign_keys = ON;
-- migrations/afterMigrateError__notify.sql
-- runs only if migrate fails
SELECT 1;
See Naming conventions for the nineteen event names and the __ rule.
The Python event bus is for tooling. Every client exposes listeners that receive a typed Event object, never a raw dict.
Subscribing
from dblift.api.events import EventType
def on_script(event):
print(event.event_type.value, event.version, event.execution_time)
client.events.on(EventType.MIGRATION_APPLIED, on_script)
client.events.on("migration.script.*", on_script) # wildcard
client.events.on("*.failed", on_script) # any failure
client.events.off("migration.script.*", on_script)
Patterns match on the whole event string, so "*.started" matches migration.started but not migration.started.extra. Either an EventType member or its string value is accepted everywhere.
| EventEmitter method | Behaviour |
|---|---|
on(event, callback) | Register a listener. Accepts an EventType, an exact string, or a wildcard pattern. |
off(event, callback) | Unregister a listener. Silently ignores a callback that was never registered. |
subscribe / unsubscribe | Aliases for on / off, for consumers coming from RxJS, blinker or Node conventions. |
emit(event, data) | Emit an event. data keys must be declared Event fields. |
clear(event=None) | Drop listeners for one event, or all listeners when called with no argument. |
get_history() | Events in dispatch order. Empty unless the emitter was built with keep_history=True. |
clear_history() | Empty the recorded history. |
start_batch() | Collect events instead of dispatching them. |
flush_batch() | Dispatch everything collected so far and keep batching. |
stop_batch() | Leave batch mode and return the collected events. |
The Event payload
A frozen dataclass. event_type and timestamp are always populated and are owned by the emitter — passing either at emit time raises TypeError. Every other field defaults to None; only the subset the dispatching site provides is set, so read defensively.
| Group | Fields |
|---|---|
| Always populated | event_type · timestamp · name |
| Operation context | operation · target_version · dry_run · show_sql · tags · error · result · summary · config · provider · history_manager · log |
| Script level | script · version · description · type · execution_time |
| Generation and undo | dialect · migration_path · count · migrations_applied · results · success_count · failure_count |
The dataclass is the contract
Unknown keyword arguments at emit time raise
TypeErrorrather than being silently dropped. The dataclass is the single source of truth for the event contract, so a new field has to be declared before it can be emitted.
Event catalogue
87 event strings in 11 groups. MIGRATION_SCRIPT_COMPLETED is a backward-compatible alias of MIGRATION_APPLIED — the same enum member, so iterating EventType yields it once.
| Group | Events |
|---|---|
| Migration | migration.started · migration.completed · migration.failed · migration.script.started · migration.script.completed · migration.script.failed · migration.script.skipped · migration.progress · migration.script.validated · migration.script.validation_failed |
| Validation | validation.started · validation.completed · validation.failed · validation.rule.checked · validation.rule.violation · validation.rule.passed |
| Schema and diff | schema.diff.detected · schema.introspection.started · schema.introspection.completed · schema.introspection.failed · schema.object.detected · diff.analysis.started · diff.analysis.completed · script.risk.detected |
| Connection and provider | connection.established · connection.closed · connection.error · provider.initialized · driver.validation.started · driver.validation.completed · driver.validation.failed |
| History and state | history.loaded · history.updated · state.sync.started · state.sync.completed |
| Undo | undo.started · undo.completed · undo.failed · undo.script.rolled_back |
| Clean | clean.started · clean.completed · clean.failed · clean.object.removed |
| Baseline, repair, info | baseline.started · baseline.completed · baseline.failed · repair.started · repair.completed · repair.failed · info.started · info.completed · info.failed |
| Export | export.started · export.completed · export.failed · export.object.exported · export.file.written |
| Snapshot | snapshot.started · snapshot.completed · snapshot.loaded · snapshot.saved |
| Callback lifecycle | callback.started · callback.completed · callback.failed · callback.before_migrate · callback.after_migrate · callback.after_migrate_error · callback.before_each · callback.after_each · callback.before_each_migrate · callback.after_each_migrate · callback.before_repeatable · callback.after_repeatable · callback.before_versioned · callback.after_versioned · callback.before_validate · callback.after_validate · callback.before_each_validate · callback.after_each_validate · callback.before_clean · callback.after_clean · callback.after_clean_error · callback.before_each_clean · callback.after_each_clean · callback.before_undo · callback.after_undo · callback.after_undo_error |
Isolation and error handling
Each DBLiftClient owns its own emitter and binds it for the duration of every public operation, so script-level events raised deep in the migration engine reach that client's listeners and no other's. A listener that raises is caught and logged; it never interrupts the migration.
Filename callbacks — beforeMigrate__*.sql and the rest — are a separate mechanism. See Naming Conventions.