How the TeslaMate Repair Module Identifies and Fixes Data Inconsistencies

The TeslaMate Repair module is a background GenServer that hourly scans the database for Drive and ChargingProcess records missing address associations, then geocodes their positions to fill the gaps using a circuit-breaker pattern.

TeslaMate, the open-source Tesla data logger hosted at teslamate-org/teslamate, occasionally encounters incomplete records where address information is missing due to transient geocoding failures or legacy imports. The TeslaMate.Repair module automatically reconciles these data inconsistencies by linking orphaned drives and charging sessions to valid geographic addresses without manual intervention.

Detecting Missing Address Records

The repair process begins with targeted Ecto queries in lib/teslamate/repair.ex that identify records with incomplete location data while ensuring positional data exists for geocoding.

Identifying Incomplete Drive Records

The module queries for all Drive entries where either start_address_id or end_address_id is nil, but both start and end positions are present. This condition indicates a drive was logged without successful reverse-geocoding of its endpoints.


# Query logic from lib/teslamate/repair.ex (lines 41-57)

from d in Drive,
  where: is_nil(d.start_address_id) or is_nil(d.end_address_id),
  where: not is_nil(d.start_position_id) and not is_nil(d.end_position_id),
  preload: [:start_position, :end_position]

Identifying Incomplete Charging Processes

Similarly, the module identifies ChargingProcess entries where address_id is nil despite having an associated position record.


# Query logic from lib/teslamate/repair.ex (lines 61-68)

from c in ChargingProcess,
  where: is_nil(c.address_id),
  where: not is_nil(c.position_id),
  preload: [:position]

The Repair Execution Loop

Once problematic records are identified, the private repair/1 function processes them recursively, updating the database with correct address associations.

Recursive Record Processing

The function walks through the result list, logging each repair attempt and handling individual failures without aborting the entire batch.


# Simplified recursive structure from lib/teslamate/repair.ex

defp repair([]), do: :ok
defp repair([entity | rest]) do
  # Process entity...

  repair(rest)
end

Changeset Updates and Persistence

For each entity, the module builds an Ecto changeset using Drive.changeset/2 or ChargingProcess.changeset/2, populates the missing *_address_id fields, and persists the update via Repo.update/1.


# Repairing a Drive record with missing addresses

drive
|> Drive.changeset(%{
     start_address_id: get_address_id(drive.start_position),
     end_address_id:   get_address_id(drive.end_position)
   })
|> Repo.update()

Any database errors during this phase are logged but do not stop the repair loop, ensuring subsequent records still process.

Geocoding with Circuit-Breaker Protection

The get_address_id/1 function implements defensive programming to prevent overwhelming the geocoding service during repair operations.

Rate Limiting and Fuse Pattern

Before calling the geocoder, the function checks a circuit-breaker named :addr_fuse. If the fuse is open, the lookup is skipped. If closed, the process sleeps for 1.5 seconds to respect rate limits, then proceeds.


# From lib/teslamate/repair.ex (lines 119-124)

case :fuse.ask(:addr_fuse, :sync) do
  :ok ->
    Process.sleep(1_500)  # Rate limiting

    Locations.find_address(position)
  # ...

end

On repeated failures, the module melts the fuse via :fuse.melt/1, which automatically reinstalls after a cooldown period, preventing endless API calls during outages.

Address Lookup and Creation

The Locations.find_address/1 function (defined in lib/teslamate/locations.ex) performs the reverse geocoding. It either returns an existing Address record or creates a new one based on the latitude and longitude from the position data.

Manual Repair Triggers

While the GenServer schedules automatic repairs once per hour by default, you can initiate an immediate run manually using the public API:


# Trigger repair from IEx console

TeslaMate.Repair.trigger_run()

This is useful after bulk imports or when you notice specific data gaps that need immediate attention.

Summary

  • TeslaMate.Repair is a GenServer in lib/teslamate/repair.ex that runs hourly to fix missing address associations in the database.
  • It detects inconsistencies by querying for Drive records with nil start_address_id/end_address_id and ChargingProcess records with nil address_id, provided positional data exists.
  • The module uses a recursive repair/1 function to update records via Ecto changesets without stopping on individual errors.
  • Geocoding is protected by a circuit-breaker (:addr_fuse) with 1.5-second rate limiting to prevent API abuse.
  • Manual repairs can be triggered via TeslaMate.Repair.trigger_run/0 from the application console.

Frequently Asked Questions

How often does TeslaMate automatically repair data inconsistencies?

By default, the Repair module schedules a repair cycle once per hour using Process.send_after/3. It also triggers an immediate run when the GenServer initializes via trigger_run/0, ensuring that recently imported or updated records are processed quickly after application startup.

What happens if the geocoding service is unavailable during repairs?

The module implements a circuit-breaker pattern using the Fuse library. If geocoding requests fail repeatedly, the fuse melts and blocks further calls until it automatically reinstalls. This prevents the system from hammering a failing API and allows the external service to recover before retrying.

Can I repair specific drives or charging sessions individually?

The public API only exposes trigger_run/0, which scans for all incomplete records across both tables. To target specific records, you would need to interact directly with the TeslaMate.Log.Drive or TeslaMate.Log.ChargingProcess schemas and the TeslaMate.Locations module in an IEx session.

Why do some drives show missing start or end addresses?

Missing addresses typically result from transient geocoding failures during the original data import, network timeouts when the drive was logged, or legacy data migrated from earlier TeslaMate versions. The Repair module exists specifically to backfill these gaps automatically without requiring database manual edits.

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 →