How the TeslaMate Repair Module Fixes Data Inconsistencies: A Deep Dive
The TeslaMate.Repair module is a background GenServer that periodically scans the database for missing address references in drives and charging processes, then reverse-geocodes the coordinates to populate the missing data.
The teslamate-org/teslamate repository includes a sophisticated data reconciliation system to handle incomplete records caused by earlier imports or transient geocoding failures. Understanding how the Repair module fixes data inconsistencies helps administrators ensure their vehicle logs remain geographically accurate and fully linked to the Address table.
How the Repair Module Detects Missing Addresses
When the GenServer initializes, it schedules a recurring :repair message that executes once per hour by default, plus an immediate run via trigger_run/0 to catch existing issues right away. The detection logic queries two specific tables for orphaned records.
Scanning Drive Records
The module queries lib/teslamate/repair.ex to identify Drive entries where either start_address_id or end_address_id is nil, provided both start and end positions exist. This condition indicates that geocoding failed during the original drive recording.
Scanning Charging Process Records
Similarly, the system locates ChargingProcess rows where address_id is nil but a valid position reference exists. These records appear in lib/teslamate/log/charging_process.ex and represent charging sessions that lack geographic context.
The Repair Loop and Database Updates
The private repair/1 function processes problematic rows recursively. For each entity, it performs three critical operations:
- Logging – Records the start of the repair attempt for observability
- Address resolution – Invokes
get_address_id/1with the associatedPositionto obtain the correct geographic identifier - Changeset application – Constructs an update using
Drive.changeset/2orChargingProcess.changeset/2to fill the missing*_address_idfield(s), then persists the change viaRepo.update/1
Database errors are caught and reported without halting the loop, ensuring that one corrupt record does not block the entire reconciliation batch.
# Inside the Repair module – how a missing address is fixed for a Drive
drive
|> Drive.changeset(%{
start_address_id: get_address_id(drive.start_position),
end_address_id: get_address_id(drive.end_position)
})
|> Repo.update()
Geocoding with Circuit Breaker Protection
The get_address_id/1 function implements defensive programming to prevent overwhelming external APIs. It first checks a Fuse circuit-breaker (:addr_fuse) to verify the geocoding service is healthy.
If the fuse reports :ok, the function sleeps for 1.5 seconds to enforce rate limiting, then calls Locations.find_address/1 in lib/teslamate/locations.ex. This function performs a reverse lookup via the configured geocoder and either returns an existing Address record or creates a new one.
On repeated failures, the module melts the fuse using :fuse.melt/1, which automatically reinstalls after a cooldown period. This pattern prevents endless API calls when the geocoding service is unavailable.
# The recursive repair function (simplified)
defp repair([]), do: :ok
defp repair([entity | rest]) do
# …process entity…
repair(rest)
end
Manual Triggering and Configuration
Administrators can manually initiate a repair cycle from an IEx console without waiting for the hourly schedule. This is useful when importing historical data or recovering from extended geocoding outages.
# Trigger a repair run manually (e.g. from an IEx console)
TeslaMate.Repair.trigger_run()
Summary
- Periodic detection: The Repair module runs hourly by default via GenServer messages, scanning
DriveandChargingProcesstables for nil address references. - Safe updates: Each fix uses Ecto changesets (
Drive.changeset/2,ChargingProcess.changeset/2) and captures errors gracefully to prevent cascading failures. - Protected geocoding: A Fuse circuit-breaker and 1.5-second rate limiting protect the external geocoder from excessive requests during bulk repairs.
- Manual control: The
trigger_run/0function allows immediate reconciliation outside the normal schedule.
Frequently Asked Questions
What causes address data inconsistencies in TeslaMate?
Missing address data typically stems from earlier data imports that predated geocoding features, transient network failures during drive recording, or temporary unavailability of the geocoding service when the vehicle was at a specific location.
How often does the Repair module run automatically?
According to the source code in lib/teslamate/repair.ex, the GenServer schedules repairs to run once per hour by default, plus an immediate execution upon server startup to catch any backlog.
What happens if the geocoding service fails repeatedly?
The module uses the :addr_fuse circuit-breaker pattern. After multiple failures, the fuse melts and blocks further geocoding attempts until it automatically reinstalls, preventing the system from hammering a failing API endpoint.
Can I manually trigger a repair run?
Yes. Call TeslaMate.Repair.trigger_run/0 from an IEx console or another Elixir process to force an immediate scan and repair cycle without waiting for the next scheduled hourly execution.
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 →