Spector.Migration (Spector v0.8.0)
View SourceMigration helpers for creating Spector event tables.
Basic Usage
defmodule MyApp.Repo.Migrations.CreateEvents do
use Ecto.Migration
def up, do: Spector.Migration.up(table: "events")
def down, do: Spector.Migration.down(table: "events")
endOptions
:table(required) - The database table name for the events:shards- List of table names for sharded setups (creates multiple tables):hashed- Add ahashcolumn for hash chain integrity (default:false):links- List of link tables to create:[{"table_name", :foreign_key}, ...]
With Table Sharding
For sharded event tables, use :shards to create multiple tables:
def up do
Spector.Migration.up(shards: ["events_0", "events_1", "events_2", "events_3"])
end
def down do
Spector.Migration.down(shards: ["events_0", "events_1", "events_2", "events_3"])
endWhen combining shards with links, a link table is created for each shard by concatenating the shard name to the link table name. For example:
Spector.Migration.up(
shards: ["events_0", "events_1"],
links: [{"ancestors", :ancestor_id}]
)This creates four tables: events_0, events_1, events_0_ancestors, and
events_1_ancestors. If you need a different naming convention, omit the
:links option and use link_up/2 separately for each shard.
With Hash Chain Integrity
If using hashed events, include the :hashed option:
def up, do: Spector.Migration.up(table: "events", hashed: true)
def down, do: Spector.Migration.down(table: "events")With Event Links
To create join tables for event linking (e.g., ancestry tracking):
def up do
Spector.Migration.up(
table: "events",
links: [{"event_ancestors", :ancestor_id}]
)
end
def down do
Spector.Migration.down(
table: "events",
links: [{"event_ancestors", :ancestor_id}]
)
endEach link tuple creates a join table with event_id and the specified foreign key,
along with indexes for efficient queries. A database trigger enforces that both
ends of a link must have the same parent_id (i.e., links can only connect events
within the same record).
Typed Link Tables
To distinguish different relationship types on the same link table, use the
:typed option to add a type integer column:
def up do
Spector.Migration.up(
table: "events",
links: [{"event_links", :linked_id, typed: true}]
)
endThe type column allows a single link table to represent multiple relationship types (e.g., "parent", "sibling", "reference") by assigning each type an integer value.
It is recommended to use an Ecto schema for typed link tables. See the Event Links Guide for examples.
Generated Schema
The migration creates a table with:
id- UUIDv7 primary keyparent_id- Foreign key reference to the first event (self-referential)payload- Map/JSONB column storing the event dataschema- Integer identifying which schema this event belongs toaction- Integer identifying the action (insert, update, delete, or custom)hash- Binary column for SHA-256 hash (only ifhashed: true)inserted_at,updated_at- Timestamps with microsecond precision
Indexes are created on schema and parent_id for efficient queries.
Summary
Functions
Drop the event table(s) and any link tables.
Drop a link table.
Create a link table for many-to-many event relationships.
Create the event table(s) and any link tables.
Functions
Drop the event table(s) and any link tables.
Pass the same options used in up/1 to ensure link tables are also dropped.
Drop a link table.
Example
Spector.Migration.link_down({"event_ancestors", :ancestor_id})
Create a link table for many-to-many event relationships.
Use this to add link tables in a separate migration after the events table exists.
Parameters
events_table- The events table this link table referenceslink_spec- Either{link_table, foreign_key}or{link_table, foreign_key, opts}
Options
:typed- Add atypeinteger column to distinguish different relationship types on the same link table (default:false):constrained- Create a database trigger to enforce that linked events share the sameparent_id(default:true). Set tofalsefor non-PostgreSQL databases.
Examples
Basic link table:
Spector.Migration.link_up("events", {"event_ancestors", :ancestor_id})Link table with type column:
Spector.Migration.link_up("events", {"event_links", :linked_id, typed: true})Link table without parent_id constraint (for non-PostgreSQL databases):
Spector.Migration.link_up("events", {"event_links", :linked_id, constrained: false})
Create the event table(s) and any link tables.
Use :table for a single table or :shards for sharded setups.
See module documentation for available options.