Current section

53 Versions

Jump to

Compare versions

4 files changed
+82 additions
-42 deletions
  @@ -2,12 +2,14 @@
2 2
3 3 ```mermaid
4 4 graph LR
5 - subgraph "Elixir/OTP Layer"
5 + ElixirOTPLayer["Elixir OTP Layer"]
6 + subgraph ElixirOTPLayer
6 7 Client["Client API"]
7 8 Pool["Pool Manager<br/>⚡ Non-blocking async"]
8 9 TaskSup["Task Supervisor<br/>⚡ Isolated execution"]
9 10
10 - subgraph "Worker Management"
11 + WorkerManagement["Worker Management"]
12 + subgraph WorkerManagement
11 13 WorkerSup["Worker Supervisor<br/>⚡ Dynamic workers"]
12 14 Starter1["Worker Starter 1<br/>🔄 Auto-restart"]
13 15 Starter2["Worker Starter 2<br/>🔄 Auto-restart"]
  @@ -17,19 +19,22 @@ graph LR
17 19 WorkerN["Worker N<br/>GenServer"]
18 20 end
19 21
20 - subgraph "High-Performance Registries"
22 + HighPerformanceRegistries["High Performance Registries"]
23 + subgraph HighPerformanceRegistries
21 24 Registry["Worker Registry<br/>⚡ O(1) lookups"]
22 25 ProcReg["Process Registry<br/>⚡ PID tracking"]
23 26 StarterReg["Starter Registry<br/>⚡ Supervisor tracking"]
24 27 end
25 28
26 - subgraph "Session Store (ETS)"
29 + SessionStoreETS["Session Store ETS"]
30 + subgraph SessionStoreETS
27 31 SessionStore["Session Store<br/>⚡ Concurrent R/W<br/>📊 Decentralized counters"]
28 32 GlobalPrograms["Global Programs<br/>⚡ Public table access"]
29 33 end
30 34 end
31 35
32 - subgraph "External Processes"
36 + ExternalProcesses["External Processes"]
37 + subgraph ExternalProcesses
33 38 Python1["Python Process 1<br/>🐍 Port communication"]
34 39 Python2["Python Process 2<br/>🐍 Port communication"]
35 40 PythonN["Python Process N<br/>🐍 Port communication"]
  @@ -63,10 +68,15 @@ graph LR
63 68 Worker2 -->|Track PID| ProcReg
64 69 WorkerN -->|Track PID| ProcReg
65 70
66 - style Pool fill:#f9f,stroke:#333,stroke-width:4px,color:#000
67 - style SessionStore fill:#bbf,stroke:#333,stroke-width:4px,color:#000
68 - style Registry fill:#bfb,stroke:#333,stroke-width:4px,color:#000
69 - style TaskSup fill:#fbf,stroke:#333,stroke-width:4px,color:#000
71 + style ElixirOTPLayer fill:#e6e6fa,stroke:#9370db,stroke-width:3px,color:#2e1065
72 + style WorkerManagement fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
73 + style HighPerformanceRegistries fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
74 + style SessionStoreETS fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
75 + style ExternalProcesses fill:#f0f9ff,stroke:#0ea5e9,stroke-width:2px,color:#0c4a6e
76 + style Pool fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
77 + style SessionStore fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
78 + style Registry fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
79 + style TaskSup fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
70 80 ```
71 81
72 82 ## 2. Request Flow - Performance Critical Path
  @@ -113,8 +123,10 @@ sequenceDiagram
113 123
114 124 ```mermaid
115 125 graph LR
116 - subgraph "Session Store ETS Tables"
117 - subgraph "Sessions Table"
126 + SessionStoreETSTables["Session Store ETS Tables"]
127 + subgraph SessionStoreETSTables
128 + SessionsTable["Sessions Table"]
129 + subgraph SessionsTable
118 130 ST[":snakepit_sessions<br/>⚡ read_concurrency: true<br/>⚡ write_concurrency: true<br/>⚡ decentralized_counters: true"]
119 131
120 132 S1["Key: session_1<br/>Value: {last_accessed, ttl, session_data}"]
  @@ -122,7 +134,8 @@ graph LR
122 134 SN["Key: session_N<br/>Value: {last_accessed, ttl, session_data}"]
123 135 end
124 136
125 - subgraph "Global Programs Table"
137 + GlobalProgramsTable["Global Programs Table"]
138 + subgraph GlobalProgramsTable
126 139 GP[":snakepit_sessions_global_programs<br/>⚡ Same optimizations"]
127 140
128 141 P1["Key: program_1<br/>Value: {data, timestamp}"]
  @@ -131,7 +144,8 @@ graph LR
131 144 end
132 145 end
133 146
134 - subgraph "Optimized Operations"
147 + OptimizedOperations["Optimized Operations"]
148 + subgraph OptimizedOperations
135 149 Read["⚡ Concurrent reads<br/>No locking"]
136 150 Write["⚡ Concurrent writes<br/>Decentralized counters"]
137 151 Cleanup["⚡ select_delete<br/>Atomic batch cleanup"]
  @@ -152,11 +166,15 @@ graph LR
152 166 Cleanup --> ST
153 167 Cleanup --> GP
154 168
155 - style ST fill:#bbf,stroke:#333,stroke-width:4px,color:#000
156 - style GP fill:#bbf,stroke:#333,stroke-width:4px,color:#000
157 - style Read fill:#bfb,stroke:#333,stroke-width:2px,color:#000
158 - style Write fill:#bfb,stroke:#333,stroke-width:2px,color:#000
159 - style Cleanup fill:#fbb,stroke:#333,stroke-width:2px,color:#000
169 + style SessionStoreETSTables fill:#e6e6fa,stroke:#9370db,stroke-width:3px,color:#2e1065
170 + style SessionsTable fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
171 + style GlobalProgramsTable fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
172 + style OptimizedOperations fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
173 + style ST fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
174 + style GP fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
175 + style Read fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
176 + style Write fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
177 + style Cleanup fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
160 178 ```
161 179
162 180 ## 4. Worker Lifecycle - Performance & Reliability
  @@ -204,7 +222,8 @@ stateDiagram-v2
