fix: edit ops review findings

From the review of 7723711:
- The assembler is locked: a client closed for a full queue is closed
  by the task that was sending, loop(), whose disconnect dropped the
  buffer while async_tcp could be copying into it. A whole message is
  taken out of it, so a disconnect can't free it while it is read.
- loop() expires a message stalled for 10 s, freeing its buffer and
  telling its client, instead of holding it until another client came.
  A binary message is refused before it can touch another's buffer.
- Each edit takes only the fields its route reads; one it would ignore
  is refused by name. linkRemote's rolling code goes in under the
  route's name, so applyModelEdit is unchanged again.
- An edit refused for an id that doesn't exist replies not found
  (edit_result_t::missing). A reply that doesn't fit its buffer goes
  as an internal error, so the op still gets one.
- The TYPE table says what becomes of each op (proto_op_t), which the
  socket switches on. The reply address is one proto_reply_to_t. The
  routes and the ops start and queue an edit the same way
  (newModelEdit, submitModelEdit). The full-list texts and the offered
  remote address rule live in ModelEditor.
- e2e: the sort order test skips a list that it would renumber.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-24 18:10:06 +02:00
parent 77237111ea
commit 8fa087aa89
23 changed files with 486 additions and 257 deletions

View file

@ -2,6 +2,7 @@
#define SOMFY_EDITOR_H
#include <ArduinoJson.h>
#include "ModelEditor.h"
#include "ProtoFrame.h"
// ModelEditor on the device: an edit of the shade model handed from the web
// server task to loop(), which applies it with the ModelEditor rules and tells
@ -9,13 +10,11 @@
// One edit on its way to loop(): the edit route and a copy of its request.
// From an edit route its result goes to every client as requestResult; from a
// protocol 2 edit op, as the reply to replyId for the socket client
// replyClient.
// protocol 2 edit op, as its reply.
struct model_edit_t {
model_edit_type_t type = model_edit_type_t::add_room;
uint32_t requestId = 0;
uint32_t replyClient = 0;
uint32_t replyId = 0;
proto_reply_to_t replyTo;
JsonDocument doc;
};
@ -25,6 +24,12 @@ bool beginModelEdit();
uint32_t nextEditRequestId();
// Gives up an edit that was begun but never queued. Any task.
void cancelModelEdit(model_edit_t *edit);
// Begins an edit of that type: nullptr when one is already waiting or running
// (busy), or there was no memory for it. Any task.
model_edit_t *newModelEdit(model_edit_type_t type, bool &busy);
// Hands a begun edit to loop(); false when the queue is full, and it is given
// up. Any task.
bool submitModelEdit(model_edit_t *edit);
// Applies the edit, saves it, tells how it went and frees it. loop() only.
void runModelEdit(model_edit_t *edit);
// Applies the edit to the shade model and saves it. loop() only.