Browse Source

Preserve input cursor when member page outputs alias it

master
evgeny 5 days ago
parent
commit
864a250eea
  1. 47
      src/chat/chat_feedback.h
  2. 2
      src/chat/member_sync.c

47
src/chat/chat_feedback.h

@ -0,0 +1,47 @@
/* Подписанные состояния реакций и ответов, отдельная таблица feedback_<channel>.
* Каждый (message_id, node_id, kind) хранит последнее полное состояние с ver.
* Пустое data — сохраняемая отмена. Слой хранит и реплицирует подписанные байты;
* интерпретацию ответа относительно опроса выполняет вызывающий модуль.
* Все операции — в uasync-потоке. init вызывается после member_sync_init;
* общий Merkle-движок освобождается member_sync_destroy. */
#ifndef CHAT_FEEDBACK_H
#define CHAT_FEEDBACK_H
#include <stdint.h>
#include <stddef.h>
struct UTUN_INSTANCE;
#define CHAT_FEEDBACK_REACTION 1
#define CHAT_FEEDBACK_ANSWER 2
#define CHAT_FEEDBACK_DATA_MAX 2048
#define CHAT_MESSAGE_ID_SIZE 32
struct chat_feedback_record {
uint8_t message_id[CHAT_MESSAGE_ID_SIZE];
uint64_t node_id;
uint64_t ver; /* 1..INT64_MAX; отдельная версия для каждого kind */
uint8_t kind;
uint16_t data_len;
uint8_t data[CHAT_FEEDBACK_DATA_MAX];
uint8_t signature[64];
};
/* Производный ID неизменяемого сообщения; 0/-1. Числа хешируются как BE64. */
int chat_message_id(uint64_t channel_id, uint64_t timestamp, const uint8_t signature[64], uint8_t id[32]);
/* Регистрирует FEEDBACK и восстанавливает производный индекс из подписанных записей; 0/-1. */
int chat_feedback_init(struct UTUN_INSTANCE* inst);
/* Подготовить таблицу канала; 0/-1. Не создаёт членство или сетевую группу. */
int chat_feedback_ensure_channel(struct UTUN_INSTANCE* inst, const char* channel);
/* Прочитать состояние: 1 найдено, 0 отсутствует, -1 ошибка. */
int chat_feedback_get(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message_id[32],
uint64_t node_id, uint8_t kind, struct chat_feedback_record* out);
/* Проверить и применить подписанную запись: 1 изменилось, 0 повтор/старая, -1 ошибка.
* Одинаковый ver разрешается сравнением data; подпись проверяется до сравнения. */
int chat_feedback_apply(struct UTUN_INSTANCE* inst, const char* channel, const struct chat_feedback_record* record);
/* Подписать локальное полное состояние с ver+1; NULL/0 отменяет. 1/0/-1 как apply.
* out_ver необязателен. Семантику data проверяет вызывающий модуль до этого вызова. */
int chat_feedback_set(struct UTUN_INSTANCE* inst, const char* channel, const uint8_t message_id[32],
uint8_t kind, const uint8_t* data, size_t len, uint64_t* out_ver);
#endif

2
src/chat/member_sync.c

@ -209,12 +209,12 @@ static int _member_get_page(void* ctx, const char* ns, uint64_t prefix, int afte
struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)ctx; struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)ctx;
sqlite3* db = _db(inst); if (!db || !buf || !len) { DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: get_items — invalid args db=%p buf=%p len=%p", MS_ID, (void*)db, (void*)buf, (void*)len); return -1; } sqlite3* db = _db(inst); if (!db || !buf || !len) { DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: get_items — invalid args db=%p buf=%p len=%p", MS_ID, (void*)db, (void*)buf, (void*)len); return -1; }
const uint8_t level = MT_MAX_LEVEL; const uint8_t level = MT_MAX_LEVEL;
memset(next, 0, sizeof(*next)); *more = 0;
uint64_t after_id = member_read64(after->bytes); uint64_t after_id = member_read64(after->bytes);
static const uint8_t zero_tail[MT_KEY_SIZE - 8]; static const uint8_t zero_tail[MT_KEY_SIZE - 8];
if (after_valid && memcmp(after->bytes + 8, zero_tail, sizeof(zero_tail))) { if (after_valid && memcmp(after->bytes + 8, zero_tail, sizeof(zero_tail))) {
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: invalid member cursor ns=%s", MS_ID, ns); return -1; DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: invalid member cursor ns=%s", MS_ID, ns); return -1;
} }
memset(next, 0, sizeof(*next)); *more = 0;
DEBUG_TRACE(DEBUG_CATEGORY_MEMBER_SYNC, "%s: get_items ns=%s L%d/P%016llx", MS_ID, ns, level, (unsigned long long)prefix); DEBUG_TRACE(DEBUG_CATEGORY_MEMBER_SYNC, "%s: get_items ns=%s L%d/P%016llx", MS_ID, ns, level, (unsigned long long)prefix);
char peers_tbl[128]; _peers_table(ns, peers_tbl, sizeof(peers_tbl)); char peers_tbl[128]; _peers_table(ns, peers_tbl, sizeof(peers_tbl));

Loading…
Cancel
Save