Extract DB records from compound state tuples: simple atoms (Phase 5 final)#5259
Extract DB records from compound state tuples: simple atoms (Phase 5 final)#5259brianmay wants to merge 6 commits intomcu2-upgraded-carsfrom
Conversation
…compound states
These fields prepare for the next refactoring step where we'll move DB records
out of compound state tuples like {:driving, status, %Log.Drive{}} into dedicated
Data struct fields.
This commit only adds the fields without using them yet, keeping the change
minimal and focused. Future commits will:
1. Update state transitions to populate these fields
2. Update pattern matches to read from fields instead of state tuples
3. Remove compound states in favor of simple atoms
No behavior changes in this commit.
Each transition into {:driving, ...}, {:charging, ...}, or {:updating, ...}
now also updates the corresponding Data struct fields:
- current_drive / driving_status (all 9 driving transitions)
- current_charging_process (both charging entry points)
- current_update (single update entry)
The compound state tuples are unchanged so all existing pattern matches
continue to work. The struct fields mirror the tuple contents and will be
used for reads in a future PR, at which point the compound tuples can be
replaced with simple atoms.
No behaviour changes.
|
This is only the first phase so far, we haven't seen the simplification to the compound state tuples yet. That will come later. |
|
As before, this was done with AI. It was going to make one big pull request, then we agreed that breaking it up might be better. |
c7b2015 to
5ccde37
Compare
5ccde37 to
ba33348
Compare
This PR migrates all pattern-match reads of compound state tuples
({:driving, status, drive}, {:charging, cproc}, {:updating, update})
to use the corresponding Data struct fields instead.
Changes:
- vehicle_in_service driving case: guard on data.current_drive != nil,
read drive from data.current_drive, clear both current_drive and
driving_status on exit from driving state
- remaining_distance interval: use {current_drive, current_charging_process}
tuple instead of compound state pattern match
- asleep handler: guard on driving_status != nil && driving_status != :available
to detect offline sub-states, clear driving_status on :start exit
- fetch can_fall_asleep?: add guards on current_drive/update/charging_process
- fetch reachable: same guards added
- All 6 transitions to :start from driving state now clear driving_status: nil
The compound state tuples remain in next_state positions (handled in prior
PR), so this is purely a read migration. No behaviour changes expected.
No behaviour changes - all guards are guaranteed true at runtime given
correct dual-write population from prior PR.
This is the final step in the state machine simplification. After this
commit, the GenState state is always a simple atom (:driving, :charging,
:updating, :start, :asleep, :offline, :online, :suspended) instead of
compound tuples like {:driving, status, drive}.
Changes:
- All 12 next_state positions now use simple atoms instead of compound
tuples {:driving, :available, drive}, {:driving, {:unavailable, n}, drv},
{:driving, {:offline, last}, drive}, {:charging, cproc},
{:updating, update}
- Driving sub-state (available/unavailable/offline) is tracked in
data.driving_status instead of the state tuple's second element
- DB records (drive, cproc, update) are read from data.current_drive,
data.current_charging_process, data.current_update
- All driving handlers now match :driving with guards on driving_status:
:available, {:unavailable, n}, {:offline, last}
- suspend_logging handlers updated to match simple atoms
- fetch/can_fall_asleep and fetch/reachable updated to use simple atoms
- Summary module updated: format_state/2 now takes driving_status to
correctly format :driving/:offline display state
- broadcast_summary passes driving_status to Summary.into
This change makes the state machine significantly more readable. The 3-element
tuple {:driving, status, drive} is now just :driving, with status and
drive accessible as data.driving_status and data.current_drive.
|
I decided to do the full refactor in one pull request. While this the PR more complicated, don't think you can really review this probably unless you can see the entire picture. The steps are still there, but as separate commits. Which probably should stay as separate commits. Key questions before merging:
I think by making the state an enum only and putting state data into the data variable we have made it easier to understand. If anyone disagrees, feel free to speak out :-)
It looks OK to me... Although certainly is scope for errors to creep in. Guess next step will be to test this. |
The interval calculation for API errors was unnecessarily restructured during the read-migration phase. The original case on state was still correct at that point and should have remained unchanged. With simple atoms now in place, the correct form is restored: :driving -> 10 :charging -> 15 :online -> 20 _ -> 30 This is a 4-line case expression instead of the 14-line restructure that was added during read migration.
f2d2ed5 to
2f1f3fe
Compare
|
I spotted a place where the logic had been changed and was more complicated then required. Fixed now. |
The guards 'when data.current_drive != nil' etc. on the simple atom patterns ':driving', ':updating', ':charging' are unnecessary. The state atom itself is the source of truth - if we're in ':driving', the dual-write invariant guarantees current_drive is populated. The guards added nothing over the atom pattern match.
Summary
This PR completes the state machine simplification by replacing compound state tuples like
{:driving, status, %Log.Drive{}},{:charging, %Log.ChargingProcess{}}, and{:updating, %Log.Update{}}with simple atoms (:driving,:charging,:updating). DB records and sub-states are stored inDatastruct fields.Changes (4 commits)
Commit 1: Add preparatory fields to Data struct
Adds
current_drive,current_charging_process,current_update, anddriving_statusfields.Commit 2: Populate Data struct fields in parallel with compound state tuples
Every transition into a compound state now also updates the corresponding struct fields.
Commit 3: Migrate compound state reads to struct field guards
Replaces pattern-match reads with guards on the struct fields.
Commit 4: Replace compound state tuples with simple atoms throughout state machine
This is the main simplification commit. After this:
{:driving, status, drive}→:driving(status indata.driving_status, drive indata.current_drive){:charging, cproc}→:charging(cproc indata.current_charging_process){:updating, update}→:updating(update indata.current_update)Key changes in this commit:
next_statepositions now use simple atomsdata.driving_statusinstead of the state tuple's second element:drivingwith guards ondriving_statussuspend_logging,fetch/can_fall_asleep, andfetch/reachableall use simple atom matchingSummarymodule updated to handle the new state formatRefactoring sequence (complete!)
fake_online_stateintegers withpre_online_checkatomsBefore vs After
Before (hard to read):
After (clean):
Testing
All commits are no-behaviour-change mechanical refactors. Existing tests pass.