mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
docs: record group reads emitting events from the web server task
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
8d4c621d5a
commit
d9287a9e1f
1 changed files with 32 additions and 0 deletions
|
|
@ -90,3 +90,35 @@ Unlike the `/controller` HTTP crash, this path does **not** abort — there is n
|
|||
|
||||
- Not the same code path as the `/controller` crash. Solve independently.
|
||||
- Worth grepping for `JsonSockEvent` usages that iterate collections (see references in `SomfyEvents.cpp`, `Transceiver.cpp`, `ESPNetwork.cpp`, `GitOTA.cpp`) to identify the most at-risk events.
|
||||
- [Group reads emit events from the web server task](#group-reads-emit-events-from-the-web-server-task): a second task writing the same buffer.
|
||||
|
||||
## Group reads emit events from the web server task
|
||||
|
||||
**Status:** open
|
||||
**Location:** `serializeGroupRef` in [src/entryPoints/Web.cpp](../src/entryPoints/Web.cpp) calls `SomfyGroup::updateFlags()` in [src/SomfyGroup.cpp](../src/SomfyGroup.cpp).
|
||||
|
||||
### Summary
|
||||
|
||||
Serializing a group for an HTTP reply first calls `group->updateFlags()`. When the group's flags no longer match its shades', that writes `group->flags`, sends a `groupState` socket event and publishes the group's MQTT topics, all on the async_tcp task, while `loop()` sends events and publishes too.
|
||||
|
||||
Every socket event is formatted into the one static buffer `g_response` in [src/outputs/Sockets.cpp](../src/outputs/Sockets.cpp) through the one `JsonSockEvent` in `sockEmit`. Two tasks emitting at once write over each other's event. The MQTT client (PubSubClient) isn't safe to use from two tasks either.
|
||||
|
||||
Reached from every route that serializes a group: `/controller`, `/discovery`, `/groups`, `/group`, `/groupCommand`, `/addGroup`, `/saveGroup`, `/linkToGroup`, `/unlinkFromGroup` and others.
|
||||
|
||||
### Concrete failure modes
|
||||
|
||||
1. A `groupState` from a `/groups` request and a `shadeState` from `loop()` are formatted at the same time: clients receive garbled JSON, or an event with another event's fields.
|
||||
2. The group's MQTT publish interleaves with one from `loop()` in the client's buffer, and the broker gets a broken packet or the connection drops.
|
||||
3. `group->flags` is written on async_tcp while `loop()` updates the same group through `updateGroupFlags()`.
|
||||
|
||||
It needs a group whose flags are out of date at the moment a client reads it, for example right after a sensor frame changed a linked shade's sun or wind flags, so it is rare.
|
||||
|
||||
### Fix options
|
||||
|
||||
- **(a) Drop `updateFlags()` from the serializers.** `loop()` already keeps group flags current through `updateGroupFlags()`. This is part of step 2 of [LOOP_QUEUE_PLAN.md](LOOP_QUEUE_PLAN.md): reads come from a ModelSnapshot that `loop()` fills, and serializers only read.
|
||||
- **(b) Only emit from `loop()`.** Covered by ADR-0002 once nothing outside `loop()` changes the shade model.
|
||||
|
||||
### Related
|
||||
|
||||
- [ADR-0002](adr/0002-loop-task-is-the-only-writer-of-the-shade-model.md): the loop task is the only writer of the shade model.
|
||||
- [Large websocket events are dropped](#large-websocket-events-are-dropped): the same `g_response` buffer.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue