Versioned migrations for Arcana's GraphRAG tables.
GraphRAG is optional, so it carries its own version separate from
Arcana.Migration. Install it the same way:
defmodule MyApp.Repo.Migrations.AddArcanaGraph do
use Ecto.Migration
def up, do: Arcana.Graph.Migration.up(dimensions: 384)
def down, do: Arcana.Graph.Migration.down()
endUpgrade by adding another host migration that calls up/1. Version 2 adds
relationship provenance DDL and clears legacy relationship facts that have
no source chunk.
Options
:version- target version (defaults to the latest):dimensions- embedding dimensions forarcana_graph_entities.embedding. Must matchArcana.Embedder.dimensions/1for the embedder you run:prefix- Postgres schema to install into (defaults to the connection's current schema):create_schema- whether to create:prefixwhen it is missing (defaults totrue, ignored without a prefix)
Adoption
Installs predating this module have graph tables but no recorded version. Version 1 converges them: it creates only what is absent and adds only the columns and indexes a later release introduced. The one thing it drops is a unique index whose shape is wrong: see "What converge verifies" below.
Where the version is recorded
The applied version is stored as the Postgres comment on arcana_graph_entities, as
exactly arcana_graph:<n>:
SELECT obj_description('arcana_graph_entities'::regclass);Arcana owns that comment. Two consequences worth knowing before you point schema-documentation or data-catalog tooling at this table:
- recording a version replaces whatever comment is there, so a
description you wrote on
arcana_graph_entitiesis lost on the next migration - a comment Arcana doesn't recognise reads as version 0, the same as a
fresh install, so
up/1re-runs the converge path (idempotent, and harmless) whiledown/1declines to drop anything
Comment on any other table freely. Only arcana_graph_entities is reserved.
What converge verifies
Adoption creates only what is absent, so most objects are checked by name alone. Three are verified against the catalog and corrected when they differ, because being merely present isn't enough:
arcana_documents.collection_id's delete rule, since older templates emittedON DELETE SET NULL- the embedding column's dimension, which is compared against
:dimensionsrather than altered - the unique indexes on
arcana_graph_entities(name, collection_id)andarcana_graph_entity_mentions(entity_id, chunk_id), sincecreate_if_not_existsmatches on the index name and an older template may have created one with a different shape
Everything else is create-if-absent. For the plain indexes that is deliberate: a differing one costs performance, not correctness.
Version history
- 1 - entities, relationships, mentions and communities, including the
entity-mention unique index and
communities.summary_fingerprintthat earlier releases shipped as separate upgrade migrations - 2 - canonical relationship facts with per-chunk evidence. Existing relationships are cleared because their source chunks cannot be inferred; rebuild the graph after upgrading
Uninstall ownership
Target version 0 removes only Arcana's graph tables and table-contained
objects. It leaves the core tables, Postgres schema, and vector extension in
place. Foreign keys, views, and materialized views owned by the host
application block uninstall with their schema-qualified identities. Arcana
never uses DROP ... CASCADE, because that would delete host-owned objects.
Summary
Functions
The latest graph version this release of Arcana knows how to migrate to.
Migrates down to :version, or removes the graph tables entirely after
checking for host-owned dependents.
The graph version recorded in the database, or 0 when GraphRAG has never been installed.
Migrates up to :version, or to the latest version.
Functions
The latest graph version this release of Arcana knows how to migrate to.
Migrates down to :version, or removes the graph tables entirely after
checking for host-owned dependents.
The graph version recorded in the database, or 0 when GraphRAG has never been installed.
Pass a repo when calling this outside a migration; inside one it defaults
to the migration's own repo. Pass :prefix to read a version recorded in
a Postgres schema other than the current one.
Both arguments default, so options must be given with a repo:
recorded_version(MyApp.Repo, prefix: "tenant_a"). A lone keyword list
would bind to the repo argument.
Migrates up to :version, or to the latest version.