How the TeslaMate Release Module Manages Database Migrations
The TeslaMate.Release module serves as the central coordinator for all database migration activities in TeslaMate, leveraging Ecto to apply pending changes, execute rollbacks, and monitor migration status across every configured repository.
The teslamate-org/teslamate repository relies on Ecto for database persistence, but delegates migration orchestration to a dedicated release module. Located at lib/teslamate/release.ex, this module provides idempotent, reliable functions that ensure the database schema remains synchronized with the application code during deployments and rollbacks.
Core Migration Functions
The TeslaMate.Release module exposes a focused public API for managing database state. Each function wraps lower-level Ecto primitives to provide safe, repeatable operations.
migrate/0
The migrate/0 function applies all pending migrations for every Ecto repository defined in the application configuration. According to the source code in lib/teslamate/release.ex, it iterates over the list of repos returned by the private repos/0 function and executes:
Ecto.Migrator.with_repo(repo, fn repo ->
Ecto.Migrator.run(repo, :up, all: true)
end)
This ensures that schema changes are applied transactionally across all configured databases before the application starts serving traffic.
rollback/2
When reverting changes, the rollback/2 function targets a single repository and rolls it back to a specific version. The function signature accepts a repository module and a timestamp version:
def rollback(repo, version) do
# Implementation filters repos list to target repo
# Then executes:
Ecto.Migrator.run(repo, :down, to: version)
end
This selective approach allows operators to revert specific databases without affecting others, using Ecto.Migrator.run/3 with the :down direction and to: version option.
seconds_since_last_migration/0
To support health checks and monitoring, the module provides seconds_since_last_migration/0, which returns the age in seconds of the most recent migration entry. The implementation queries the schema_migrations table directly:
def seconds_since_last_migration do
query =
from(m in "schema_migrations",
select: fragment("EXTRACT(EPOCH FROM (NOW() - inserted_at))")
)
Repo.one(query)
end
This raw SQL fragment calculates the epoch difference between the current time and the inserted_at timestamp of the latest migration record.
repos/0 (Private)
The private repos/0 function bootstraps the application environment to discover configured repositories. As implemented in lib/teslamate/release.ex, it ensures the :ssl application is started, loads the :teslamate application, and retrieves the :ecto_repos configuration:
defp repos do
Application.ensure_all_started(:ssl)
Application.load(:teslamate)
Application.fetch_env!(:teslamate, :ecto_repos)
end
This guarantees that migration commands operate on the complete set of repositories defined in config/config.exs or environment-specific configuration files.
Practical Usage Examples
During deployment, operators invoke these functions from IEx sessions or release scripts to ensure database consistency.
Running All Pending Migrations
To apply all pending migrations across every configured repository:
TeslaMate.Release.migrate()
This is typically executed from a Docker entrypoint script or distillery boot hook before the web server starts.
Rolling Back to a Specific Version
If you need to revert the primary repository to a previous state:
TeslaMate.Release.rollback(TeslaMate.Repo, 20210831153305)
Only the specified repository is affected; all other repos remain at their current versions.
Checking Migration Status
For health monitoring or debugging, retrieve the time elapsed since the last migration:
seconds = TeslaMate.Release.seconds_since_last_migration()
IO.puts("Last migration ran #{seconds} seconds ago")
Key Source Files
Understanding the migration system requires familiarity with these components:
lib/teslamate/release.ex— Contains the coreTeslaMate.Releasemodule withmigrate/0,rollback/2, and monitoring functions.priv/repo/migrations/— Directory containing individual migration files that define schema changes; these are executed by the release module.config/config.exs— Defines the:ecto_reposlist thatTeslaMate.Releasereads to determine which repositories to manage.mix.exs— Declaresecto_sqland related dependencies required for migration support.
Summary
- The
TeslaMate.Releasemodule inlib/teslamate/release.excentralizes all database migration logic for the application. - migrate/0 applies pending changes across all configured Ecto repositories using
Ecto.Migrator.run/3withall: true. - rollback/2 reverts a specific repository to a target version using the
:downdirection. - seconds_since_last_migration/0 queries the
schema_migrationstable directly to determine migration age. - The module is invoked during deployment scripts to ensure schema consistency before application startup.
Frequently Asked Questions
How does TeslaMate apply migrations during deployment?
TeslaMate applies migrations by invoking TeslaMate.Release.migrate/0 from the release script or container entrypoint. This function loads the application configuration, discovers all repositories via the private repos/0 function, and executes Ecto.Migrator.run/3 with the :up direction to apply pending changes.
Can I roll back migrations for only one database?
Yes. The rollback/2 function accepts a specific repository module (such as TeslaMate.Repo) and a version timestamp. It filters the configured repositories to match only the supplied module, then executes the rollback using Ecto.Migrator.run/3 with to: version, leaving other repositories unaffected.
How can I verify when the last migration was applied?
Use the seconds_since_last_migration/0 function, which returns the number of seconds since the most recent entry in the schema_migrations table. This is useful for health checks that verify the database schema is current.
Where does TeslaMate store migration files?
Migration files reside in priv/repo/migrations/ within the repository. Each file contains an Ecto migration module defining specific schema changes, which TeslaMate.Release discovers and executes based on the version timestamps recorded in the database's schema_migrations table.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →