W ramach technicznej analizy problemu przedstawiam poniżej mój punkt widzenia, dlaczego data stworzenia postu powinna być decydująca.
Opierając się na logice kompetytywności rajdu, decydującym czynnikiem na sukces lub porażkę rajdowca powinno być akcja użytkownika. Z oczywistych względów nie jest możliwy pomiar czasu kliknięcia użytkownika, wobec czego decydującym winien być najwcześniejszy moment rejestracji akcji użytkownika.
Istotna część kodu poniżej:
src/posts/create.js L16-38
// This is an internal method, consider using Topics.reply instead
const uid = data.uid;
const tid = data.tid;
const content = data.content.toString();
const timestamp = data.timestamp || Date.now();
const isMain = data.isMain || false;
if (!uid && parseInt(uid, 10) !== 0) {
throw new Error('[[error:invalid-uid]]');
}
if (data.toPid && !utils.isNumber(data.toPid)) {
throw new Error('[[error:invalid-pid]]');
}
const pid = await db.incrObjectField('global', 'nextPid');
let postData = {
pid: pid,
uid: uid,
tid: tid,
content: content,
timestamp: timestamp,
};
To jest kod odpowiedzialny za utworzenie postu przy odpowiedzi na utworzony temat.
W linii const timestamp = data.timestamp || Date.now();
tworzony jest timestamp, o ile nie istniał wcześniej (sytuacje inne niż tworzenie nowego posta).
Następnie w liniach
if (!uid && parseInt(uid, 10) !== 0) {
throw new Error('[[error:invalid-uid]]');
}
oraz
if (data.toPid && !utils.isNumber(data.toPid)) {
throw new Error('[[error:invalid-pid]]');
}
Przeprowadzone są walidacje kolejno ID użytkownika oraz ID rodzica.
W kolejnej linii const pid = await db.incrObjectField('global', 'nextPid');
tworzony jest ID postu, poprzez pobranie globalnego licznika ID postów.
Jako że wszystko wykonuje się asynchronicznie, zdarzenia mogą być dowolnie przeplatane przez silnik JavaScriptu. Ponadto dostęp do bazy danych w kontekście globalnego licznika ID postów może być dowolnie obsłużone przez serwer bazy danych.
Wobec powyższego ustawienie znacznika czasowego posta oraz ID posta nie jest transakcyjne i mogą dowolnie się przeplatać, zaś znacznik czasowy posta jest w każdym przypadku wyznaczany pierwszy.
Z uwagi na powyższe moją rekomendacją, przy rzadkiej sytuacji gdzie id posta A jest wcześniejsza niż id posta B, zaś znacznik czasowy posta B jest wcześniejszy niż znacznik czasowy posta A, uwzględnić post B jako wygrywający, jako że posiada wcześniejszy znacznik czasowy.
Analizowany kod dostępny jest na licencji otwartoźródłowej: https://github.com/NodeBB/NodeBB
Commit użyty do analizy: e8ca993aac4b90cfea131050814a19e144a27094