Documentation
¶
Overview ¶
Package charges persists derived charge sessions.
Index ¶
- func IsOpenLiveFinalState(s string) bool
- type Charge
- type Factory
- type StaleOpenCandidate
- type Store
- func (s *Store) AbandonOpenLive(ctx context.Context, externalID string) (int, error)
- func (s *Store) Close() error
- func (s *Store) CloseStaleOpenLive(ctx context.Context, rivianVehicleID, keepID string) (int, error)
- func (s *Store) CloseStaleOpenLiveBefore(ctx context.Context, before time.Time) (int, error)
- func (s *Store) Count(ctx context.Context) (int, error)
- func (s *Store) Dedupe(ctx context.Context) (int, error)
- func (s *Store) DeleteByExternalID(ctx context.Context, externalID string) (int64, error)
- func (s *Store) LatestOpenLive(ctx context.Context, rivianVehicleID string) (*Charge, error)
- func (s *Store) ListAll(ctx context.Context) ([]Charge, error)
- func (s *Store) ListRecent(ctx context.Context, limit int) ([]Charge, error)
- func (s *Store) ListStaleOpenLive(ctx context.Context, before time.Time) ([]StaleOpenCandidate, error)
- func (s *Store) RefreshOpenLive(ctx context.Context, externalID, finalState string) (int, error)
- func (s *Store) Reset(ctx context.Context) (int64, error)
- func (s *Store) UpdatePricing(ctx context.Context, externalID string, cost float64, currency string, ...) (int64, error)
- func (s *Store) Upsert(ctx context.Context, c Charge) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsOpenLiveFinalState ¶
IsOpenLiveFinalState reports whether s names a charges.final_state value that means the session is physically still in progress. Kept in sync with the inline IN-list in LatestOpenLive et al.
Types ¶
type Charge ¶
type Charge struct {
ID string
VehicleID string
StartedAt time.Time
EndedAt time.Time
StartSoCPct float64
EndSoCPct float64
EnergyAddedKWh float64
MilesAdded float64
MaxPowerKW float64
AvgPowerKW float64
FinalState string
Lat, Lon float64
Source string
Cost float64
Currency string
PricePerKWh float64
// ThermalKWh is the energy the BMS spent on pack heating / cooling
// during the session, surfaced by Rivian's Parallax
// ChargingSessionLiveData protobuf. Nullable: legacy rows
// recorded before this column existed leave it nil so the UI
// can render "—" instead of misleading "0 kWh thermal".
ThermalKWh *float64
}
Charge is a single charging session. ID is the stable external id ("live_<vid>_c_<unix>", "electrafi_<vid>_c_<unix>") and maps to the charges.external_id column. VehicleID is the Rivian gateway string.
type Factory ¶
type Factory struct {
// contains filtered or unexported fields
}
Factory hands out per-user *Store instances. See drives.Factory for the rationale; this is the same shape, scoped to the charges table.
func NewFactory ¶
func NewFactory(d *sql.DB, resolvers *db.VehicleResolverFactory) *Factory
NewFactory wraps the shared pool + resolver factory.
type StaleOpenCandidate ¶
type StaleOpenCandidate struct {
ExternalID string
RivianVehicleID string
FinalState string
EndedAt time.Time
}
StaleOpenCandidate is one row the janitor is considering for abandonment. The rivian-side vehicle ID is denormalised here so the caller can REST-poll the gateway without re-resolving from the internal vehicle UUID.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store wraps the charges table.
func (*Store) AbandonOpenLive ¶
AbandonOpenLive closes one specific open live row as abandoned. The smart janitor calls this only after a REST poll has confirmed the vehicle is no longer in a charging state. Same guarded WHERE as RefreshOpenLive so we never abandon a row that's already been closed legitimately by a terminal-state push between the list and the close.
func (*Store) CloseStaleOpenLive ¶
func (s *Store) CloseStaleOpenLive(ctx context.Context, rivianVehicleID, keepID string) (int, error)
CloseStaleOpenLive marks every live-sourced charge for the vehicle whose external_id is NOT keepID and whose final_state is still a non-terminal "charging_*" as abandoned. Returns rows updated.
func (*Store) CloseStaleOpenLiveBefore ¶
CloseStaleOpenLiveBefore is the unattended janitor variant: marks every open live charge for THIS user whose ended_at is older than `before` as abandoned. Used by the recorder's periodic sweep to self-heal sessions left open by a previous process that died mid-charge and never came back. Returns rows updated.
func (*Store) Dedupe ¶
Dedupe is a no-op on Postgres — UNIQUE (vehicle_id, external_id) prevents the SQLite-era duplicates the old code had to clean up.
func (*Store) DeleteByExternalID ¶
DeleteByExternalID removes a single charge row owned by this user. Returns the number of rows deleted (0 if no match — caller should treat that as 404). Scoped by user_id so a malicious external_id can't reach into another user's data.
func (*Store) LatestOpenLive ¶
LatestOpenLive returns the most recent live-sourced charge for this vehicle whose final_state is still a non-terminal "charging_*" — i.e. the recorder was mid-session when the process stopped.
func (*Store) ListAll ¶
ListAll returns every charge for this user, newest first. Used by the Settings → Backup endpoint.
func (*Store) ListRecent ¶
ListRecent returns the most recent N charges, newest first.
func (*Store) ListStaleOpenLive ¶
func (s *Store) ListStaleOpenLive(ctx context.Context, before time.Time) ([]StaleOpenCandidate, error)
ListStaleOpenLive returns every open live-sourced charge row whose ended_at is older than `before`. Same WHERE shape as CloseStaleOpenLiveBefore but read-only — used by the smarter janitor that wants to REST-confirm the vehicle is actually no longer charging before tagging the row abandoned. WS feeds for long L1/L2 sessions can go silent for hours without the charge having ended.
func (*Store) RefreshOpenLive ¶
RefreshOpenLive bumps ended_at = NOW() on a single open live row and optionally advances its final_state. Used by the smart janitor when a REST poll confirms the vehicle is still actively charging — keeps the row live for another sweep window without abandoning it. The WHERE clause is intentionally narrow (still open, still live) so a concurrent terminal-state push that closed the row legitimately can't be undone here.
func (*Store) UpdatePricing ¶
func (s *Store) UpdatePricing(ctx context.Context, externalID string, cost float64, currency string, pricePerKWh float64) (int64, error)
UpdatePricing overwrites the cost / currency / price-per-kWh of a single charge row, scoped to the current user. Used when the user edits a row in the UI to correct a missing or wrong DCFC price (e.g. a session paid outside the Rivian app). Zeros clear the stored value and let the API-layer fallbacks (home rate, etc.) take over again.