204 222
205 223 ```mermaid
206 224 graph TD
207 - subgraph "Sequential Startup (Traditional)"
225 + SequentialStartupTraditional["Sequential Startup Traditional"]
226 + subgraph SequentialStartupTraditional
208 227 T0["Start"] --> W1S["Worker 1<br/>2s"]
209 228 W1S --> W2S["Worker 2<br/>2s"]
210 229 W2S --> W3S["Worker 3<br/>2s"]
  @@ -212,7 +231,8 @@ graph TD
212 231 W4S --> DoneS["Ready<br/>Total: 8s"]
213 232 end
214 233
215 - subgraph "Concurrent Startup (Snakepit)"
234 + ConcurrentStartupSnakepit["Concurrent Startup Snakepit"]
235 + subgraph ConcurrentStartupSnakepit
216 236 T0C["Start"] --> Init["Task.async_stream"]
217 237 Init --> W1C["Worker 1<br/>2s"]
218 238 Init --> W2C["Worker 2<br/>2s"]
  @@ -227,17 +247,21 @@ graph TD
227 247 Collect --> DoneC["Ready<br/>Total: ~2s"]
228 248 end
229 249
230 - style Init fill:#f9f,stroke:#333,stroke-width:4px,color:#000
231 - style DoneC fill:#bfb,stroke:#333,stroke-width:4px,color:#000
232 - style DoneS fill:#fbb,stroke:#333,stroke-width:2px,color:#000
250 + style SequentialStartupTraditional fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e
251 + style ConcurrentStartupSnakepit fill:#e6e6fa,stroke:#9370db,stroke-width:3px,color:#2e1065
252 + style Init fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
253 + style DoneC fill:#dcfce7,stroke:#22c55e,stroke-width:2px,color:#14532d
254 + style DoneS fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d
233 255 ```
234 256
235 257 ## 6. Request Queueing & Load Distribution
236 258
237 259 ```mermaid
238 260 graph LR
239 - subgraph "High-Performance Request Handling"
240 - subgraph "Request Queue"
261 + HighPerformanceRequestHandling["High Performance Request Handling"]
262 + subgraph HighPerformanceRequestHandling
263 + RequestQueue["Request Queue"]
264 + subgraph RequestQueue
241 265 Q[":queue (Erlang)<br/>⚡ FIFO<br/>⚡ O(1) operations"]
242 266 R1["Request 1"]
243 267 R2["Request 2"]
  @@ -245,7 +269,8 @@ graph LR
245 269 RN["Request N"]
246 270 end
247 271
248 - subgraph "Worker Pool State"
272 + WorkerPoolState["Worker Pool State"]
273 + subgraph WorkerPoolState
249 274 Available["MapSet<br/>⚡ O(1) member check<br/>⚡ O(1) add/remove"]
250 275 Busy["Map<br/>⚡ O(1) lookup"]
251 276
  @@ -255,7 +280,8 @@ graph LR
255 280 BW4["Worker 4 🔴"]
256 281 end
257 282
258 - subgraph "Load Distribution"
283 + LoadDistribution["Load Distribution"]
284 + subgraph LoadDistribution
259 285 Check{"Worker<br/>Available?"}
260 286 Assign["Assign to worker<br/>⚡ O(1)"]
261 287 Queue["Queue request<br/>⚡ O(1)"]
  @@ -283,31 +309,39 @@ graph LR
283 309
284 310 Dequeue -->|Worker freed| Assign
285 311
286 - style Q fill:#bbf,stroke:#333,stroke-width:4px,color:#000
287 - style Available fill:#bfb,stroke:#333,stroke-width:4px,color:#000
288 - style Check fill:#f9f,stroke:#333,stroke-width:4px,color:#000
312 + style HighPerformanceRequestHandling fill:#e6e6fa,stroke:#9370db,stroke-width:3px,color:#2e1065
313 + style RequestQueue fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
314 + style WorkerPoolState fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
315 + style LoadDistribution fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
316 + style Q fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
317 + style Available fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
318 + style Check fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
289 319 ```
290 320
291 321 ## 7. Process Registry - O(1) Performance
292 322
293 323 ```mermaid
294 324 graph LR
295 - subgraph "Registry Architecture"
296 - subgraph "Worker Registry"
325 + RegistryArchitecture["Registry Architecture"]
326 + subgraph RegistryArchitecture
327 + WorkerRegistry["Worker Registry"]
328 + subgraph WorkerRegistry
297 329 WR["Elixir Registry<br/>⚡ :unique keys<br/>⚡ O(1) operations"]
298 330 WK1["worker_1 → PID1"]
299 331 WK2["worker_2 → PID2"]
300 332 WKN["worker_N → PIDN"]
301 333 end
302 334
303 - subgraph "Process Registry (ETS)"
335 + ProcessRegistryETS["Process Registry ETS"]
336 + subgraph ProcessRegistryETS
304 337 PR["Process Registry<br/>⚡ :protected table<br/>⚡ read_concurrency"]
305 338 PK1["worker_1 → {pid, os_pid, fingerprint}"]
306 339 PK2["worker_2 → {pid, os_pid, fingerprint}"]
307 340 PKN["worker_N → {pid, os_pid, fingerprint}"]
308 341 end
309 342
310 - subgraph "Starter Registry"
343 + StarterRegistry["Starter Registry"]
344 + subgraph StarterRegistry
311 345 SR["Starter Registry<br/>⚡ Supervisor tracking"]
312 346 SK1["worker_1 → Starter PID1"]
313 347 SK2["worker_2 → Starter PID2"]
  @@ -315,7 +349,8 @@ graph LR
315 349 end
316 350 end
317 351
318 - subgraph "O(1) Operations"
352 + O1Operations["O(1) Operations"]
353 + subgraph O1Operations
319 354 Op1["via_tuple lookup<br/>⚡ Direct to worker"]
320 355 Op2["Reverse lookup<br/>⚡ PID to worker_id"]
321 356 Op3["OS PID tracking<br/>⚡ Cleanup guarantee"]
  @@ -337,7 +372,12 @@ graph LR
337 372 Op2 --> WR
338 373 Op3 --> PR
339 374
340 - style WR fill:#bfb,stroke:#333,stroke-width:4px,color:#000
341 - style PR fill:#bbf,stroke:#333,stroke-width:4px,color:#000
342 - style SR fill:#fbf,stroke:#333,stroke-width:4px,color:#000
375 + style RegistryArchitecture fill:#e6e6fa,stroke:#9370db,stroke-width:3px,color:#2e1065
376 + style WorkerRegistry fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
377 + style ProcessRegistryETS fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
378 + style StarterRegistry fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
379 + style O1Operations fill:#f3e8ff,stroke:#a855f7,stroke-width:2px,color:#581c87
380 + style WR fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
381 + style PR fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
382 + style SR fill:#ddd6fe,stroke:#7c3aed,stroke-width:2px,color:#581c87
343 383 ```
\ No newline at end of file
  @@ -42,7 +42,7 @@ Snakepit is a battle-tested Elixir library that provides a robust pooling system
