This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="1280" viewBox="0 0 720 1280" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Контролируемая компенсация между owner и consumer</title>
|
||||
<desc id="desc">Вертикальная схема отделяет отказ учебного резерва, проверку owner-а, запись компенсационного ключа и новое событие отмены от обработки consumer-ом и подавления дубликата.</desc>
|
||||
<defs>
|
||||
<style>
|
||||
.bg { fill: #0b1220; }
|
||||
.frame { fill: #101c31; stroke: #2e4264; stroke-width: 3; }
|
||||
.owner { fill: #153a5b; stroke: #55b6e6; stroke-width: 3; }
|
||||
.check { fill: #47351a; stroke: #f6c45a; stroke-width: 3; }
|
||||
.ledger { fill: #24473f; stroke: #6bd5b5; stroke-width: 3; }
|
||||
.consumer { fill: #293950; stroke: #a8c8e7; stroke-width: 3; }
|
||||
.stop { fill: #552b35; stroke: #ff8992; stroke-width: 3; }
|
||||
.title { fill: #f5f8ff; font: 700 32px Arial, sans-serif; }
|
||||
.section { fill: #ffffff; font: 700 26px Arial, sans-serif; }
|
||||
.copy { fill: #d9e5f5; font: 22px Arial, sans-serif; }
|
||||
.small { fill: #b8cbe0; font: 20px Arial, sans-serif; }
|
||||
.accent { fill: #8de0ff; font: 700 22px Arial, sans-serif; }
|
||||
.green { fill: #93e6cb; font: 700 22px Arial, sans-serif; }
|
||||
.arrow { fill: none; stroke: #8de0ff; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; marker-end: url(#arrowhead); }
|
||||
</style>
|
||||
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#8de0ff"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect class="bg" width="720" height="1280" rx="32"/>
|
||||
<rect class="frame" x="34" y="30" width="652" height="104" rx="22"/>
|
||||
<text class="title" x="62" y="73">Компенсация — новое решение owner-а</text>
|
||||
<text class="copy" x="62" y="108">Не откат распределённой операции задним числом</text>
|
||||
|
||||
<rect class="owner" x="68" y="174" width="584" height="122" rx="20"/>
|
||||
<text class="section" x="96" y="218">1. Owner: paid · version 2</text>
|
||||
<text class="copy" x="96" y="255">Исходное решение и объект известны</text>
|
||||
<path class="arrow" d="M360 296 L360 334"/>
|
||||
|
||||
<rect class="check" x="68" y="344" width="584" height="142" rx="20"/>
|
||||
<text class="section" x="96" y="388">2. Вход для компенсации</text>
|
||||
<text class="copy" x="96" y="425">reason, order id и version проверены</text>
|
||||
<text class="small" x="96" y="456">unknown timeout → не автоматическая отмена</text>
|
||||
<path class="arrow" d="M360 486 L360 524"/>
|
||||
|
||||
<rect class="ledger" x="68" y="534" width="584" height="162" rx="20"/>
|
||||
<text class="section" x="96" y="578">3. Локальный compensation ledger</text>
|
||||
<text class="green" x="96" y="615">key: order-417 / reservation / v2</text>
|
||||
<text class="copy" x="96" y="646">тот же вход второй раз → already-recorded</text>
|
||||
<text class="small" x="96" y="675">одна локальная граница, не две базы сразу</text>
|
||||
<path class="arrow" d="M360 696 L360 734"/>
|
||||
|
||||
<rect class="owner" x="68" y="744" width="584" height="142" rx="20"/>
|
||||
<text class="section" x="96" y="788">4. Owner создаёт cancelled · v3</text>
|
||||
<text class="accent" x="96" y="825">event id + source + type + version</text>
|
||||
<text class="copy" x="96" y="856">v2 не удаляется; появляется следующий факт</text>
|
||||
<path class="arrow" d="M360 886 L360 924"/>
|
||||
|
||||
<rect class="consumer" x="68" y="934" width="584" height="164" rx="20"/>
|
||||
<text class="section" x="96" y="978">5. Consumer применяет по version</text>
|
||||
<text class="copy" x="96" y="1015">v3 до v2 → defer с expected version</text>
|
||||
<text class="copy" x="96" y="1045">v2 → apply; затем replay v3</text>
|
||||
<text class="small" x="96" y="1076">тот же event id → duplicate suppressed</text>
|
||||
<path class="arrow" d="M360 1098 L360 1136"/>
|
||||
|
||||
<rect class="stop" x="68" y="1146" width="584" height="92" rx="20"/>
|
||||
<text class="section" x="96" y="1186">6. Предел контракта</text>
|
||||
<text class="copy" x="96" y="1219">Нет version + evidence → нет следующего effect</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,79 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="1380" viewBox="0 0 720 1380" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Диагностика расхождения owner и проекции</title>
|
||||
<desc id="desc">Вертикальная диагностическая схема собирает owner version, projection version, event id и compensation key. Затем отделяет version gap, конфликт одинаковой версии и повтор события; рискованный следующий шаг заблокирован до доказательств.</desc>
|
||||
<defs>
|
||||
<style>
|
||||
.bg { fill: #0b1220; }
|
||||
.frame { fill: #101c31; stroke: #2e4264; stroke-width: 3; }
|
||||
.input { fill: #173954; stroke: #66c5f2; stroke-width: 3; }
|
||||
.evidence { fill: #294050; stroke: #a8c8e7; stroke-width: 3; }
|
||||
.decision { fill: #503b1b; stroke: #f6c45a; stroke-width: 3; }
|
||||
.action { fill: #1d473e; stroke: #72d7b7; stroke-width: 3; }
|
||||
.stop { fill: #552b35; stroke: #ff8992; stroke-width: 3; }
|
||||
.title { fill: #f5f8ff; font: 700 32px Arial, sans-serif; }
|
||||
.section { fill: #ffffff; font: 700 26px Arial, sans-serif; }
|
||||
.copy { fill: #d9e5f5; font: 22px Arial, sans-serif; }
|
||||
.small { fill: #b8cbe0; font: 20px Arial, sans-serif; }
|
||||
.accent { fill: #8de0ff; font: 700 22px Arial, sans-serif; }
|
||||
.arrow { fill: none; stroke: #8de0ff; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; marker-end: url(#arrowhead); }
|
||||
.branch { fill: none; stroke: #f6c45a; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; marker-end: url(#yellowhead); }
|
||||
</style>
|
||||
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#8de0ff"/>
|
||||
</marker>
|
||||
<marker id="yellowhead" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#f6c45a"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect class="bg" width="720" height="1380" rx="32"/>
|
||||
<rect class="frame" x="34" y="30" width="652" height="104" rx="22"/>
|
||||
<text class="title" x="62" y="73">Разные статусы одного заказа</text>
|
||||
<text class="copy" x="62" y="108">Сначала блокируем effect, затем собираем evidence</text>
|
||||
|
||||
<rect class="stop" x="68" y="174" width="584" height="100" rx="20"/>
|
||||
<text class="section" x="96" y="216">1. Не выполнять следующий effect</text>
|
||||
<text class="copy" x="96" y="249">отгрузка, доступ или повторный reserve — paused</text>
|
||||
<path class="arrow" d="M360 274 L360 312"/>
|
||||
|
||||
<rect class="evidence" x="68" y="322" width="584" height="188" rx="20"/>
|
||||
<text class="section" x="96" y="366">2. Собрать evidence packet</text>
|
||||
<text class="copy" x="96" y="403">owner state + version</text>
|
||||
<text class="copy" x="96" y="434">projection state + version</text>
|
||||
<text class="copy" x="96" y="465">source + event id + compensation key</text>
|
||||
<text class="small" x="96" y="494">один object id, один момент наблюдения</text>
|
||||
<path class="arrow" d="M360 510 L360 548"/>
|
||||
|
||||
<rect class="decision" x="68" y="558" width="584" height="122" rx="20"/>
|
||||
<text class="section" x="96" y="602">3. Сравнить version</text>
|
||||
<text class="accent" x="96" y="639">owner > projection, равно или event duplicate?</text>
|
||||
|
||||
<path class="branch" d="M236 680 L136 730 L136 762"/>
|
||||
<path class="branch" d="M484 680 L584 730 L584 762"/>
|
||||
<text class="small" x="82" y="724">gap</text>
|
||||
<text class="small" x="548" y="724">same</text>
|
||||
|
||||
<rect class="action" x="44" y="772" width="296" height="176" rx="20"/>
|
||||
<text class="section" x="72" y="816">4a. Version gap</text>
|
||||
<text class="copy" x="72" y="853">найти missing event</text>
|
||||
<text class="copy" x="72" y="883">или deferred record</text>
|
||||
<text class="small" x="72" y="916">replay только по contract</text>
|
||||
|
||||
<rect class="input" x="380" y="772" width="296" height="176" rx="20"/>
|
||||
<text class="section" x="408" y="816">4b. Version same</text>
|
||||
<text class="copy" x="408" y="853">сверить transform rule</text>
|
||||
<text class="copy" x="408" y="883">event ledger и effect</text>
|
||||
<text class="small" x="408" y="916">не стирать ledger вслепую</text>
|
||||
|
||||
<path class="arrow" d="M192 948 L192 1000 L360 1000 L360 1038"/>
|
||||
<path class="arrow" d="M528 948 L528 1000 L360 1000"/>
|
||||
|
||||
<rect class="evidence" x="68" y="1048" width="584" height="150" rx="20"/>
|
||||
<text class="section" x="96" y="1092">5. Проверить компенсацию</text>
|
||||
<text class="copy" x="96" y="1129">reason + исходная version + один key</text>
|
||||
<text class="small" x="96" y="1160">key не доказывает внешний effect</text>
|
||||
<path class="arrow" d="M360 1198 L360 1236"/>
|
||||
|
||||
<rect class="action" x="68" y="1246" width="584" height="96" rx="20"/>
|
||||
<text class="section" x="96" y="1286">6. Выбрать контролируемое действие</text>
|
||||
<text class="copy" x="96" y="1319">replay, correction с журналом или manual decision</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -0,0 +1,65 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="1260" viewBox="0 0 720 1260" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Порядок состояний owner и fulfillment проекции</title>
|
||||
<desc id="desc">Вертикальная схема показывает owner заказа paid версии 2, контролируемую компенсацию cancelled версии 3, отложенное событие версии 3 в fulfillment, применение версии 2 и replay версии 3. Отгрузка остаётся заблокированной.</desc>
|
||||
<defs>
|
||||
<style>
|
||||
.bg { fill: #0b1220; }
|
||||
.frame { fill: #101c31; stroke: #2e4264; stroke-width: 3; }
|
||||
.owner { fill: #153a5b; stroke: #55b6e6; stroke-width: 3; }
|
||||
.consumer { fill: #20394f; stroke: #9cc4e4; stroke-width: 3; }
|
||||
.warn { fill: #52331c; stroke: #f6b850; stroke-width: 3; }
|
||||
.stop { fill: #552b35; stroke: #ff8992; stroke-width: 3; }
|
||||
.ok { fill: #19443d; stroke: #6bd5b5; stroke-width: 3; }
|
||||
.title { fill: #f5f8ff; font: 700 32px Arial, sans-serif; }
|
||||
.section { fill: #ffffff; font: 700 26px Arial, sans-serif; }
|
||||
.copy { fill: #d9e5f5; font: 22px Arial, sans-serif; }
|
||||
.small { fill: #b8cbe0; font: 20px Arial, sans-serif; }
|
||||
.accent { fill: #8de0ff; font: 700 22px Arial, sans-serif; }
|
||||
.arrow { fill: none; stroke: #8de0ff; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; marker-end: url(#arrowhead); }
|
||||
.muted { fill: none; stroke: #f6b850; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; marker-end: url(#arrowhead); }
|
||||
</style>
|
||||
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#8de0ff"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect class="bg" width="720" height="1260" rx="32"/>
|
||||
<rect class="frame" x="34" y="30" width="652" height="104" rx="22"/>
|
||||
<text class="title" x="62" y="73">Один owner, две версии проекции</text>
|
||||
<text class="copy" x="62" y="108">Расхождение видно до следующего действия</text>
|
||||
|
||||
<rect class="owner" x="68" y="174" width="584" height="142" rx="20"/>
|
||||
<text class="section" x="96" y="218">1. order-service — owner</text>
|
||||
<text class="accent" x="96" y="255">order-417: paid · version 2</text>
|
||||
<text class="copy" x="96" y="286">Только owner принимает новое доменное решение</text>
|
||||
<path class="arrow" d="M360 316 L360 358"/>
|
||||
|
||||
<rect class="warn" x="68" y="368" width="584" height="142" rx="20"/>
|
||||
<text class="section" x="96" y="412">2. Проверенный учебный отказ</text>
|
||||
<text class="copy" x="96" y="449">reason + order version совпадают</text>
|
||||
<text class="small" x="96" y="480">unknown timeout не становится компенсацией сам</text>
|
||||
<path class="muted" d="M360 510 L360 552"/>
|
||||
|
||||
<rect class="owner" x="68" y="562" width="584" height="164" rx="20"/>
|
||||
<text class="section" x="96" y="606">3. Новое решение owner-а</text>
|
||||
<text class="accent" x="96" y="643">compensation key → cancelled · version 3</text>
|
||||
<text class="copy" x="96" y="678">v2 остаётся фактом истории, а не стирается</text>
|
||||
<text class="small" x="96" y="706">Создан event: order.cancelled v3</text>
|
||||
<path class="arrow" d="M360 726 L360 768"/>
|
||||
|
||||
<rect class="consumer" x="68" y="778" width="584" height="156" rx="20"/>
|
||||
<text class="section" x="96" y="822">4. fulfillment получает v3 первой</text>
|
||||
<text class="copy" x="96" y="859">current v1, expected v2 → defer version gap</text>
|
||||
<text class="small" x="96" y="890">projection не меняется, evidence сохранён</text>
|
||||
<text class="small" x="96" y="918">v3 ждёт, а не применяется поверх v1</text>
|
||||
<path class="arrow" d="M360 934 L360 976"/>
|
||||
|
||||
<rect class="ok" x="68" y="986" width="584" height="164" rx="20"/>
|
||||
<text class="section" x="96" y="1030">5. Приходит v2, затем replay v3</text>
|
||||
<text class="copy" x="96" y="1067">accepted v1 → awaiting-reservation v2</text>
|
||||
<text class="copy" x="96" y="1097">→ cancelled v3; duplicate не меняет projection</text>
|
||||
<text class="accent" x="96" y="1128">readyToShip = false</text>
|
||||
<path class="arrow" d="M360 1150 L360 1182"/>
|
||||
|
||||
<rect class="stop" x="68" y="1190" width="584" height="46" rx="16"/>
|
||||
<text class="section" x="156" y="1222" style="font-size:23px">Рискованный шаг заблокирован</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
Reference in New Issue
Block a user