Files
progcode/web/public/assets/editorial/2020/retry-idempotency-state-contract-2020.svg
T
huncode 6c4f980f51
Build and deploy / deploy (push) Successful in 14s
revise June 2020 idempotency articles
2026-07-31 11:32:33 +03:00

68 lines
6.9 KiB
XML

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1400" role="img" aria-labelledby="title desc">
<title id="title">Контракт состояния для idempotency key</title>
<desc id="desc">Вертикальная диаграмма показывает, как сервис создаёт запись с ключом, scope и fingerprint, возвращает конфликт для другого payload или параллельного выполнения и повторяет сохранённый результат после завершения.</desc>
<rect width="720" height="1400" fill="#f8fafc"/>
<rect x="28" y="26" width="664" height="112" rx="24" fill="#172554"/>
<text x="62" y="72" fill="#f8fafc" font-family="Arial, sans-serif" font-size="32" font-weight="700">Состояние ключа на сервисе</text>
<text x="62" y="108" fill="#bfdbfe" font-family="Arial, sans-serif" font-size="20">Key + scope + fingerprint определяют одну операцию</text>
<rect x="52" y="172" width="616" height="154" rx="22" fill="#e0f2fe" stroke="#0284c7" stroke-width="3"/>
<text x="84" y="218" fill="#0c4a6e" font-family="Arial, sans-serif" font-size="27" font-weight="700">Входящий POST</text>
<text x="84" y="256" fill="#164e63" font-family="Arial, sans-serif" font-size="22">actor + operation + key</text>
<text x="84" y="288" fill="#164e63" font-family="Arial, sans-serif" font-size="22">payload → канонизация → fingerprint</text>
<line x1="360" y1="328" x2="360" y2="384" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<path d="M342 372 L360 396 L378 372" fill="none" stroke="#64748b" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="52" y="402" width="616" height="162" rx="22" fill="#eff6ff" stroke="#2563eb" stroke-width="3"/>
<text x="84" y="449" fill="#1e3a8a" font-family="Arial, sans-serif" font-size="27" font-weight="700">Атомарный захват записи</text>
<text x="84" y="486" fill="#1e3a8a" font-family="Arial, sans-serif" font-size="22">UNIQUE(scope, key) защищает конкуренцию</text>
<rect x="84" y="506" width="330" height="37" rx="12" fill="#dbeafe"/>
<text x="102" y="532" fill="#1d4ed8" font-family="Arial, sans-serif" font-size="20" font-weight="700">state = in_progress</text>
<line x1="206" y1="566" x2="206" y2="622" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<path d="M188 610 L206 634 L224 610" fill="none" stroke="#64748b" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="514" y1="566" x2="514" y2="622" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<path d="M496 610 L514 634 L532 610" fill="none" stroke="#64748b" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="52" y="642" width="308" height="172" rx="22" fill="#ecfdf5" stroke="#059669" stroke-width="3"/>
<text x="82" y="689" fill="#065f46" font-family="Arial, sans-serif" font-size="26" font-weight="700">Новый key</text>
<text x="82" y="725" fill="#065f46" font-family="Arial, sans-serif" font-size="21">Один владелец</text>
<text x="82" y="754" fill="#065f46" font-family="Arial, sans-serif" font-size="21">выполняет effect</text>
<text x="82" y="783" fill="#065f46" font-family="Arial, sans-serif" font-size="21">и сохраняет result</text>
<rect x="360" y="642" width="308" height="172" rx="22" fill="#fff7ed" stroke="#ea580c" stroke-width="3"/>
<text x="390" y="689" fill="#9a3412" font-family="Arial, sans-serif" font-size="26" font-weight="700">Запись есть</text>
<text x="390" y="725" fill="#9a3412" font-family="Arial, sans-serif" font-size="21">Сравнить hash</text>
<text x="390" y="754" fill="#9a3412" font-family="Arial, sans-serif" font-size="21">до обработчика</text>
<text x="390" y="783" fill="#9a3412" font-family="Arial, sans-serif" font-size="21">и второго effect</text>
<line x1="206" y1="816" x2="206" y2="872" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<path d="M188 860 L206 884 L224 860" fill="none" stroke="#64748b" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="514" y1="816" x2="514" y2="872" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<path d="M496 860 L514 884 L532 860" fill="none" stroke="#64748b" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="52" y="892" width="308" height="190" rx="22" fill="#f0fdf4" stroke="#16a34a" stroke-width="3"/>
<text x="82" y="939" fill="#166534" font-family="Arial, sans-serif" font-size="26" font-weight="700">completed</text>
<text x="82" y="976" fill="#166534" font-family="Arial, sans-serif" font-size="21">status + body + result ID</text>
<text x="82" y="1007" fill="#166534" font-family="Arial, sans-serif" font-size="21">повтору: replay</text>
<text x="82" y="1038" fill="#166534" font-family="Arial, sans-serif" font-size="21">без нового effect</text>
<rect x="360" y="892" width="308" height="190" rx="22" fill="#fef2f2" stroke="#dc2626" stroke-width="3"/>
<text x="390" y="939" fill="#991b1b" font-family="Arial, sans-serif" font-size="26" font-weight="700">conflict</text>
<text x="390" y="976" fill="#991b1b" font-family="Arial, sans-serif" font-size="21">другая hash</text>
<text x="390" y="1007" fill="#991b1b" font-family="Arial, sans-serif" font-size="21">или in_progress</text>
<text x="390" y="1038" fill="#991b1b" font-family="Arial, sans-serif" font-size="21">не запускает handler</text>
<rect x="52" y="1130" width="616" height="172" rx="22" fill="#f5f3ff" stroke="#7c3aed" stroke-width="3"/>
<text x="84" y="1178" fill="#4c1d95" font-family="Arial, sans-serif" font-size="27" font-weight="700">Граница, которую нельзя скрыть</text>
<text x="84" y="1214" fill="#4c1d95" font-family="Arial, sans-serif" font-size="20">Локальная запись не делает внешний вызов атомарным.</text>
<text x="84" y="1240" fill="#4c1d95" font-family="Arial, sans-serif" font-size="20">Внешний effect требует своего key или status route.</text>
<text x="84" y="1266" fill="#4c1d95" font-family="Arial, sans-serif" font-size="20">TTL дольше retry-budget: поздний retry иначе</text>
<text x="84" y="1292" fill="#4c1d95" font-family="Arial, sans-serif" font-size="20">станет новым действием.</text>
<rect x="52" y="1322" width="616" height="56" rx="14" fill="#dbeafe"/>
<text x="360" y="1346" text-anchor="middle" fill="#1e3a8a" font-family="Arial, sans-serif" font-size="20" font-weight="700">Резервируем intent → выполняем effect</text>
<text x="360" y="1370" text-anchor="middle" fill="#1e3a8a" font-family="Arial, sans-serif" font-size="20" font-weight="700">→ сохраняем terminal ответ</text>
</svg>