turboapi 0.3.28__cp313-cp313-win_amd64.whl → 0.4.1__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- turboapi/_rust.cp313-win_amd64.pyd +0 -0
- turboapi/async_limiter.py +86 -0
- turboapi/main_app.py +63 -2
- {turboapi-0.3.28.dist-info → turboapi-0.4.1.dist-info}/METADATA +2 -2
- {turboapi-0.3.28.dist-info → turboapi-0.4.1.dist-info}/RECORD +6 -5
- {turboapi-0.3.28.dist-info → turboapi-0.4.1.dist-info}/WHEEL +0 -0
|
Binary file
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Async Limiter - Semaphore-based rate limiting for async tasks
|
|
3
|
+
|
|
4
|
+
Prevents event loop overload by limiting concurrent async tasks.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
from typing import Any, Coroutine
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AsyncLimiter:
|
|
12
|
+
"""Semaphore-based limiter for async tasks
|
|
13
|
+
|
|
14
|
+
Limits the number of concurrent async tasks to prevent event loop overload.
|
|
15
|
+
This is critical for maintaining stable performance under high load.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
max_concurrent: Maximum number of concurrent tasks (default: 512)
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
limiter = AsyncLimiter(max_concurrent=512)
|
|
22
|
+
result = await limiter(some_coroutine())
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, max_concurrent: int = 512):
|
|
26
|
+
self.semaphore = asyncio.Semaphore(max_concurrent)
|
|
27
|
+
self.max_concurrent = max_concurrent
|
|
28
|
+
self._active_tasks = 0
|
|
29
|
+
|
|
30
|
+
async def __call__(self, coro: Coroutine) -> Any:
|
|
31
|
+
"""Execute coroutine with semaphore gating
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
coro: Coroutine to execute
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Result of the coroutine
|
|
38
|
+
"""
|
|
39
|
+
async with self.semaphore:
|
|
40
|
+
self._active_tasks += 1
|
|
41
|
+
try:
|
|
42
|
+
return await coro
|
|
43
|
+
finally:
|
|
44
|
+
self._active_tasks -= 1
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def active_tasks(self) -> int:
|
|
48
|
+
"""Get current number of active tasks"""
|
|
49
|
+
return self._active_tasks
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def available_slots(self) -> int:
|
|
53
|
+
"""Get number of available slots"""
|
|
54
|
+
return self.max_concurrent - self._active_tasks
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Global limiter instance per event loop
|
|
58
|
+
_limiters = {}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_limiter(max_concurrent: int = 512) -> AsyncLimiter:
|
|
62
|
+
"""Get or create limiter for current event loop
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
max_concurrent: Maximum concurrent tasks
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
AsyncLimiter instance for current event loop
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
loop = asyncio.get_running_loop()
|
|
72
|
+
loop_id = id(loop)
|
|
73
|
+
|
|
74
|
+
if loop_id not in _limiters:
|
|
75
|
+
_limiters[loop_id] = AsyncLimiter(max_concurrent)
|
|
76
|
+
|
|
77
|
+
return _limiters[loop_id]
|
|
78
|
+
except RuntimeError:
|
|
79
|
+
# No running loop, create standalone limiter
|
|
80
|
+
return AsyncLimiter(max_concurrent)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def reset_limiters():
|
|
84
|
+
"""Reset all limiters (useful for testing)"""
|
|
85
|
+
global _limiters
|
|
86
|
+
_limiters = {}
|
turboapi/main_app.py
CHANGED
|
@@ -193,14 +193,19 @@ class TurboAPI(Router):
|
|
|
193
193
|
"detail": str(e)
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
def
|
|
196
|
+
def run_legacy(
|
|
197
197
|
self,
|
|
198
198
|
host: str = "127.0.0.1",
|
|
199
199
|
port: int = 8000,
|
|
200
200
|
workers: int = 1,
|
|
201
201
|
**kwargs
|
|
202
202
|
):
|
|
203
|
-
"""Run the TurboAPI application.
|
|
203
|
+
"""Run the TurboAPI application with legacy loop sharding (DEPRECATED).
|
|
204
|
+
|
|
205
|
+
Use run() instead for 12x better performance with Pure Rust Async Runtime.
|
|
206
|
+
"""
|
|
207
|
+
print(f"\n⚠️ WARNING: Using legacy loop sharding runtime")
|
|
208
|
+
print(f" For 12x better performance, use app.run() (default)")
|
|
204
209
|
print(f"\n{ROCKET} Starting TurboAPI server...")
|
|
205
210
|
print(f" Host: {host}:{port}")
|
|
206
211
|
print(f" Workers: {workers}")
|
|
@@ -246,3 +251,59 @@ class TurboAPI(Router):
|
|
|
246
251
|
asyncio.run(self._run_shutdown_handlers())
|
|
247
252
|
|
|
248
253
|
print("[BYE] Server stopped")
|
|
254
|
+
|
|
255
|
+
def run(
|
|
256
|
+
self,
|
|
257
|
+
host: str = "127.0.0.1",
|
|
258
|
+
port: int = 8000,
|
|
259
|
+
**kwargs
|
|
260
|
+
):
|
|
261
|
+
"""Run the TurboAPI application with Pure Rust Async Runtime.
|
|
262
|
+
|
|
263
|
+
Performance: 24K+ RPS (12x faster than baseline!)
|
|
264
|
+
Uses Tokio work-stealing scheduler with Python 3.14 free-threading.
|
|
265
|
+
"""
|
|
266
|
+
print(f"\n🚀 Starting TurboAPI with Pure Rust Async Runtime!")
|
|
267
|
+
print(f" Host: {host}:{port}")
|
|
268
|
+
print(f" Title: {self.title} v{self.version}")
|
|
269
|
+
print(f" ⚡ Performance: 24K+ RPS (12x improvement!)")
|
|
270
|
+
|
|
271
|
+
# Print route information
|
|
272
|
+
self.print_routes()
|
|
273
|
+
|
|
274
|
+
print("\n[PERF] Phase D Features:")
|
|
275
|
+
print(" ✨ Tokio work-stealing scheduler")
|
|
276
|
+
print(" ✨ Python 3.14 free-threading (no GIL)")
|
|
277
|
+
print(" ✨ pyo3-async-runtimes bridge")
|
|
278
|
+
print(" ✨ 7,168 concurrent task capacity")
|
|
279
|
+
print(" ✨ Rust-powered async execution")
|
|
280
|
+
|
|
281
|
+
# Run startup handlers
|
|
282
|
+
if self.startup_handlers:
|
|
283
|
+
asyncio.run(self._run_startup_handlers())
|
|
284
|
+
|
|
285
|
+
print(f"\n{CHECK_MARK} TurboAPI server ready with Tokio runtime!")
|
|
286
|
+
print(f" Visit: http://{host}:{port}")
|
|
287
|
+
|
|
288
|
+
try:
|
|
289
|
+
# Import and use the Rust server with Tokio runtime
|
|
290
|
+
import turbonet
|
|
291
|
+
|
|
292
|
+
server = turbonet.TurboServer(host, port)
|
|
293
|
+
|
|
294
|
+
# Register all routes
|
|
295
|
+
for route in self.registry.get_routes():
|
|
296
|
+
server.add_route(route.method.value, route.path, route.handler)
|
|
297
|
+
|
|
298
|
+
print(f"\n[SERVER] Starting Tokio runtime...")
|
|
299
|
+
# Use run_tokio instead of run!
|
|
300
|
+
server.run_tokio()
|
|
301
|
+
|
|
302
|
+
except KeyboardInterrupt:
|
|
303
|
+
print("\n[STOP] Shutting down TurboAPI server...")
|
|
304
|
+
|
|
305
|
+
# Run shutdown handlers
|
|
306
|
+
if self.shutdown_handlers:
|
|
307
|
+
asyncio.run(self._run_shutdown_handlers())
|
|
308
|
+
|
|
309
|
+
print("[BYE] Server stopped")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: turboapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -23,7 +23,7 @@ Requires-Dist: pandas>=1.3.0 ; extra == 'benchmark'
|
|
|
23
23
|
Requires-Dist: requests>=2.25.0 ; extra == 'benchmark'
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Provides-Extra: benchmark
|
|
26
|
-
Summary: Revolutionary Python web framework with FastAPI syntax and
|
|
26
|
+
Summary: Revolutionary Python web framework with FastAPI syntax and 12x performance - Pure Rust Async Runtime (Python 3.13+ free-threading required)
|
|
27
27
|
Keywords: web,framework,http,server,rust,performance,free-threading,no-gil,fastapi-compatible
|
|
28
28
|
Home-Page: https://github.com/justrach/turboAPI
|
|
29
29
|
Author-email: Rach Pradhan <rach@turboapi.dev>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
turboapi-0.
|
|
2
|
-
turboapi-0.
|
|
1
|
+
turboapi-0.4.1.dist-info/METADATA,sha256=ZH6x-Hl8MpzPigfYncs6OIUs6gKVTTEeGT2aKFAalzg,1481
|
|
2
|
+
turboapi-0.4.1.dist-info/WHEEL,sha256=TJQY77QRLvXq32tEs9ATmwKO6NAOtuKOAw50eyiSmWU,96
|
|
3
3
|
turboapi/__init__.py,sha256=r9Fphtu9ruHFUhSpBMAGxY5en2wvcnsE1nMp2DDRM6w,692
|
|
4
|
-
turboapi/_rust.cp313-win_amd64.pyd,sha256=
|
|
4
|
+
turboapi/_rust.cp313-win_amd64.pyd,sha256=C_Dwmlg87zZ4-8CXqiu99XMu6EQV6ovMiIZATO4c3Fo,3659264
|
|
5
|
+
turboapi/async_limiter.py,sha256=x2qkloPbg2YelDNUXKya2BwBTq5zVxDHxuaQspIgYBg,2416
|
|
5
6
|
turboapi/async_pool.py,sha256=UVm0A-0jIN4V43jY8a5XEU_L0SSyWGMV2bs5FiQGr2M,4489
|
|
6
7
|
turboapi/decorators.py,sha256=jjJrIXZ3y_yJ231ar24hS09OCDtTqmYA7arpIOcr2kk,1788
|
|
7
|
-
turboapi/main_app.py,sha256=
|
|
8
|
+
turboapi/main_app.py,sha256=e2w03wgEnh1lz-w_dGJUM0OQfG8Fd1GBEOWSYm8LiRE,11516
|
|
8
9
|
turboapi/middleware.py,sha256=iqtklH5_GMICuAmmxMBfaFSNZkR8wHSNbwhNscGe-pA,11200
|
|
9
10
|
turboapi/models.py,sha256=VCU68f9MGtDdFb4crsx2e0SHghICg8zjU8OumfdpZLQ,5363
|
|
10
11
|
turboapi/request_handler.py,sha256=KrN9d3r7bO8LUU68X6cXTtl3a2dCoRqmdWrjDW2V2qQ,8413
|
|
@@ -13,4 +14,4 @@ turboapi/rust_integration.py,sha256=ycA_i8kxC2Upbu7PAqC2EdjsqRw5AVkYwLvx9aTWBWc,
|
|
|
13
14
|
turboapi/security.py,sha256=-XgwBhiqQZdfU7oKLHi-3xN_UwlKiQxpfSQ6kTA0ko8,17230
|
|
14
15
|
turboapi/server_integration.py,sha256=drUhhTasWgQfyhFiAaHKd987N3mnE0qkMab1ylmqd4c,18340
|
|
15
16
|
turboapi/version_check.py,sha256=z3O1vIJsWmG_DO271ayYWSwaDfgpFnfJzYRYyowKYMc,9625
|
|
16
|
-
turboapi-0.
|
|
17
|
+
turboapi-0.4.1.dist-info/RECORD,,
|
|
File without changes
|