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:

  1. Logging – Records the start of the repair attempt for observability
  2. Address resolution – Invokes get_address_id/1 with the associated Position to obtain the correct geographic identifier
  3. Changeset application – Constructs an update using Drive.changeset/2 or ChargingProcess.changeset/2 to fill the missing *_address_id field(s), then persists the change via Repo.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 Drive and ChargingProcess tables 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/0 function 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →