Pipelines & Events Reference
VirtualDB's extension model is built on two primitives.
A pipeline is an ordered sequence of named points. When something happens — a query arrives, rows are fetched, a transaction commits — VirtualDB runs the corresponding pipeline. Handlers registered at a point are called in priority order and can inspect or modify the data passing through.
An event is a fire-and-forget notification emitted after a pipeline completes. Events are for observation, not transformation — subscribe to an event when you need to react to something without blocking the path that triggered it.
Pipelines
vdb.context.create
Fired once at startup, before any connections are accepted. Used to initialize the global context shared across all sessions.
| Point | Description |
|---|---|
vdb.context.create.build_context | Allocates the initial global context object. |
vdb.context.create.contribute | Allows handlers to add values to the context. |
vdb.context.create.seal | Seals the context — no further contributions accepted. |
vdb.context.create.emit | Fires startup-time events. |
vdb.server.start
Fired after the global context is sealed, just before the server binds its port.
| Point | Description |
|---|---|
vdb.server.start.build_context | Builds the context for the start sequence. |
vdb.server.start.configure | Applies final server configuration. |
vdb.server.start.launch | Starts the server and binds the TCP listener. |
vdb.server.start.emit | Emits the server-started notification. |
vdb.server.stop
Fired when VirtualDB receives a shutdown signal (SIGTERM or SIGINT).
| Point | Description |
|---|---|
vdb.server.stop.build_context | Builds the context for the stop sequence. |
vdb.server.stop.drain | Waits for in-flight requests to complete. |
vdb.server.stop.halt | Closes the listener and terminates the server. |
vdb.server.stop.emit | Emits vdb.server.stopped. |
vdb.connection.opened
Fired after a client completes the MySQL authentication handshake.
| Point | Description |
|---|---|
vdb.connection.opened.build_context | Builds the per-connection context with the authenticated user and remote address. |
vdb.connection.opened.accept | Gate point — a handler that returns an error refuses the connection. |
vdb.connection.opened.track | Registers the connection in VirtualDB's connection state map. |
vdb.connection.opened.emit | Emits vdb.connection.opened. |
vdb.connection.closed
Fired when a client disconnects, regardless of the reason.
| Point | Description |
|---|---|
vdb.connection.closed.build_context | Builds the context for the teardown sequence. |
vdb.connection.closed.cleanup | Discards any in-progress transaction delta for this connection. |
vdb.connection.closed.release | Removes the connection from the state map. |
vdb.connection.closed.emit | Emits vdb.connection.closed. |
vdb.transaction.begin
Fired when a transaction starts, whether via an explicit BEGIN or implicitly in autocommit mode.
| Point | Description |
|---|---|
vdb.transaction.begin.build_context | Builds the context, including whether the transaction is read-only. |
vdb.transaction.begin.authorize | Gate point — a handler that returns an error refuses the transaction. |
vdb.transaction.begin.emit | Emits vdb.transaction.started. |
vdb.transaction.commit
Fired when a transaction is committed.
| Point | Description |
|---|---|
vdb.transaction.commit.build_context | Builds the context for the commit sequence. |
vdb.transaction.commit.apply | Merges the transaction's private delta into the live process delta. |
vdb.transaction.commit.emit | Emits vdb.transaction.committed. |
vdb.transaction.rollback
Fired when a transaction is rolled back, fully or to a named savepoint.
| Point | Description |
|---|---|
vdb.transaction.rollback.build_context | Builds the context, including the savepoint name (empty string for a full rollback). |
vdb.transaction.rollback.apply | Discards the transaction's private delta. |
vdb.transaction.rollback.emit | Emits vdb.transaction.rolledback. |
vdb.query.received
Fired when a SQL statement arrives, before the SQL engine executes it. This is the primary interception point for query rewriting.
| Point | Description |
|---|---|
vdb.query.received.build_context | Builds the context with the raw SQL string and current database name. |
vdb.query.received.intercept | Transformation point. A handler may return a modified SQL string; VirtualDB executes the replacement. |
vdb.query.received.emit | No event here — vdb.query.completed is emitted after execution. |
vdb.records.source
Fired after rows are fetched from the source database, before the delta overlay is applied.
| Point | Description |
|---|---|
vdb.records.source.build_context | Builds the context with the table name and the raw record slice. |
vdb.records.source.transform | Transformation point. Handlers may add, remove, or modify rows. The built-in delta overlay runs here at priority 10. |
vdb.records.source.emit | Notifies subscribers that source records are available. |
Priority and the delta overlay
Handlers registered at vdb.records.source.transform with priority < 10 see raw source rows before the delta is applied. Handlers with priority > 10 see the merged rows after the overlay. See Plugins for more.
vdb.records.merged
Fired after the delta has been overlaid on source rows, producing the final result set. This is the last opportunity to modify rows before they reach the client.
| Point | Description |
|---|---|
vdb.records.merged.build_context | Builds the context with the post-merge record slice. |
vdb.records.merged.transform | Transformation point. Handlers may make final adjustments to outgoing rows. |
vdb.records.merged.emit | Notifies subscribers that the merged records are ready. |
vdb.write.insert
Fired once per row when an INSERT is processed.
| Point | Description |
|---|---|
vdb.write.insert.build_context | Builds the context with the table name and the new row. |
vdb.write.insert.apply | Records the row as a new insert in the delta. Handlers may modify the record. |
vdb.write.insert.emit | Emits vdb.record.inserted. |
vdb.write.update
Fired once per row when an UPDATE is processed.
| Point | Description |
|---|---|
vdb.write.update.build_context | Builds the context with the table name and both the old and new row. |
vdb.write.update.apply | Records the update overlay in the delta. Handlers may modify the new row before it is stored. |
vdb.write.update.emit | Emits vdb.record.updated. |
vdb.write.delete
Fired once per row when a DELETE is processed.
| Point | Description |
|---|---|
vdb.write.delete.build_context | Builds the context with the table name and the deleted row. |
vdb.write.delete.apply | Records a tombstone in the delta, removing any prior overlay for the same row. |
vdb.write.delete.emit | Emits vdb.record.deleted. |
Events
Events are emitted after their corresponding pipeline completes. Subscribe to observe state changes without blocking the request path.
| Event | Emitted when |
|---|---|
vdb.server.stopped | The server has fully shut down and the port has been released. |
vdb.connection.opened | A client connection has been accepted and is being tracked. |
vdb.connection.closed | A client connection has been released. |
vdb.transaction.started | A transaction has been authorized and begun. |
vdb.transaction.committed | A transaction has committed and its delta merged into the live store. |
vdb.transaction.rolledback | A transaction has been rolled back (full or to a savepoint). |
vdb.query.completed | A query has finished. Payload includes the SQL string, rows affected, and any error. |
vdb.record.inserted | A row has been stored in the delta as an insert. |
vdb.record.updated | An update overlay has been recorded in the delta. |
vdb.record.deleted | A tombstone has been recorded in the delta. |
vdb.schema.loaded | Schema metadata for a table has been loaded from the source. Payload includes the table name, columns, and primary key. |
vdb.schema.invalidated | Schema metadata for a table has been invalidated and will reload on next access. |
Handler priorities
When multiple handlers are registered at the same pipeline point, they run in ascending priority order — lower numbers run first. Priorities do not need to be unique or contiguous.
Plugin-declared pipelines and events
Plugins are not limited to the built-in pipelines. A plugin may declare its own pipelines and events in its declare notification, making them available for other plugins to attach to. See Plugins for details.
Related
- Plugins — writing a plugin and the JSON-RPC protocol
- How It Works — the delta model and query lifecycle