Preserve input cursor when member page outputs alias it
This commit is contained in:
1 parent
49dc837df2
commit
864a250eea
2 files changed
+48
-1
No files matched your search
@@ -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
|
||||
@@ -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;
|
||||
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;
|
||||
memset(next, 0, sizeof(*next)); *more = 0;
|
||||
uint64_t after_id = member_read64(after->bytes);
|
||||
static const uint8_t zero_tail[MT_KEY_SIZE - 8];
|
||||
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;
|
||||
}
|
||||
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);
|
||||
char peers_tbl[128]; _peers_table(ns, peers_tbl, sizeof(peers_tbl));
|
||||
|
||||
|
||||
Reference in new issue
Block a user