42 42 # In your mix.exs
43 43 def deps do
44 44 [
45 - {:snakepit, "~> 0.0.1"}
45 + {:snakepit, "~> 0.1.2"}
46 46 ]
47 47 end
48 48
  @@ -68,7 +68,7 @@ Application.put_env(:snakepit, :pool_config, %{pool_size: 4})
68 68 ```elixir
69 69 def deps do
70 70 [
71 - {:snakepit, "~> 0.0.1"}
71 + {:snakepit, "~> 0.1.2"}
72 72 ]
73 73 end
74 74 ```
  @@ -1,6 +1,6 @@
1 1 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/nshkrdotcom/snakepit">>}]}.
2 2 {<<"name">>,<<"snakepit">>}.
3 - {<<"version">>,<<"0.1.1">>}.
3 + {<<"version">>,<<"0.1.2">>}.
4 4 {<<"description">>,
5 5 <<"High-performance pooler and session manager for external language integrations">>}.
6 6 {<<"elixir">>,<<"~> 1.18">>}.
  @@ -4,7 +4,7 @@ defmodule Snakepit.MixProject do
4 4 def project do
5 5 [
6 6 app: :snakepit,
7 - version: "0.1.1",
7 + version: "0.1.2",
8 8 elixir: "~> 1.18",
9 9 start_permanent: Mix.env() == :prod,
10 10 description: