Update dependent feedback atomically with membership and filter poll results

This commit is contained in:
evgeny committed 2026-10-26 14:44:03 +01:00
1 parent 8925503d59
commit 490b30b956
2 files changed
+17 -1

No files matched your search

+10
View File
@@ -1,5 +1,6 @@
#include "chat_poll.h"
#include "chat_feedback.h"
#include "member_sync.h"
#include "chat_core_priv.h"
#include "chat_event.h"
#include "../utun_instance.h"
@@ -120,6 +121,10 @@ int chat_feedback_snapshot(struct UTUN_INSTANCE* inst, const char* channel, cons
sqlite3_bind_blob(st, 1, message_id, 32, SQLITE_STATIC);
while ((step = sqlite3_step(st)) == SQLITE_ROW) {
uint64_t author = (uint64_t)sqlite3_column_int64(st, 0), ver = (uint64_t)sqlite3_column_int64(st, 2);
uint8_t author_key[32];
enum ms_author_status status = member_sync_author_key(inst, channel, author, author_key);
if (status == MS_AUTHOR_ERROR) goto done;
if (status != MS_AUTHOR_ACTIVE) continue;
const uint8_t* data = sqlite3_column_blob(st, 3); size_t len = sqlite3_column_bytes(st, 3);
int kind = sqlite3_column_int(st, 1);
if (kind == CHAT_FEEDBACK_REACTION) {
@@ -191,6 +196,11 @@ void chat_feedback_check_message(struct UTUN_INSTANCE* inst, const char* channel
if (sqlite3_prepare_v2(inst->topo_sqlite_db, sql, -1, &st, NULL) != SQLITE_OK) { poll_db_error(inst, "evaluate query"); return; }
sqlite3_bind_blob(st, 1, message_id, 32, SQLITE_STATIC); int step; unsigned accepted = 0, rejected = 0;
while ((step = sqlite3_step(st)) == SQLITE_ROW) {
uint8_t author_key[32];
enum ms_author_status status = member_sync_author_key(inst, channel,
(uint64_t)sqlite3_column_int64(st, 0), author_key);
if (status == MS_AUTHOR_ERROR) { sqlite3_finalize(st); return; }
if (status != MS_AUTHOR_ACTIVE) continue;
struct chat_poll_answer answer;
if (chat_answer_decode(sqlite3_column_blob(st, 2), sqlite3_column_bytes(st, 2), &answer) < 0
|| !is_poll || !poll_answer_allowed(&poll, &answer)) {
+7 -1
View File
@@ -1,5 +1,6 @@
#include "../routing_layer/topo_group_connect.h"
#include "member_sync.h"
#include "chat_feedback.h"
#include "../routing_layer/topo_node_sqlite.h"
#include "../routing_layer/topo_group.h"
@@ -740,6 +741,8 @@ static int member_apply_record(struct UTUN_INSTANCE* inst, const char* ch_id,
/* ── recompute и подтвердить реальное изменение по хешу ── */
if (changed) {
/* Общий ключ может разрешить удостоверения приглашённых в других каналах. */
if (chat_feedback_member_update(inst, m->node_id) < 0) return MT_ERR_IO;
int rc = merkle_sync_recompute_path(inst, MT_DATA_MEMBERS, ch_id, m->node_id);
if (rc < 0) return -1;
if (rc == 0) changed = 0; /* запись была no-op (данные идентичны) */
@@ -752,6 +755,7 @@ static int member_apply_record(struct UTUN_INSTANCE* inst, const char* ch_id,
void member_sync_record_committed(struct UTUN_INSTANCE* inst, const char* ns, uint64_t node_id) {
merkle_sync_changed(inst, MT_DATA_MEMBERS, ns);
chat_feedback_member_committed(inst, node_id);
struct TOPO_GROUP* g = inst->topo_groups ? topo_groups_find(inst->topo_groups, strtoull(ns, NULL, 10)) : NULL;
struct ETCP_CONN* conn = instance_find_conn(inst, node_id);
if (g && g->group_type == TOPO_GROUP_TYPE_CHAT) {
@@ -946,7 +950,8 @@ int member_sync_verify_and_purge(struct UTUN_INSTANCE* inst, const char* ch_id)
for (int i = 0; i < count; i++) if (topo_node_sqlite_member_del(db, ns, removed[i]) < 0) goto fail;
stage = "index";
for (int i = 0; i < count; i++)
if (merkle_sync_recompute_path(inst, MT_DATA_MEMBERS, ns, removed[i]) < 0) goto fail;
if (merkle_sync_recompute_path(inst, MT_DATA_MEMBERS, ns, removed[i]) < 0
|| chat_feedback_member_update(inst, removed[i]) < 0) goto fail;
stage = "commit";
rc = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL);
if (rc != SQLITE_OK) goto fail;
@@ -956,6 +961,7 @@ int member_sync_verify_and_purge(struct UTUN_INSTANCE* inst, const char* ch_id)
}
for (int i = 0; i < count; i++) {
uint64_t nid = removed[i];
chat_feedback_member_committed(inst, nid);
radio_forget_member_mute(inst, group_id, nid);
struct TOPO_GROUP* g = inst->topo_groups ? topo_groups_find(inst->topo_groups, group_id) : NULL;
struct ETCP_CONN* conn = instance_find_conn(inst, nid);