From 288b8091ceb236155caee9094c80c58a84fb5cf5 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 25 Oct 2026 16:26:14 +0100 Subject: [PATCH] Document targeted recovery and retain scheduler diagnostics --- src/chat/chat_sync.h | 6 ++++-- src/chat/merkle_sync.c | 17 ++--------------- tests/test_chat_sync_schedule.c | 3 ++- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/chat/chat_sync.h b/src/chat/chat_sync.h index fe7f88ad..bcac6c09 100644 --- a/src/chat/chat_sync.h +++ b/src/chat/chat_sync.h @@ -1,6 +1,8 @@ /* * chat_sync — связь чат-сервиса с транспортом и группами. * Отслеживает пиров, запускает member_sync, поддерживает кеш каналов и статус в GUI. + * UP/REINIT/пробуждение восстанавливают только общие каналы соответствующего пира. + * Отложенные запросы объединяются по (канал, пир); активными обменами и обновлениями владеет Merkle. * Вход по ссылке держит отдельный NCD handle до результата join, а не только до UP. * JOIN_INFO_REQ → JOIN_INFO_RESP → JOIN_REQUEST → JOIN_READY; правила — в chat_join.h. * Жизненным циклом управляет chat_service_start/stop. Вызовы — в потоке uasync, @@ -101,8 +103,8 @@ void chat_sync_join_channel(struct UTUN_INSTANCE* inst, const char* ch_id, uint6 Вызывается из auto_socket при появлении/изменении сетевой связности. */ void chat_sync_retry_channels_on_socket_change(struct UTUN_INSTANCE* inst); -/* Немедленно убрать канал из кеша chat_sync (локальное удаление канала), - * чтобы cs_on_conn_status не запускал member_sync для удалённого ns до следующего refresh. */ +/* Отменить отложенные запросы канала и немедленно убрать его из кеша (локальное удаление). + * Активные Merkle-сессии отменяет вызывающий код через member_sync_cancel_channel(). */ void chat_sync_on_channel_deleted(struct UTUN_INSTANCE* inst, const char* ch_id); /* Разослать всем подключённым пирам канала смену per-chat настройки «play sound on message». */ diff --git a/src/chat/merkle_sync.c b/src/chat/merkle_sync.c index 3b36bae5..958ce7a1 100644 --- a/src/chat/merkle_sync.c +++ b/src/chat/merkle_sync.c @@ -343,12 +343,8 @@ static void ms_work(void* arg) { s->work = NULL; if (s->state != MS_IDLE || !s->dirty || s->tx) return; int rc; - if (s->leader) { - DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "merkle local work: dataset=%u ns=%s peer=%016llx revision=%llu verified=%llu", - s->dataset->id, s->ns, (unsigned long long)s->peer, - (unsigned long long)s->revision, (unsigned long long)s->verified_revision); - rc = ms_begin(s); - } else { s->dirty = 0; rc = ms_send(s, MS_WAKE, 0, NULL, 0); } + if (s->leader) rc = ms_begin(s); + else { s->dirty = 0; rc = ms_send(s, MS_WAKE, 0, NULL, 0); } if (rc < 0) ms_fail(s, MT_ERR_IO, "start send", 1); } @@ -358,8 +354,6 @@ void merkle_sync_changed(struct UTUN_INSTANCE* inst, uint8_t dataset, const char for (struct ms_session* s = ms->sessions; s; s = s->next) { if (s->dataset->id != dataset || strcmp(s->ns, ns)) continue; s->revision++; s->dirty = 1; - DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "merkle changed: dataset=%u ns=%s peer=%016llx state=%d revision=%llu", - dataset, ns, (unsigned long long)s->peer, s->state, (unsigned long long)s->revision); if (s->state == MS_FAILED) { s->state = MS_IDLE; s->previous_valid = 0; } if (s->state == MS_IDLE && ms_schedule(s) < 0) { ms_fail(s, MT_ERR_IO, "change scheduling", 1); return; @@ -506,10 +500,6 @@ static void ms_receive(struct ETCP_CONN* conn, struct ll_entry* entry) { /* Follower мог отменить и заново подключить namespace. Старый запрос уже некому обслужить. */ ms_discard_tx(s); s->previous_valid = 0; - DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, - "merkle remote wake: dataset=%u ns=%s peer=%016llx state=%d dirty=%d revision=%llu verified=%llu", - dataset, ns, (unsigned long long)s->peer, s->state, s->dirty, - (unsigned long long)s->revision, (unsigned long long)s->verified_revision); rc = ms_begin(s); } } else if (type == MS_BEGIN) { @@ -667,9 +657,6 @@ int merkle_sync_start(struct UTUN_INSTANCE* inst, uint8_t dataset, uint64_t peer u_free(r); return -1; } if (s->state == MS_FAILED) { s->state = MS_IDLE; s->previous_valid = 0; } - DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, - "merkle start request: dataset=%u ns=%s peer=%016llx state=%d dirty=%d revision=%llu callback=%d", - dataset, ns, (unsigned long long)peer, s->state, s->dirty, (unsigned long long)s->revision, cb != NULL); s->dirty = 1; if (s->state == MS_IDLE && ms_schedule(s) < 0) { u_free(r); ms_fail(s, MT_ERR_IO, "start scheduling", 1); return -1; diff --git a/tests/test_chat_sync_schedule.c b/tests/test_chat_sync_schedule.c index 578d0e1d..45650859 100644 --- a/tests/test_chat_sync_schedule.c +++ b/tests/test_chat_sync_schedule.c @@ -71,7 +71,7 @@ static void setup(struct fixture* f) { for (struct ll_entry* e = f->inst->topo_groups->group_list->head; e; e = e->next) { struct TOPO_GROUP* group = (struct TOPO_GROUP*)e; assert(group->group_type == TOPO_GROUP_TYPE_CHAT && channels < 2); - snprintf(f->channel[channels], sizeof(f->channel[channels]), "%s", group->channel_id); + snprintf(f->channel[channels], sizeof(f->channel[channels]), "%llu", (unsigned long long)group->group_id); f->gid[channels++] = group->group_id; } assert(channels == 2); @@ -80,6 +80,7 @@ static void setup(struct fixture* f) { struct ETCP_CONN* conn = etcp_connection_create(f->inst, "schedule peer"); assert(conn); conn->peer_node_id = sc_derive_node_id_from_pubkey(keys.public_key); conn->initialized = 1; conn->links_up = 1; conn->state = 1; + assert(sc_init_ctx(&conn->crypto_ctx, &f->inst->my_keys) == SC_OK); assert(sc_set_peer_public_key(&conn->crypto_ctx, keys.public_key, SC_PEER_PUBKEY_BIN) == SC_OK); assert(etcp_conn_index_peer(conn) == 0); f->peers[i] = conn; uint8_t signature[64] = {0};