mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
fix: web UI client review findings (step 2a)
- One socket at a time: a socket being replaced is let go without a word, and connect() or a new token while a reconnect waits opens no second one. A new token reconnects at once, without a refused. - Events that came before the schema go as soon as it is whole, ahead of the sync frames formatted after them, not at syncEnd over newer state. - A schema's hash counts only once it has come whole, so a sync cut short gets it again. - Feeds are subscribed again after a reconnect; an unknown feed is refused. - A long op refused as busy without its id goes again. - A sync without repeaters clears them; order changes name their list; a refused resync is called off. - refused: a listener can close() to stop the retries, which the UI does once /loginContext says a login is needed. The client itself can't tell a refused token from a device that is down. - localStorage keeps the schema by default. minify.py removes its work folder even when a bundle fails. ADR 0005 records the two bundles. - Smaller: ProtoSchema.ROWS/withoutRows, ProtoModel.ITEMS, named type numbers, unused feeds map and FakeSocket.all gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
99c6019431
commit
4415beb4f7
8 changed files with 382 additions and 147 deletions
|
|
@ -17,11 +17,11 @@ function recordedSchema() {
|
|||
}
|
||||
// The recorded sync's device sections, expanded, frame by frame.
|
||||
function deviceSections(schema) {
|
||||
return sync.filter((f) => f.t === 4).map((f) => {
|
||||
const d = {};
|
||||
for (const k of Object.keys(f.d)) if (!['T', 'F', 'E', 'Q'].includes(k)) d[k] = f.d[k];
|
||||
return schema.expand(d);
|
||||
});
|
||||
return sync.filter((f) => f.t === 4).map((f) => schema.expand(ProtoSchema.withoutRows(f.d)));
|
||||
}
|
||||
// The recorded sync as the device sends it to a client that has the schema.
|
||||
function syncWithoutSchema() {
|
||||
return sync.map((f) => Object.assign({}, f, { d: ProtoSchema.withoutRows(f.d || {}) }));
|
||||
}
|
||||
// The recorded sync's items under their short keys.
|
||||
function recordedItems(key) {
|
||||
|
|
@ -36,7 +36,7 @@ class FakeSocket {
|
|||
this.sent = [];
|
||||
this.closed = false;
|
||||
FakeSocket.last = this;
|
||||
FakeSocket.all.push(this);
|
||||
FakeSocket.count++;
|
||||
}
|
||||
send(text) { this.sent.push(JSON.parse(text)); }
|
||||
close() {
|
||||
|
|
@ -49,8 +49,9 @@ class FakeSocket {
|
|||
// The device closing it, or refusing it before it opened.
|
||||
drop() { this.close(); }
|
||||
}
|
||||
FakeSocket.all = [];
|
||||
FakeSocket.reset = () => { FakeSocket.all = []; FakeSocket.last = null; };
|
||||
// How many the client has opened.
|
||||
FakeSocket.count = 0;
|
||||
FakeSocket.reset = () => { FakeSocket.count = 0; FakeSocket.last = null; };
|
||||
|
||||
// Timers the test runs by hand.
|
||||
class FakeTimers {
|
||||
|
|
@ -64,9 +65,9 @@ class FakeTimers {
|
|||
};
|
||||
this.clearTimeout = (id) => { this.timers.delete(id); };
|
||||
}
|
||||
// Runs every timer waiting, and returns their delays.
|
||||
// Runs every timer waiting, the shortest first, and returns their delays.
|
||||
runAll() {
|
||||
const due = [...this.timers.entries()];
|
||||
const due = [...this.timers.entries()].sort((a, b) => a[1].ms - b[1].ms);
|
||||
this.timers.clear();
|
||||
for (const [, t] of due) t.fn();
|
||||
return due.map(([, t]) => t.ms);
|
||||
|
|
@ -79,4 +80,5 @@ class FakeStorage {
|
|||
setItem(key, value) { this.items[key] = String(value); }
|
||||
}
|
||||
|
||||
module.exports = { hello, sync, schemaJson, recordedSchema, deviceSections, recordedItems, FakeSocket, FakeTimers, FakeStorage };
|
||||
module.exports = { hello, sync, schemaJson, recordedSchema, deviceSections, syncWithoutSchema, recordedItems, FakeSocket,
|
||||
FakeTimers, FakeStorage };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue