fix: отказ kio.patch возвращает серверные значения, каталог служб проверяется на входе, без дублей с notify

This commit is contained in:
GGlamer 2026-09-27 22:23:15 +03:00
commit 30bf109ad0
5 changed files with 144 additions and 35 deletions

View file

@ -74,6 +74,18 @@ socket.receive({ type: "kio.patch", fields: {
}, source: "operator" });
socket = reconnect(socket);
assert.deepEqual(socket.sent, [], "matching checkpoint echo clears the KIO patch");
const refused = { type: "kio.patch", fields: { address: "ул. Новая, 3", notify_extra: ["Нет в каталоге"] } };
call.send(refused);
socket.receive({ type: "kio.patch", fields: { address: patch.fields.address, notify_extra: [] }, source: "auto" });
socket.sent = [];
call.send({ type: "kio.patch", fields: { floor: "2" } });
assert.deepEqual(socket.sent.at(-1).fields, { floor: "2" },
"server values after a refused patch acknowledge it: refused fields are not merged into the next edit");
socket.receive({ type: "kio.patch", fields: { floor: "2" }, source: "operator" });
socket = reconnect(socket);
assert.deepEqual(socket.sent, [], "nothing left to replay after refusal and the next echo");
const refusedCard = applyPatch(edit(empty, "notify_extra", ["Нет в каталоге"]), { notify_extra: [] }, "auto");
assert.deepEqual(refusedCard.pending, {}, "server value after refusal drops the pending edit");
const edited = edit(empty, "coords", { latitude: 55.7, longitude: 37.6 });
assert.deepEqual(applyPatch(edited, { coords: { longitude: 37.6, latitude: 55.7 } }, "operator").pending, {});
assert.deepEqual(applyState(edited, { coords: { longitude: 37.6, latitude: 55.7 } }).pending, {});

View file

@ -164,8 +164,17 @@ export const callChannel = (
...options,
queueKey: (event) => event.type === "kio.patch" ? "kio.patch" : null,
isAcknowledged: (incoming, pending) => {
if (pending.type !== "kio.patch" || incoming.type !== "kio.patch"
|| incoming.source !== "operator") return false;
if (pending.type !== "kio.patch" || incoming.type !== "kio.patch") return false;
// `auto` по всем полям команды с другим значением — сервер её переписал
// (так он отвечает и на отклонённый пакет), а merge.ts уже снял правку из
// pending. Повтор затёр бы серверную истину, а слияние с новыми правками
// отклоняло бы и их. Совпадающий `auto` ничего не доказывает: команда
// могла не дойти, повтор безвреден.
if (incoming.source === "auto") {
const keys = Object.keys(pending.fields);
return keys.every((key) => key in incoming.fields)
&& keys.some((key) => !sameJsonValue(pending.fields[key], incoming.fields[key]));
}
return Object.entries(pending.fields).every(([key, value]) =>
sameJsonValue(value, incoming.fields[key]),
);