store: при равной полноте точек побеждает пришедшая доставка
- байтовый порядок канонических форм остался тай-брейком только внутри одной доставки: на живом корпусе он решал 98,8% спорных координат и системно хранил меньшее значение, из-за чего step_count терял род и verify:archive был красным - правило перестало быть коммутативным осознанно, поэтому порядок свёртки приведён к журнальному: проход воркера прекращается на отложенной доставке, а свёртка вне порядка журнала пишет WARN - заведены счётчики PointsHeld и PointsErased — удержание полнотой и единственное направление, в котором правило теряет содержание
This commit is contained in:
+19
-15
@@ -197,12 +197,16 @@ func (v *entityVersion) sortKey() []byte {
|
||||
// 3. содержание равно → версия из более поздней доставки ЖУРНАЛА
|
||||
// 4. наборы несравнимы → сохранённая
|
||||
//
|
||||
// Пункт 3 — не «побеждает приехавшая». Приехавшая есть функция порядка
|
||||
// СВЁРТКИ, а он порядку журнала не равен: воркер сворачивает в порядке журнала
|
||||
// только среди видимых ему доставок. Доставка с более ранней меткой, свёрнутая
|
||||
// позже, вернула бы витрину к недосчитанной версии, и пересборка разошлась бы
|
||||
// с живым приёмом молча — в содержимом тренировки, где это не видно ничем,
|
||||
// кроме отпечатка.
|
||||
// Пункт 3 — не «побеждает приехавшая», и различие здесь в СИЛЕ гарантии, а не
|
||||
// в намерении. Порядок свёртки приведён к порядку журнала (барьер на
|
||||
// отложенной доставке в replay.Worker), но равенство неполное: строка учёта
|
||||
// становится видимой только после записи тела, и при конкурентном приёме
|
||||
// доставка с более ранней меткой сворачивается позже. Хранимая позиция журнала
|
||||
// это окно закрывает целиком, происхождение кандидата — нет. У точек колонки
|
||||
// провенанса нет и заводить её дорого, поэтому там взято происхождение вместе
|
||||
// с обеспеченным порядком; здесь колонка есть, и терять из-за неё гарантию
|
||||
// незачем. Критерий выбора записан в architecture.md, «Разрешение
|
||||
// столкновений».
|
||||
//
|
||||
// Равные позиции означают две версии одного ключа внутри ОДНОЙ доставки; там
|
||||
// решает минимум канонической формы, потому что порядок элементов в
|
||||
@@ -220,15 +224,15 @@ func pickEntity(stored, incoming *entityVersion) (takeIncoming, lost bool) {
|
||||
// версий остаётся сохранённая: правило называется «не теряет
|
||||
// содержания», и приехавшая его теряет.
|
||||
//
|
||||
// ЗДЕСЬ И ТОЛЬКО ЗДЕСЬ исход зависит от порядка свёртки, а не от
|
||||
// журнала: в витрине лежит победитель прошлых слияний, а не все
|
||||
// кандидаты истории, и «сохранённая выигрывает» означает разный итог
|
||||
// при разном порядке. Порядок свёртки журналу не равен — доставка,
|
||||
// получившая ErrBusy, остаётся `pending` и сворачивается следующим
|
||||
// проходом, — так что живой приём и пересборка на несравнимых версиях
|
||||
// законно расходятся. Это единственная точка, где витрина не является
|
||||
// функцией множества доставок; она названа вслух в architecture.md, и
|
||||
// счётчик удержаний ниже — единственное, что о ней сообщает.
|
||||
// Исход здесь зависит от порядка свёртки, а не от журнала: в витрине
|
||||
// лежит победитель прошлых слияний, а не все кандидаты истории, и
|
||||
// «сохранённая выигрывает» означает разный итог при разном порядке.
|
||||
// Окно этого расхождения СУЖЕНО: доставка, получившая ErrBusy, больше
|
||||
// не перегоняется своими преемницами — проход воркера прекращается на
|
||||
// ней. Осталось окно конкурентного приёма, где строка учёта становится
|
||||
// видимой позже метки; там живой приём и пересборка на несравнимых
|
||||
// версиях законно расходятся, и воркер об этом пишет WARN. Счётчик
|
||||
// удержаний ниже — второе, что о расхождении сообщает.
|
||||
return false, true
|
||||
default:
|
||||
return laterInJournal(stored, incoming), false
|
||||
|
||||
Reference in New Issue
Block a user