[MOD] Move temporary stanza/event mappings

This should increase reliability, as a bad write shouldn't affect the
MUC mappings directoy (which I've _seen_ happen.)
This commit is contained in:
LDA 2024-08-02 14:11:23 +02:00
commit 3c5b9aac82
3 changed files with 60 additions and 120 deletions

View file

@ -370,15 +370,17 @@ ParseeEventHandler(ParseeData *data, HashMap *event)
{ {
char *event_type, *event_id, *room_id, *sender; char *event_type, *event_id, *room_id, *sender;
char *parsee = ParseeMXID(data); char *parsee = ParseeMXID(data);
if (!data || !event)
event_id = GrabString(event, 1, "event_id");
event_type = GrabString(event, 1, "type");
room_id = GrabString(event, 1, "room_id");
sender = GrabString(event, 1, "sender");
if (!data || !event || ParseeIsPuppet(data->config, sender))
{ {
Free(parsee);
return; return;
} }
event_type = GrabString(event, 1, "type");
event_id = GrabString(event, 1, "event_id");
room_id = GrabString(event, 1, "room_id");
sender = GrabString(event, 1, "sender");
ParseePushHeadTable(room_id, event_id); ParseePushHeadTable(room_id, event_id);
if (StrEquals(event_type, "m.room.member")) if (StrEquals(event_type, "m.room.member"))

View file

@ -68,45 +68,46 @@ ParseeCleanup(void *datp)
uint64_t ts = UtilTsMillis(); uint64_t ts = UtilTsMillis();
Log(LOG_NOTICE, "Cleaning up..."); Log(LOG_NOTICE, "Cleaning up...");
chats = DbList(data->db, 1, "chats"); chats = DbList(data->db, 1, "chats");
for (i = 0; i < ArraySize(chats); i++) for (i = 0; i < ArraySize(chats); i++)
{ {
DbRef *ref; DbRef *ref;
HashMap *json, *stanzas, *events, *ids;
char *stanza, *event, *id; char *stanza, *event, *id;
JsonValue *val;
Array *to_delete; Array *to_delete;
size_t j; size_t j;
chat = ArrayGet(chats, i); chat = ArrayGet(chats, i);
ref = DbLock(data->db, 2, "chats", chat);
json = DbJson(ref);
#define CleanupField(field, timeout, threshold) do \ #define CleanupField(field, timeout, threshold) do \
{ \ { \
Array *field##_list = DbList(data->db, 3, "chats", chat, #field"s"); \
size_t cleaned = 0; \ size_t cleaned = 0; \
field##s = JsonValueAsObject(HashMapGet(json, #field"s")); \
to_delete = ArrayCreate(); \ to_delete = ArrayCreate(); \
while (HashMapIterate(field##s, &field, (void **) &val)) \ for (j = 0; j < ArraySize(field##_list); j++) \
{ \ { \
HashMap *obj = JsonValueAsObject(val); \ char *f = ArrayGet(field##_list, j); \
ref = DbLock(data->db, 4, "chats", chat, #field"s", f); \
HashMap *obj = DbJson(ref); \
uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age")); \ uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age")); \
uint64_t dur = ts - age; \ uint64_t dur = ts - age; \
\ \
if ((dur > (timeout))) \ if ((dur > (timeout))) \
{ \ { \
ArrayAdd(to_delete, StrDuplicate(field)); \ ArrayAdd(to_delete, StrDuplicate(f)); \
cleaned++; \ cleaned++; \
} \ } \
DbUnlock(data->db, ref); \
} \ } \
DbListFree(field##_list); \
\ \
for (j = 0; j < ArraySize(to_delete); j++) \ for (j = 0; j < ArraySize(to_delete); j++) \
{ \ { \
field = ArrayGet(to_delete, j); \ field = ArrayGet(to_delete, j); \
if (cleaned > threshold) \ if (cleaned > threshold) \
{ \ { \
JsonValueFree(HashMapDelete(field##s, field)); \ DbDelete(data->db, 4, "chats", chat, #field"s", field); \
} \ } \
Free(field); \ Free(field); \
} \ } \
@ -117,8 +118,7 @@ ParseeCleanup(void *datp)
CleanupField(stanza, 30 MINUTES, 50); CleanupField(stanza, 30 MINUTES, 50);
CleanupField(event, 30 MINUTES, 50); CleanupField(event, 30 MINUTES, 50);
CleanupField(id, 30 MINUTES, 50); CleanupField(id, 30 MINUTES, 50);
#undef CleanupField
DbUnlock(data->db, ref);
} }
DbListFree(chats); DbListFree(chats);
/* TODO */ /* TODO */
@ -499,76 +499,56 @@ ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id, char *id, cha
{ {
DbRef *ref; DbRef *ref;
HashMap *j; HashMap *j;
HashMap *stanzas, *obj, *events, *ids;
bool new_stanzas = false, new_events = false;
bool new_ids = false;
uint64_t age = UtilTsMillis(); uint64_t age = UtilTsMillis();
if (!data || !chat_id || !stanza_id || !ev || !sender) if (!data || !chat_id || !stanza_id || !ev || !sender)
{ {
return; return;
} }
ref = DbLock(data->db, 2, "chats", chat_id); /* TODO */
{
ref = DbCreate(data->db, 4, "chats", chat_id, "stanzas", stanza_id);
j = DbJson(ref); j = DbJson(ref);
if (!ref) if (!ref)
{ {
return; return;
} }
stanzas = JsonValueAsObject(HashMapGet(j, "stanzas")); HashMapSet(j, "age", JsonValueInteger(age));
if (!stanzas) HashMapSet(j, "event", JsonValueString(ev));
{ DbUnlock(data->db, ref);
stanzas = HashMapCreate();
new_stanzas = true;
} }
obj = HashMapCreate();
HashMapSet(obj, "age", JsonValueInteger(age));
HashMapSet(obj, "event", JsonValueString(ev));
JsonValueFree(HashMapSet(stanzas, stanza_id, JsonValueObject(obj)));
if (new_stanzas)
{ {
HashMapSet(j, "stanzas", JsonValueObject(stanzas)); ref = DbCreate(data->db, 4, "chats", chat_id, "events", ev);
j = DbJson(ref);
if (!ref)
{
return;
} }
events = JsonValueAsObject(HashMapGet(j, "events")); HashMapSet(j, "event", JsonValueString(ev));
if (!events) HashMapSet(j, "stanza", JsonValueString(stanza_id));
{ HashMapSet(j, "origin", JsonValueString(id));
events = HashMapCreate(); HashMapSet(j, "sender", JsonValueString(sender));
new_events = true; HashMapSet(j, "age", JsonValueInteger(age));
} DbUnlock(data->db, ref);
obj = HashMapCreate();
HashMapSet(obj, "stanza", JsonValueString(stanza_id));
HashMapSet(obj, "origin", JsonValueString(id));
HashMapSet(obj, "sender", JsonValueString(sender));
HashMapSet(obj, "age", JsonValueInteger(age));
JsonValueFree(HashMapSet(events, ev, JsonValueObject(obj)));
if (new_events)
{
HashMapSet(j, "events", JsonValueObject(events));
} }
if (id) if (id)
{ {
ids = JsonValueAsObject(HashMapGet(j, "ids")); ref = DbCreate(data->db, 4, "chats", chat_id, "ids", id);
if (!ids) j = DbJson(ref);
if (!ref)
{ {
ids = HashMapCreate(); return;
new_ids = true;
}
obj = HashMapCreate();
HashMapSet(obj, "stanza", JsonValueString(stanza_id));
HashMapSet(obj, "event", JsonValueString(ev));
HashMapSet(obj, "sender", JsonValueString(sender));
HashMapSet(obj, "age", JsonValueInteger(age));
JsonValueFree(HashMapSet(ids, id, JsonValueObject(obj)));
if (new_ids)
{
HashMapSet(j, "ids", JsonValueObject(ids));
}
} }
HashMapSet(j, "stanza", JsonValueString(stanza_id));
HashMapSet(j, "event", JsonValueString(ev));
HashMapSet(j, "sender", JsonValueString(sender));
HashMapSet(j, "age", JsonValueInteger(age));
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
}
} }
bool bool
@ -605,29 +585,15 @@ bool
ParseeVerifyStanza(ParseeData *data, char *chat_id, char *stanza_id) ParseeVerifyStanza(ParseeData *data, char *chat_id, char *stanza_id)
{ {
DbRef *ref = NULL; DbRef *ref = NULL;
HashMap *j = NULL;
HashMap *stanzas = NULL;
bool ret = true; bool ret = true;
if (!data || !chat_id || !stanza_id) if (!data || !chat_id || !stanza_id)
{ {
return true; return true;
} }
ref = DbLock(data->db, 2, "chats", chat_id); ref = DbLock(data->db, 4, "chats", chat_id, "stanzas", stanza_id);
j = DbJson(ref); ret = !ref;
if (!ref)
{
goto end;
}
stanzas = JsonValueAsObject(HashMapGet(j, "stanzas"));
if (!stanzas)
{
goto end;
}
ret = !HashMapGet(stanzas, stanza_id);
end:
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
return ret; return ret;
} }
@ -636,27 +602,20 @@ ParseeEventFromID(ParseeData *data, char *chat_id, char *id)
{ {
DbRef *ref = NULL; DbRef *ref = NULL;
HashMap *j = NULL; HashMap *j = NULL;
HashMap *ids = NULL;
char *ret = NULL; char *ret = NULL;
if (!data || !chat_id || !id) if (!data || !chat_id || !id)
{ {
return NULL; return NULL;
} }
ref = DbLock(data->db, 2, "chats", chat_id); ref = DbLock(data->db, 4, "chats", chat_id, "ids", id);
j = DbJson(ref); j = DbJson(ref);
if (!ref) if (!ref)
{ {
goto end; goto end;
} }
ids = JsonValueAsObject(HashMapGet(j, "ids")); ret = JsonValueAsString(JsonGet(j, 1, "event"));
if (!ids)
{
goto end;
}
ret = JsonValueAsString(JsonGet(ids, 2, id, "event"));
ret = StrDuplicate(ret); ret = StrDuplicate(ret);
end: end:
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
@ -699,27 +658,20 @@ ParseeEventFromSID(ParseeData *data, char *chat_id, char *id)
{ {
DbRef *ref = NULL; DbRef *ref = NULL;
HashMap *j = NULL; HashMap *j = NULL;
HashMap *ids = NULL;
char *ret = NULL; char *ret = NULL;
if (!data || !chat_id || !id) if (!data || !chat_id || !id)
{ {
return NULL; return NULL;
} }
ref = DbLock(data->db, 2, "chats", chat_id); ref = DbLock(data->db, 4, "chats", chat_id, "stanzas", id);
j = DbJson(ref); j = DbJson(ref);
if (!ref) if (!ref)
{ {
goto end; goto end;
} }
ids = JsonValueAsObject(HashMapGet(j, "stanzas")); ret = JsonValueAsString(JsonGet(j, 1, "event"));
if (!ids)
{
goto end;
}
ret = JsonValueAsString(JsonGet(ids, 2, id, "event"));
ret = StrDuplicate(ret); ret = StrDuplicate(ret);
end: end:
DbUnlock(data->db, ref); DbUnlock(data->db, ref);

View file

@ -583,28 +583,21 @@ ParseeGetStanzaInfo(ParseeData *data, char *chat_id, char *ev, char **st, char *
{ {
DbRef *ref = NULL; DbRef *ref = NULL;
HashMap *j = NULL; HashMap *j = NULL;
HashMap *event = NULL;
bool ret = false; bool ret = false;
if (!data || !chat_id || !ev || !st || !se) if (!data || !chat_id || !ev || !st || !se)
{ {
return false; return false;
} }
ref = DbLock(data->db, 2, "chats", chat_id); ref = DbLock(data->db, 4, "chats", chat_id, "events", ev);
j = DbJson(ref); j = DbJson(ref);
if (!ref) if (!ref)
{ {
goto end; goto end;
} }
*st = StrDuplicate(JsonValueAsString(HashMapGet(j, "stanza")));
event = JsonValueAsObject(JsonGet(j, 2, "events", ev)); *se = StrDuplicate(JsonValueAsString(HashMapGet(j, "sender")));
if (!event)
{
goto end;
}
*st = StrDuplicate(JsonValueAsString(HashMapGet(event, "stanza")));
*se = StrDuplicate(JsonValueAsString(HashMapGet(event, "sender")));
ret = true; ret = true;
end: end:
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
@ -647,27 +640,20 @@ ParseeGetOrigin(ParseeData *data, char *chat_id, char *ev, char **o)
{ {
DbRef *ref = NULL; DbRef *ref = NULL;
HashMap *j = NULL; HashMap *j = NULL;
HashMap *event = NULL;
bool ret = false; bool ret = false;
if (!data || !chat_id || !ev || !o) if (!data || !chat_id || !ev || !o)
{ {
return false; return false;
} }
ref = DbLock(data->db, 2, "chats", chat_id); ref = DbLock(data->db, 4, "chats", chat_id, "events", ev);
j = DbJson(ref); j = DbJson(ref);
if (!ref) if (!ref)
{ {
goto end; goto end;
} }
*o = StrDuplicate(JsonValueAsString(HashMapGet(j, "origin")));
event = JsonValueAsObject(JsonGet(j, 2, "events", ev));
if (!event)
{
goto end;
}
*o = StrDuplicate(JsonValueAsString(HashMapGet(event, "origin")));
ret = true; ret = true;
end: end:
DbUnlock(data->db, ref); DbUnlock(data->db, ref);