feat: expand gen2D deck with deep technical slides and interactive elements
Deploy Slides / build-and-deploy (push) Successful in 1m8s
Deploy Slides / build-and-deploy (push) Successful in 1m8s
- Add 5 new slide pages: eino-deep-dive, ratelimit-overview, ratelimit-lua, async-deep-dive, harness - Add 4 new drawio SVGs: pipeline-detail, ratelimit, async-task, harness - Update all existing slides with v-clicks progressive reveal - Add presenter notes and interactive prompts - Expand slides.md to register all new pages (16 → 25+ slides) - Fix text overflow by trimming content per Item block - Add Eino Graph deep dive: WithGenLocalState, Pre/Post Handler, branch routing - Add rate limiting section: algorithm comparison, Lua script, Gin middleware - Add async task deep dive: TaskQueue FIFO, context progress injection - Add consistency section: style/pipeline/data/deployment 4-layer guarantees
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400" font-family="system-ui, sans-serif" font-size="13">
|
||||
<defs>
|
||||
<filter id="shadow" x="-2%" y="-2%" width="104%" height="104%">
|
||||
<feDropShadow dx="1" dy="2" stdDeviation="2" flood-opacity="0.3"/>
|
||||
</filter>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#60a5fa"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4ade80"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#f87171"/>
|
||||
</marker>
|
||||
<marker id="arrow-yellow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#fbbf24"/>
|
||||
</marker>
|
||||
<marker id="arrow-purple" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#c084fc"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="400" fill="#0f172a" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="400" y="30" font-size="16" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Async Task Lifecycle</text>
|
||||
|
||||
<!-- POST /generate (client request) -->
|
||||
<rect x="20" y="75" width="120" height="50" rx="6" fill="#1a1a2e" stroke="#60a5fa" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="80" y="97" font-size="12" fill="#e2e8f0" text-anchor="middle" font-weight="bold">POST</text>
|
||||
<text x="80" y="113" font-size="11" fill="#60a5fa" text-anchor="middle">/generate</text>
|
||||
|
||||
<!-- Arrow: POST → Create Task -->
|
||||
<line x1="142" y1="100" x2="178" y2="100" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- Create Task -->
|
||||
<rect x="180" y="70" width="140" height="60" rx="6" fill="#1a1a2e" stroke="#818cf8" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="250" y="95" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Create Task</text>
|
||||
<text x="250" y="112" font-size="10" fill="#fbbf24" text-anchor="middle">status = running</text>
|
||||
<text x="250" y="124" font-size="10" fill="#94a3b8" text-anchor="middle">→ DB insert</text>
|
||||
|
||||
<!-- Arrow: Create Task → Return taskId (immediate response) -->
|
||||
<path d="M 250,130 L 250,155 L 110,155 L 110,127" fill="none" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<rect x="130" y="142" width="150" height="22" rx="4" fill="#1e293b"/>
|
||||
<text x="205" y="158" font-size="10" fill="#4ade80" text-anchor="middle">return taskId immediately</text>
|
||||
|
||||
<!-- Background goroutine label -->
|
||||
<rect x="350" y="50" width="430" height="310" rx="6" fill="none" stroke="#334155" stroke-width="1" stroke-dasharray="6,3"/>
|
||||
<text x="565" y="70" font-size="12" fill="#64748b" text-anchor="middle" font-style="italic">Background: goroutine</text>
|
||||
|
||||
<!-- Arrow: Create Task → TaskQueue -->
|
||||
<line x1="322" y1="100" x2="378" y2="100" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- TaskQueue (FIFO) -->
|
||||
<rect x="380" y="70" width="130" height="60" rx="6" fill="#1a1a2e" stroke="#c084fc" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="445" y="92" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">TaskQueue</text>
|
||||
<text x="445" y="108" font-size="11" fill="#c084fc" text-anchor="middle">FIFO</text>
|
||||
<text x="445" y="122" font-size="10" fill="#94a3b8" text-anchor="middle">chan GenerateJob</text>
|
||||
|
||||
<!-- FIFO items visualization -->
|
||||
<rect x="390" y="135" width="22" height="16" rx="3" fill="#c084fc" opacity="0.7"/>
|
||||
<rect x="416" y="135" width="22" height="16" rx="3" fill="#c084fc" opacity="0.5"/>
|
||||
<rect x="442" y="135" width="22" height="16" rx="3" fill="#c084fc" opacity="0.3"/>
|
||||
<text x="482" y="148" font-size="9" fill="#94a3b8">jobs...</text>
|
||||
|
||||
<!-- Arrow: TaskQueue → Pipeline Execution -->
|
||||
<line x1="512" y1="100" x2="548" y2="100" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- Pipeline Execution -->
|
||||
<rect x="550" y="70" width="170" height="60" rx="6" fill="#1a1a2e" stroke="#818cf8" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="635" y="92" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Pipeline Execution</text>
|
||||
<text x="635" y="108" font-size="10" fill="#94a3b8" text-anchor="middle">4-stage Eino pipeline</text>
|
||||
<text x="635" y="122" font-size="10" fill="#64748b" text-anchor="middle">prompt → asset → quality → format</text>
|
||||
|
||||
<!-- Progress bar visualization -->
|
||||
<rect x="380" y="175" width="370" height="30" rx="6" fill="#1e293b" stroke="#334155" stroke-width="1"/>
|
||||
<!-- Progress segments -->
|
||||
<rect x="382" y="177" width="36" height="26" rx="4" fill="#818cf8" opacity="0.8"/>
|
||||
<text x="400" y="195" font-size="9" fill="#fff" text-anchor="middle">5%</text>
|
||||
<rect x="420" y="177" width="92" height="26" rx="4" fill="#60a5fa" opacity="0.8"/>
|
||||
<text x="466" y="195" font-size="9" fill="#fff" text-anchor="middle">25%</text>
|
||||
<rect x="514" y="177" width="100" height="26" rx="4" fill="#fbbf24" opacity="0.8"/>
|
||||
<text x="564" y="195" font-size="9" fill="#fff" text-anchor="middle">60%</text>
|
||||
<rect x="616" y="177" width="64" height="26" rx="4" fill="#4ade80" opacity="0.8"/>
|
||||
<text x="648" y="195" font-size="9" fill="#fff" text-anchor="middle">80%</text>
|
||||
<rect x="682" y="177" width="66" height="26" rx="4" fill="#34d399" opacity="0.9"/>
|
||||
<text x="715" y="195" font-size="9" fill="#fff" text-anchor="middle">100%</text>
|
||||
|
||||
<!-- Arrow: Pipeline → Update Progress -->
|
||||
<line x1="635" y1="132" x2="635" y2="173" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#arrow-yellow)"/>
|
||||
|
||||
<!-- WebSocket push label -->
|
||||
<rect x="530" y="215" width="210" height="35" rx="6" fill="#1a1a2e" stroke="#c084fc" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="635" y="230" font-size="12" fill="#c084fc" text-anchor="middle" font-weight="bold">WebSocket Push</text>
|
||||
<text x="635" y="244" font-size="10" fill="#94a3b8" text-anchor="middle">real-time progress updates</text>
|
||||
|
||||
<!-- Arrow: progress bar → WebSocket -->
|
||||
<line x1="635" y1="205" x2="635" y2="213" stroke="#c084fc" stroke-width="1.5" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Client receiving WebSocket -->
|
||||
<rect x="20" y="215" width="120" height="35" rx="6" fill="#1a1a2e" stroke="#c084fc" stroke-width="1.5" stroke-dasharray="4,3" filter="url(#shadow)"/>
|
||||
<text x="80" y="230" font-size="11" fill="#c084fc" text-anchor="middle" font-weight="bold">Client</text>
|
||||
<text x="80" y="244" font-size="9" fill="#94a3b8" text-anchor="middle">ws:// .../progress</text>
|
||||
|
||||
<!-- Arrow: WebSocket → Client (across diagram) -->
|
||||
<path d="M 530,232 L 200,232 L 142,232" fill="none" stroke="#c084fc" stroke-width="1.5" stroke-dasharray="6,3" marker-end="url(#arrow-purple)"/>
|
||||
|
||||
<!-- Completion path -->
|
||||
<!-- Arrow: Pipeline → Completion -->
|
||||
<line x1="720" y1="132" x2="720" y2="270" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- Save Assets -->
|
||||
<rect x="550" y="270" width="140" height="50" rx="6" fill="#1a1a2e" stroke="#4ade80" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="620" y="292" font-size="12" fill="#4ade80" text-anchor="middle" font-weight="bold">Save Assets</text>
|
||||
<text x="620" y="308" font-size="10" fill="#94a3b8" text-anchor="middle">→ disk / object store</text>
|
||||
|
||||
<!-- Arrow: Save Assets → Update DB -->
|
||||
<line x1="620" y1="322" x2="620" y2="348" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- Update DB -->
|
||||
<rect x="550" y="350" width="140" height="35" rx="6" fill="#1a1a2e" stroke="#4ade80" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="620" y="372" font-size="12" fill="#4ade80" text-anchor="middle" font-weight="bold">Update DB (done)</text>
|
||||
|
||||
<!-- Arrow: Update DB → status=done (notification to client) -->
|
||||
<path d="M 550,367 L 200,367 L 200,252" fill="none" stroke="#4ade80" stroke-width="1.5" stroke-dasharray="6,3" marker-end="url(#arrow-green)"/>
|
||||
<text x="370" y="360" font-size="10" fill="#4ade80" text-anchor="middle">status = done + assets</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="20" y="370" width="500" height="24" rx="6" fill="#1e293b" stroke="#334155" stroke-width="1" opacity="0"/>
|
||||
<line x1="20" y1="390" x2="50" y2="390" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="60" y="394" font-size="10" fill="#94a3b8">Sync flow</text>
|
||||
<line x1="130" y1="390" x2="160" y2="390" stroke="#c084fc" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-purple)"/>
|
||||
<text x="170" y="394" font-size="10" fill="#94a3b8">WebSocket push</text>
|
||||
<line x1="280" y1="390" x2="310" y2="390" stroke="#4ade80" stroke-width="1.5" stroke-dasharray="6,3" marker-end="url(#arrow-green)"/>
|
||||
<text x="320" y="394" font-size="10" fill="#94a3b8">Completion notify</text>
|
||||
<line x1="440" y1="390" x2="470" y2="390" stroke="#fbbf24" stroke-width="1.5" marker-end="url(#arrow-yellow)"/>
|
||||
<text x="480" y="394" font-size="10" fill="#94a3b8">Progress update</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.1 KiB |
@@ -0,0 +1,69 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 420" font-family="system-ui, sans-serif">
|
||||
<rect width="800" height="420" fill="#0f172a" rx="8"/>
|
||||
<text x="400" y="30" text-anchor="middle" fill="#e2e8f0" font-size="16" font-weight="bold">一致性保障 — 全链路设计</text>
|
||||
<!-- Layer 1 -->
|
||||
<rect x="30" y="50" width="740" height="80" fill="#1e293b" rx="6" stroke="#3b82f6" stroke-width="1.5"/>
|
||||
<text x="50" y="72" fill="#60a5fa" font-size="13" font-weight="bold">风格一致性</text>
|
||||
<rect x="50" y="82" width="140" height="36" fill="#1e3a5f" rx="4"/>
|
||||
<text x="120" y="105" text-anchor="middle" fill="#93c5fd" font-size="11">Project Style (基底)</text>
|
||||
<line x1="190" y1="100" x2="230" y2="100" stroke="#4ade80" stroke-width="2" marker-end="url(#arrowG)"/>
|
||||
<rect x="230" y="82" width="100" height="36" fill="#1e3a5f" rx="4"/>
|
||||
<text x="280" y="105" text-anchor="middle" fill="#93c5fd" font-size="11">mergeStyle()</text>
|
||||
<line x1="330" y1="100" x2="370" y2="100" stroke="#4ade80" stroke-width="2" marker-end="url(#arrowG)"/>
|
||||
<rect x="370" y="82" width="140" height="36" fill="#1e3a5f" rx="4"/>
|
||||
<text x="440" y="105" text-anchor="middle" fill="#93c5fd" font-size="11">Task Override (覆盖)</text>
|
||||
<line x1="510" y1="100" x2="550" y2="100" stroke="#4ade80" stroke-width="2" marker-end="url(#arrowG)"/>
|
||||
<rect x="550" y="82" width="200" height="36" fill="#166534" rx="4"/>
|
||||
<text x="650" y="105" text-anchor="middle" fill="#4ade80" font-size="11">Final Style (统一风格输出)</text>
|
||||
<!-- Layer 2 -->
|
||||
<rect x="30" y="140" width="740" height="80" fill="#1e293b" rx="6" stroke="#a78bfa" stroke-width="1.5"/>
|
||||
<text x="50" y="162" fill="#a78bfa" font-size="13" font-weight="bold">管线一致性</text>
|
||||
<rect x="50" y="172" width="110" height="36" fill="#2e1065" rx="4"/>
|
||||
<text x="105" y="195" text-anchor="middle" fill="#c4b5fd" font-size="11">Graph 拓扑排序</text>
|
||||
<line x1="160" y1="190" x2="200" y2="190" stroke="#a78bfa" stroke-width="2" marker-end="url(#arrowP)"/>
|
||||
<rect x="200" y="172" width="130" height="36" fill="#2e1065" rx="4"/>
|
||||
<text x="265" y="195" text-anchor="middle" fill="#c4b5fd" font-size="11">State 隔离 (每次独立)</text>
|
||||
<line x1="330" y1="190" x2="370" y2="190" stroke="#a78bfa" stroke-width="2" marker-end="url(#arrowP)"/>
|
||||
<rect x="370" y="172" width="140" height="36" fill="#2e1065" rx="4"/>
|
||||
<text x="440" y="195" text-anchor="middle" fill="#c4b5fd" font-size="11">Pre/Post Handler</text>
|
||||
<line x1="510" y1="190" x2="550" y2="190" stroke="#a78bfa" stroke-width="2" marker-end="url(#arrowP)"/>
|
||||
<rect x="550" y="172" width="200" height="36" fill="#166534" rx="4"/>
|
||||
<text x="650" y="195" text-anchor="middle" fill="#4ade80" font-size="11">质检重试 + 降级兜底</text>
|
||||
<!-- Layer 3 -->
|
||||
<rect x="30" y="230" width="740" height="80" fill="#1e293b" rx="6" stroke="#f59e0b" stroke-width="1.5"/>
|
||||
<text x="50" y="252" fill="#f59e0b" font-size="13" font-weight="bold">数据一致性</text>
|
||||
<rect x="50" y="262" width="120" height="36" fill="#451a03" rx="4"/>
|
||||
<text x="110" y="285" text-anchor="middle" fill="#fcd34d" font-size="11">SQLite ACID 事务</text>
|
||||
<line x1="170" y1="280" x2="210" y2="280" stroke="#f59e0b" stroke-width="2" marker-end="url(#arrowY)"/>
|
||||
<rect x="210" y="262" width="120" height="36" fill="#451a03" rx="4"/>
|
||||
<text x="270" y="285" text-anchor="middle" fill="#fcd34d" font-size="11">GORM 外键约束</text>
|
||||
<line x1="330" y1="280" x2="370" y2="280" stroke="#f59e0b" stroke-width="2" marker-end="url(#arrowY)"/>
|
||||
<rect x="370" y="262" width="140" height="36" fill="#451a03" rx="4"/>
|
||||
<text x="440" y="285" text-anchor="middle" fill="#fcd34d" font-size="11">CASCADE 级联删除</text>
|
||||
<line x1="510" y1="280" x2="550" y2="280" stroke="#f59e0b" stroke-width="2" marker-end="url(#arrowY)"/>
|
||||
<rect x="550" y="262" width="200" height="36" fill="#166534" rx="4"/>
|
||||
<text x="650" y="285" text-anchor="middle" fill="#4ade80" font-size="11">ID: prefix_base62 唯一</text>
|
||||
<!-- Layer 4 -->
|
||||
<rect x="30" y="320" width="740" height="80" fill="#1e293b" rx="6" stroke="#f87171" stroke-width="1.5"/>
|
||||
<text x="50" y="342" fill="#f87171" font-size="13" font-weight="bold">部署一致性</text>
|
||||
<rect x="50" y="352" width="130" height="36" fill="#450a0a" rx="4"/>
|
||||
<text x="115" y="375" text-anchor="middle" fill="#fca5a5" font-size="11">Docker Compose 双容器</text>
|
||||
<line x1="180" y1="370" x2="220" y2="370" stroke="#f87171" stroke-width="2" marker-end="url(#arrowR)"/>
|
||||
<rect x="220" y="352" width="130" height="36" fill="#450a0a" rx="4"/>
|
||||
<text x="285" y="375" text-anchor="middle" fill="#fca5a5" font-size="11">Gitee CI/CD 自动化</text>
|
||||
<line x1="350" y1="370" x2="390" y2="370" stroke="#f87171" stroke-width="2" marker-end="url(#arrowR)"/>
|
||||
<rect x="390" y="352" width="140" height="36" fill="#450a0a" rx="4"/>
|
||||
<text x="460" y="375" text-anchor="middle" fill="#fca5a5" font-size="11">Viper 多层配置覆盖</text>
|
||||
<line x1="530" y1="370" x2="570" y2="370" stroke="#f87171" stroke-width="2" marker-end="url(#arrowR)"/>
|
||||
<rect x="570" y="352" width="180" height="36" fill="#166534" rx="4"/>
|
||||
<text x="660" y="375" text-anchor="middle" fill="#4ade80" font-size="11">确定性构建 · 环境一致</text>
|
||||
<!-- Bottom summary -->
|
||||
<rect x="30" y="400" width="740" height="15" fill="transparent"/>
|
||||
<text x="400" y="412" text-anchor="middle" fill="#64748b" font-size="10">风格 → 管线 → 数据 → 部署:四层一致性保障,确保输出始终可控</text>
|
||||
<defs>
|
||||
<marker id="arrowG" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6" fill="#4ade80"/></marker>
|
||||
<marker id="arrowP" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6" fill="#a78bfa"/></marker>
|
||||
<marker id="arrowY" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6" fill="#f59e0b"/></marker>
|
||||
<marker id="arrowR" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6" fill="#f87171"/></marker>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,116 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 450" font-family="system-ui, sans-serif" font-size="13">
|
||||
<defs>
|
||||
<filter id="shadow" x="-2%" y="-2%" width="104%" height="104%">
|
||||
<feDropShadow dx="1" dy="2" stdDeviation="2" flood-opacity="0.3"/>
|
||||
</filter>
|
||||
<!-- Arrow markers -->
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#60a5fa"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4ade80"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#f87171"/>
|
||||
</marker>
|
||||
<marker id="arrow-gray" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="900" height="450" fill="#0f172a" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="450" y="30" font-size="16" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Pipeline Detail — 4-Stage Flow with Retry Logic</text>
|
||||
|
||||
<!-- PipelineState shared state box (dashed border, center) -->
|
||||
<rect x="310" y="190" width="280" height="70" rx="6" fill="none" stroke="#fbbf24" stroke-width="2" stroke-dasharray="8,4" filter="url(#shadow)"/>
|
||||
<rect x="310" y="190" width="280" height="70" rx="6" fill="#1e293b" opacity="0.9"/>
|
||||
<text x="450" y="218" font-size="14" fill="#fbbf24" text-anchor="middle" font-weight="bold">PipelineState</text>
|
||||
<text x="450" y="238" font-size="11" fill="#94a3b8" text-anchor="middle">Shared state across all stages</text>
|
||||
<text x="450" y="252" font-size="10" fill="#64748b" text-anchor="middle">prompt / asset / quality / result</text>
|
||||
|
||||
<!-- START node -->
|
||||
<rect x="20" y="90" width="80" height="44" rx="6" fill="#1a1a2e" stroke="#60a5fa" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="60" y="116" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">START</text>
|
||||
|
||||
<!-- Arrow: START → PromptOptimizer -->
|
||||
<line x1="102" y1="112" x2="138" y2="112" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- PromptOptimizer -->
|
||||
<rect x="140" y="72" width="150" height="80" rx="6" fill="#1a1a2e" stroke="#818cf8" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="215" y="95" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">PromptOptimizer</text>
|
||||
<text x="215" y="112" font-size="10" fill="#94a3b8" text-anchor="middle">prompt_builder</text>
|
||||
<text x="215" y="126" font-size="10" fill="#60a5fa" text-anchor="middle">string → Prompt</text>
|
||||
<text x="215" y="142" font-size="10" fill="#fbbf24" text-anchor="middle">progress: 5-25%</text>
|
||||
|
||||
<!-- Arrow: PromptOptimizer → AssetGenerator -->
|
||||
<line x1="292" y1="112" x2="328" y2="112" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- AssetGenerator -->
|
||||
<rect x="330" y="72" width="150" height="80" rx="6" fill="#1a1a2e" stroke="#818cf8" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="405" y="95" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">AssetGenerator</text>
|
||||
<text x="405" y="112" font-size="10" fill="#94a3b8" text-anchor="middle">asset_generator</text>
|
||||
<text x="405" y="126" font-size="10" fill="#60a5fa" text-anchor="middle">Prompt → Image</text>
|
||||
<text x="405" y="142" font-size="10" fill="#fbbf24" text-anchor="middle">progress: 25-60%</text>
|
||||
|
||||
<!-- Arrow: AssetGenerator → QualitySupervisor -->
|
||||
<line x1="482" y1="112" x2="518" y2="112" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- QualitySupervisor (diamond shape) -->
|
||||
<polygon points="590,60 660,112 590,164 520,112" fill="#1a1a2e" stroke="#fbbf24" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="590" y="108" font-size="12" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Quality</text>
|
||||
<text x="590" y="122" font-size="12" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Supervisor</text>
|
||||
|
||||
<!-- QualitySupervisor detail label -->
|
||||
<text x="590" y="180" font-size="10" fill="#94a3b8" text-anchor="middle">quality_supervisor</text>
|
||||
<text x="590" y="194" font-size="10" fill="#60a5fa" text-anchor="middle">Image → QualityReport</text>
|
||||
<text x="590" y="208" font-size="10" fill="#fbbf24" text-anchor="middle">progress: 60-80%</text>
|
||||
|
||||
<!-- PASS path: QualitySupervisor → FormatAdapter -->
|
||||
<line x1="662" y1="100" x2="698" y2="80" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="680" y="82" font-size="11" fill="#4ade80" text-anchor="middle" font-weight="bold">PASS</text>
|
||||
|
||||
<!-- FormatAdapter -->
|
||||
<rect x="700" y="55" width="160" height="55" rx="6" fill="#1a1a2e" stroke="#4ade80" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="780" y="78" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">FormatAdapter</text>
|
||||
<text x="780" y="95" font-size="10" fill="#94a3b8" text-anchor="middle">format_adapter 80-100%</text>
|
||||
|
||||
<!-- Arrow: FormatAdapter → END -->
|
||||
<line x1="862" y1="82" x2="880" y2="82" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
|
||||
<!-- END node -->
|
||||
<rect x="822" y="135" width="60" height="36" rx="6" fill="#1a1a2e" stroke="#4ade80" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="852" y="157" font-size="13" fill="#4ade80" text-anchor="middle" font-weight="bold">END</text>
|
||||
<line x1="840" y1="112" x2="852" y2="135" stroke="#4ade80" stroke-width="1.5"/>
|
||||
|
||||
<!-- FAIL path: QualitySupervisor → back to PromptOptimizer (retry < 3) -->
|
||||
<path d="M 590,166 L 590,310 L 215,310 L 215,154" fill="none" stroke="#f87171" stroke-width="2" stroke-dasharray="6,3" marker-end="url(#arrow-red)"/>
|
||||
<rect x="330" y="295" width="120" height="24" rx="4" fill="#1e293b" stroke="#f87171" stroke-width="1"/>
|
||||
<text x="390" y="312" font-size="11" fill="#f87171" text-anchor="middle" font-weight="bold">FAIL: retry < 3</text>
|
||||
|
||||
<!-- DEGRADED path: QualitySupervisor → FormatAdapter (retry >= 3) -->
|
||||
<path d="M 660,164 L 700,164 L 700,112" fill="none" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-gray)"/>
|
||||
<rect x="640" y="148" width="110" height="20" rx="4" fill="#1e293b"/>
|
||||
<text x="695" y="162" font-size="10" fill="#94a3b8" text-anchor="middle">retry ≥ 3 (degraded)</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="20" y="370" width="860" height="60" rx="6" fill="#1e293b" stroke="#334155" stroke-width="1"/>
|
||||
<text x="40" y="390" font-size="12" fill="#94a3b8" font-weight="bold">Legend:</text>
|
||||
<line x1="100" y1="386" x2="140" y2="386" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="150" y="390" font-size="11" fill="#94a3b8">Normal flow</text>
|
||||
<line x1="240" y1="386" x2="280" y2="386" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="290" y="390" font-size="11" fill="#94a3b8">Pass / Success</text>
|
||||
<line x1="400" y1="386" x2="440" y2="386" stroke="#f87171" stroke-width="2" stroke-dasharray="6,3" marker-end="url(#arrow-red)"/>
|
||||
<text x="450" y="390" font-size="11" fill="#94a3b8">Fail / Retry</text>
|
||||
<line x1="540" y1="386" x2="580" y2="386" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-gray)"/>
|
||||
<text x="590" y="390" font-size="11" fill="#94a3b8">Degraded fallback</text>
|
||||
<rect x="710" y="378" width="60" height="18" rx="3" fill="none" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="6,3"/>
|
||||
<text x="740" y="392" font-size="11" fill="#94a3b8" text-anchor="middle">Shared state</text>
|
||||
|
||||
<!-- PipelineState connections (dashed lines to each node) -->
|
||||
<line x1="215" y1="152" x2="350" y2="190" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,3" opacity="0.5"/>
|
||||
<line x1="405" y1="152" x2="450" y2="190" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,3" opacity="0.5"/>
|
||||
<line x1="590" y1="164" x2="530" y2="190" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,3" opacity="0.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
@@ -0,0 +1,120 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400" font-family="system-ui, sans-serif" font-size="13">
|
||||
<defs>
|
||||
<filter id="shadow" x="-2%" y="-2%" width="104%" height="104%">
|
||||
<feDropShadow dx="1" dy="2" stdDeviation="2" flood-opacity="0.3"/>
|
||||
</filter>
|
||||
<marker id="arrow-blue" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#60a5fa"/>
|
||||
</marker>
|
||||
<marker id="arrow-green" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#4ade80"/>
|
||||
</marker>
|
||||
<marker id="arrow-red" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#f87171"/>
|
||||
</marker>
|
||||
<marker id="arrow-yellow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#fbbf24"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="400" fill="#0f172a" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="400" y="30" font-size="16" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Rate Limiting Architecture</text>
|
||||
|
||||
<!-- Request (incoming) -->
|
||||
<rect x="20" y="140" width="100" height="50" rx="6" fill="#1a1a2e" stroke="#60a5fa" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="70" y="160" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Request</text>
|
||||
<text x="70" y="178" font-size="10" fill="#94a3b8" text-anchor="middle">POST /generate</text>
|
||||
|
||||
<!-- Arrow: Request → Gin Middleware -->
|
||||
<line x1="122" y1="165" x2="168" y2="165" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- Gin Middleware -->
|
||||
<rect x="170" y="130" width="140" height="70" rx="6" fill="#1a1a2e" stroke="#818cf8" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="240" y="158" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Gin Middleware</text>
|
||||
<text x="240" y="175" font-size="10" fill="#94a3b8" text-anchor="middle">RateLimiter()</text>
|
||||
<text x="240" y="190" font-size="10" fill="#64748b" text-anchor="middle">IP + Auth extraction</text>
|
||||
|
||||
<!-- Arrow: Middleware → User Limiter -->
|
||||
<line x1="312" y1="152" x2="358" y2="112" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="340" y="128" font-size="10" fill="#94a3b8" text-anchor="middle">per-user</text>
|
||||
|
||||
<!-- Arrow: Middleware → Global Limiter -->
|
||||
<line x1="312" y1="178" x2="358" y2="218" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="340" y="204" font-size="10" fill="#94a3b8" text-anchor="middle">global</text>
|
||||
|
||||
<!-- User-level Limiter -->
|
||||
<rect x="360" y="72" width="170" height="80" rx="6" fill="#1a1a2e" stroke="#818cf8" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="445" y="95" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">User-Level Limiter</text>
|
||||
<text x="445" y="112" font-size="10" fill="#94a3b8" text-anchor="middle">key: userID</text>
|
||||
<text x="445" y="126" font-size="10" fill="#fbbf24" text-anchor="middle">rate: 3 req/min</text>
|
||||
<text x="445" y="140" font-size="10" fill="#fbbf24" text-anchor="middle">burst: 15</text>
|
||||
|
||||
<!-- Global-level Limiter -->
|
||||
<rect x="360" y="195" width="170" height="80" rx="6" fill="#1a1a2e" stroke="#818cf8" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="445" y="218" font-size="13" fill="#e2e8f0" text-anchor="middle" font-weight="bold">Global-Level Limiter</text>
|
||||
<text x="445" y="235" font-size="10" fill="#94a3b8" text-anchor="middle">key: "generate"</text>
|
||||
<text x="445" y="249" font-size="10" fill="#fbbf24" text-anchor="middle">rate: 20 req/min</text>
|
||||
<text x="445" y="263" font-size="10" fill="#fbbf24" text-anchor="middle">burst: 50</text>
|
||||
|
||||
<!-- Arrow: User Limiter → Redis -->
|
||||
<line x1="532" y1="112" x2="578" y2="140" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- Arrow: Global Limiter → Redis -->
|
||||
<line x1="532" y1="235" x2="578" y2="210" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
|
||||
<!-- Redis (Token Bucket Lua Script) -->
|
||||
<rect x="580" y="120" width="180" height="105" rx="6" fill="#1a1a2e" stroke="#f87171" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="670" y="145" font-size="14" fill="#f87171" text-anchor="middle" font-weight="bold">Redis</text>
|
||||
<text x="670" y="163" font-size="11" fill="#e2e8f0" text-anchor="middle">Token Bucket</text>
|
||||
<text x="670" y="180" font-size="11" fill="#e2e8f0" text-anchor="middle">Lua Script</text>
|
||||
<text x="670" y="200" font-size="10" fill="#94a3b8" text-anchor="middle">INCR + EXPIRE + EVAL</text>
|
||||
<text x="670" y="215" font-size="10" fill="#64748b" text-anchor="middle">Atomic operation</text>
|
||||
|
||||
<!-- Pass path: both limiters → proceed -->
|
||||
<path d="M 445,152 L 445,320 L 200,320 L 200,260" fill="none" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)" opacity="0"/>
|
||||
<line x1="445" y1="152" x2="445" y2="310" stroke="#4ade80" stroke-width="0" opacity="0"/>
|
||||
|
||||
<!-- Decision: Allow? -->
|
||||
<!-- Proceed to handler (both pass) -->
|
||||
<rect x="260" y="310" width="120" height="40" rx="6" fill="#1a1a2e" stroke="#4ade80" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="320" y="335" font-size="13" fill="#4ade80" text-anchor="middle" font-weight="bold">→ Handler</text>
|
||||
|
||||
<!-- Success flow: from middleware area down -->
|
||||
<path d="M 240,200 L 240,330 L 258,330" fill="none" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="230" y="270" font-size="10" fill="#4ade80" text-anchor="middle" transform="rotate(-90 230 270)">allow</text>
|
||||
|
||||
<!-- HTTP 429 response path -->
|
||||
<rect x="520" y="310" width="130" height="40" rx="6" fill="#1a1a2e" stroke="#f87171" stroke-width="1.5" filter="url(#shadow)"/>
|
||||
<text x="585" y="328" font-size="13" fill="#f87171" text-anchor="middle" font-weight="bold">HTTP 429</text>
|
||||
<text x="585" y="343" font-size="10" fill="#94a3b8" text-anchor="middle">Too Many Requests</text>
|
||||
|
||||
<!-- Arrow: Redis → 429 (rate exceeded) -->
|
||||
<path d="M 670,225 L 670,330 L 652,330" fill="none" stroke="#f87171" stroke-width="2" marker-end="url(#arrow-red)"/>
|
||||
<text x="670" y="275" font-size="10" fill="#f87171" text-anchor="middle">exceeded</text>
|
||||
|
||||
<!-- Fail-open path (Redis unavailable) -->
|
||||
<rect x="600" y="50" width="160" height="40" rx="6" fill="#1a1a2e" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="6,3" filter="url(#shadow)"/>
|
||||
<text x="680" y="68" font-size="12" fill="#fbbf24" text-anchor="middle" font-weight="bold">Fail-Open</text>
|
||||
<text x="680" y="82" font-size="10" fill="#94a3b8" text-anchor="middle">Redis unavailable → allow</text>
|
||||
|
||||
<!-- Arrow: Redis → Fail-Open -->
|
||||
<path d="M 720,120 L 720,92" fill="none" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-yellow)"/>
|
||||
<text x="738" y="110" font-size="9" fill="#fbbf24" text-anchor="start">error</text>
|
||||
|
||||
<!-- Arrow: Fail-Open → Handler -->
|
||||
<path d="M 600,70 L 320,70 L 320,308" fill="none" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-yellow)"/>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect x="20" y="365" width="760" height="28" rx="6" fill="#1e293b" stroke="#334155" stroke-width="1"/>
|
||||
<line x1="40" y1="379" x2="70" y2="379" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrow-blue)"/>
|
||||
<text x="80" y="383" font-size="10" fill="#94a3b8">Normal</text>
|
||||
<line x1="140" y1="379" x2="170" y2="379" stroke="#4ade80" stroke-width="2" marker-end="url(#arrow-green)"/>
|
||||
<text x="180" y="383" font-size="10" fill="#94a3b8">Allow</text>
|
||||
<line x1="220" y1="379" x2="250" y2="379" stroke="#f87171" stroke-width="2" marker-end="url(#arrow-red)"/>
|
||||
<text x="260" y="383" font-size="10" fill="#94a3b8">Rate Exceeded</text>
|
||||
<line x1="370" y1="379" x2="400" y2="379" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrow-yellow)"/>
|
||||
<text x="410" y="383" font-size="10" fill="#94a3b8">Fail-Open (Redis down)</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.0 KiB |
Reference in New Issue
Block a user