Treat missing FinalStopActive observation as inactive#38
Merged
martijnversluis merged 1 commit intoJun 3, 2026
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Voorkomt
KeyError: key not found: :FinalStopActivewanneer Zaptec's/api/chargers/{id}/stateendpoint geenFinalStopActiveobservatie teruggeeft. Een charger zonder die observatie wordt nu correct als "niet final-stopped" behandeld in plaats van te crashen.Root cause
Zaptec::State#final_stop_active?(lib/zaptec/state.rb:27) gebruikt@data.fetch(:FinalStopActive), terwijl het Zaptec state endpoint observaties spaars teruggeeft — een charger die nooit een FinalStop event heeft geëmit heeft simpelweg geen row 718 in de response. De omliggendepaused?short-circuit'te dit toen de methode nog privé was (mode-check eerst), maar sinds #35 wordtfinal_stop_active?ook door externe callers (StekkerWeb'sConnections::Zaptec#info_for) onvoorwaardelijk aangeroepen, en die zien wél de KeyError.Waarom-keten
ChargePointRefreshJob? →Connections::Zaptec#info_forroeptcharger_state.final_stop_active?aan en die raised KeyError.@data.fetch(:FinalStopActive)faalt omdat:FinalStopActiveniet in de hash zit.final_stop_active?privé en alleen aangeroepen viapaused?, die eerstcharger_operation_mode == CONNECTED_FINISHEDcheckt. Een charger zonder FinalStopActive zit per definitie niet in dat mode, dus de korte-sluiting zorgde datfetchnooit liep. Sinds Expose final_stop_active? for diagnostic sampling #35 callen externe consumersfinal_stop_active?rechtstreeks zonder die guard.Waarom nu
#35 (gemerged 2026-04-17) maakte
final_stop_active?publiek. StekkerWeb PR #7479 (zelfde dag) begon meteeninfo_foronvoorwaardelijk te callen voor connector_status sampling, en commit5af1f603(2026-05-20) deed hetzelfde voorresume_charging. Beide call sites raken nu chargers waarvan de Zaptec state response geen:FinalStopActivebevat → KeyError in productie (Sentry issue 2016).Blast radius
Iedere Zaptec charger waarvan de state-response geen
FinalStopActiveobservatie bevat — typisch nieuw gekoppelde chargers en chargers die nooit een FinalStop event hebben geëmit. ElkeChargePointRefreshJobvoor zo'n charger faalt sinds StekkerWeb #7479 (2026-04-17). Resume-paths (Connections::Zaptec#resume_charging) zijn sinds 2026-05-20 ook gevoelig.Gekozen oplossing
final_stop_active?gebruikt nu@data[:FinalStopActive].to_i == 1in plaats vanfetch.nil.to_i == 0, dus een ontbrekende key evalueert naarfalse. Dit volgt het bestaande patroon in dezelfde file:session_identifier(regel 31-34) gebruikt al@data[:SessionIdentifier]voor dezelfde reden. Dit adresseert why 3 (sparse API-respons) door de gem te aligneren met het werkelijke API-contract — niet why 1 (de KeyError op zich).Alternatieven overwogen
info_for/resume_charging: symptom-fix op de verkeerde laag. De gem heeft het verkeerde contract; zelfspaused?zou crashen als ooit een externe caller hem metCONNECTED_FINISHEDmode + missing key zou raken. Twee rescues op twee call-sites in plaats van één fix op de juiste plek.Client#statemet defaults: vereist een mapping van elke observation naar zijn semantisch correcte default. Zwaar voor een gem die het bewust aan elke method overlaat (ziesession_identifiervstotal_charge_power).Reproductie
spec/zaptec/state_spec.rb: een nieuwe test"is false when the FinalStopActive observation is missing from the API response"faalt vóór de fix met exact dezelfdeKeyError: key not found: :FinalStopActiveals in Sentry, en slaagt erna.Follow-up
Na merge:
bundle update stekker_zaptecinstekker/stekkerom de gem-bump uit te rollen — anders blijft Sentry 2016 doorvuren tot de productie de nieuwe sha pakt.Sentry: https://sentry2.stekker.app/organizations/sentry/issues/2016/