linglong-web 0.0.1__tar.gz

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.
Files changed (71) hide show
  1. linglong_web-0.0.1/LICENSE +21 -0
  2. linglong_web-0.0.1/MANIFEST.in +14 -0
  3. linglong_web-0.0.1/PKG-INFO +249 -0
  4. linglong_web-0.0.1/README.md +180 -0
  5. linglong_web-0.0.1/linglong_web/__init__.py +132 -0
  6. linglong_web-0.0.1/linglong_web/__version__.py +9 -0
  7. linglong_web-0.0.1/linglong_web/core/__init__.py +54 -0
  8. linglong_web-0.0.1/linglong_web/core/auth.py +31 -0
  9. linglong_web-0.0.1/linglong_web/core/cacher.py +92 -0
  10. linglong_web-0.0.1/linglong_web/core/cluster_lock.py +128 -0
  11. linglong_web-0.0.1/linglong_web/core/config.py +196 -0
  12. linglong_web-0.0.1/linglong_web/core/constants.py +38 -0
  13. linglong_web-0.0.1/linglong_web/core/cors.py +52 -0
  14. linglong_web-0.0.1/linglong_web/core/db.py +12 -0
  15. linglong_web-0.0.1/linglong_web/core/ddl_manager.py +457 -0
  16. linglong_web-0.0.1/linglong_web/core/errors.py +118 -0
  17. linglong_web-0.0.1/linglong_web/core/http.py +305 -0
  18. linglong_web-0.0.1/linglong_web/core/limiter.py +55 -0
  19. linglong_web-0.0.1/linglong_web/core/limiter_local.py +84 -0
  20. linglong_web-0.0.1/linglong_web/core/py.typed +0 -0
  21. linglong_web-0.0.1/linglong_web/core/resource.py +676 -0
  22. linglong_web-0.0.1/linglong_web/core/response.py +86 -0
  23. linglong_web-0.0.1/linglong_web/core/router.py +57 -0
  24. linglong_web-0.0.1/linglong_web/core/scheduler.py +78 -0
  25. linglong_web-0.0.1/linglong_web/core/schemas.py +74 -0
  26. linglong_web-0.0.1/linglong_web/core/server.py +364 -0
  27. linglong_web-0.0.1/linglong_web/core/server_extensions.py +23 -0
  28. linglong_web-0.0.1/linglong_web/core/types.py +17 -0
  29. linglong_web-0.0.1/linglong_web/py.typed +0 -0
  30. linglong_web-0.0.1/linglong_web/utils/__init__.py +8 -0
  31. linglong_web-0.0.1/linglong_web/utils/async_read_write_lock.py +113 -0
  32. linglong_web-0.0.1/linglong_web/utils/context.py +58 -0
  33. linglong_web-0.0.1/linglong_web/utils/ddl_manager.py +1110 -0
  34. linglong_web-0.0.1/linglong_web/utils/log.py +84 -0
  35. linglong_web-0.0.1/linglong_web/utils/pj_struct.py +12 -0
  36. linglong_web-0.0.1/linglong_web/utils/signal_handler.py +227 -0
  37. linglong_web-0.0.1/linglong_web/utils/time.py +16 -0
  38. linglong_web-0.0.1/linglong_web.egg-info/PKG-INFO +249 -0
  39. linglong_web-0.0.1/linglong_web.egg-info/SOURCES.txt +69 -0
  40. linglong_web-0.0.1/linglong_web.egg-info/dependency_links.txt +1 -0
  41. linglong_web-0.0.1/linglong_web.egg-info/not-zip-safe +1 -0
  42. linglong_web-0.0.1/linglong_web.egg-info/requires.txt +50 -0
  43. linglong_web-0.0.1/linglong_web.egg-info/top_level.txt +1 -0
  44. linglong_web-0.0.1/pyproject.toml +174 -0
  45. linglong_web-0.0.1/setup.cfg +4 -0
  46. linglong_web-0.0.1/tests/test_auth.py +29 -0
  47. linglong_web-0.0.1/tests/test_cacher.py +67 -0
  48. linglong_web-0.0.1/tests/test_cluster_lock.py +61 -0
  49. linglong_web-0.0.1/tests/test_config.py +65 -0
  50. linglong_web-0.0.1/tests/test_core_cacher.py +67 -0
  51. linglong_web-0.0.1/tests/test_core_ddl_manager.py +155 -0
  52. linglong_web-0.0.1/tests/test_core_ddl_manager_algorithms.py +114 -0
  53. linglong_web-0.0.1/tests/test_core_ddl_manager_check_and_init_no_db.py +125 -0
  54. linglong_web-0.0.1/tests/test_cors_and_time_utils.py +97 -0
  55. linglong_web-0.0.1/tests/test_ddl_manager.py +343 -0
  56. linglong_web-0.0.1/tests/test_errors_more.py +33 -0
  57. linglong_web-0.0.1/tests/test_http_client.py +85 -0
  58. linglong_web-0.0.1/tests/test_http_client_behavior.py +111 -0
  59. linglong_web-0.0.1/tests/test_limiter.py +86 -0
  60. linglong_web-0.0.1/tests/test_limiter_local.py +61 -0
  61. linglong_web-0.0.1/tests/test_resource.py +29 -0
  62. linglong_web-0.0.1/tests/test_resource_ensure_database_exists.py +105 -0
  63. linglong_web-0.0.1/tests/test_resource_init_and_close_more.py +193 -0
  64. linglong_web-0.0.1/tests/test_resource_init_from_conf_mapping.py +151 -0
  65. linglong_web-0.0.1/tests/test_resource_manager_internals.py +200 -0
  66. linglong_web-0.0.1/tests/test_response.py +47 -0
  67. linglong_web-0.0.1/tests/test_router.py +28 -0
  68. linglong_web-0.0.1/tests/test_scheduler.py +58 -0
  69. linglong_web-0.0.1/tests/test_server.py +402 -0
  70. linglong_web-0.0.1/tests/test_utils_context.py +28 -0
  71. linglong_web-0.0.1/tests/test_utils_signal_handler.py +259 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Victor Lai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,14 @@
1
+ global-exclude __pycache__ *.py[cod] *.pyo *.pyd .DS_Store
2
+ prune .pytest_cache
3
+ prune .mypy_cache
4
+ prune .ruff_cache
5
+ prune .venv
6
+ prune build
7
+ prune dist
8
+ exclude .coverage
9
+ exclude coverage.xml
10
+ include README.md
11
+ include LICENSE
12
+ include pyproject.toml
13
+ recursive-include linglong_web *.py
14
+ recursive-include linglong_web *.typed
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: linglong-web
3
+ Version: 0.0.1
4
+ Summary: Asynchronous FastAPI toolkit with service bootstrap, resource orchestration, and observability utilities
5
+ Author-email: Victor Lai <victor.lai@foxmail.com>
6
+ Maintainer-email: Victor Lai <victor.lai@foxmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/10000ms/linglong_web
9
+ Project-URL: Repository, https://github.com/10000ms/linglong_web
10
+ Project-URL: Documentation, https://github.com/10000ms/linglong_web/tree/master/docs
11
+ Project-URL: Bug Tracker, https://github.com/10000ms/linglong_web/issues
12
+ Keywords: fastapi,asyncio,microservices,service-registry,resource-manager,scheduler,http-client
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Framework :: FastAPI
22
+ Classifier: Framework :: AsyncIO
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: fastapi<1.0.0,>=0.115.0
27
+ Requires-Dist: uvicorn[standard]<1.0.0,>=0.30.0
28
+ Requires-Dist: aiohttp<4.0.0,>=3.9.0
29
+ Requires-Dist: aioclock<1.0.0,>=0.3.0
30
+ Requires-Dist: limits<7.0.0,>=3.0.0
31
+ Requires-Dist: redis<9.0.0,>=5.0.0
32
+ Requires-Dist: orjson<4.0.0,>=3.9.0
33
+ Requires-Dist: pydantic<3.0.0,>=2.0.0
34
+ Requires-Dist: nanoid<4.0.0,>=2.0.0
35
+ Requires-Dist: yarl<2.0.0,>=1.9.0
36
+ Provides-Extra: postgres
37
+ Requires-Dist: asyncpg<1.0.0,>=0.29.0; extra == "postgres"
38
+ Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.0; extra == "postgres"
39
+ Provides-Extra: mongo
40
+ Requires-Dist: pymongo<5.0.0,>=4.9.0; extra == "mongo"
41
+ Provides-Extra: rabbitmq
42
+ Requires-Dist: aio-pika<10.0.0,>=9.4.0; extra == "rabbitmq"
43
+ Provides-Extra: celery
44
+ Requires-Dist: celery<6.0.0,>=5.3.0; extra == "celery"
45
+ Provides-Extra: speedups
46
+ Requires-Dist: redis[hiredis]<9.0.0,>=5.0.0; extra == "speedups"
47
+ Provides-Extra: all
48
+ Requires-Dist: asyncpg<1.0.0,>=0.29.0; extra == "all"
49
+ Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.0; extra == "all"
50
+ Requires-Dist: pymongo<5.0.0,>=4.9.0; extra == "all"
51
+ Requires-Dist: aio-pika<10.0.0,>=9.4.0; extra == "all"
52
+ Requires-Dist: celery<6.0.0,>=5.3.0; extra == "all"
53
+ Requires-Dist: redis[hiredis]<9.0.0,>=5.0.0; extra == "all"
54
+ Provides-Extra: dev
55
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
56
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
57
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
58
+ Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
59
+ Requires-Dist: aiosqlite>=0.19.0; extra == "dev"
60
+ Requires-Dist: black>=24.0.0; extra == "dev"
61
+ Requires-Dist: isort>=5.13.0; extra == "dev"
62
+ Requires-Dist: mypy>=1.8.0; extra == "dev"
63
+ Requires-Dist: pre-commit>=3.6.0; extra == "dev"
64
+ Provides-Extra: docs
65
+ Requires-Dist: mkdocs>=1.5.0; extra == "docs"
66
+ Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
67
+ Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "docs"
68
+ Dynamic: license-file
69
+
70
+ # Linglong Web
71
+
72
+ [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
73
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
74
+ [![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
75
+
76
+ Linglong Web is a FastAPI toolkit for microservice scenarios, focusing on "simple startup, flexible extension, and complete observability".
77
+
78
+ 中文文档:see [README.zh-CN.md](README.zh-CN.md)
79
+
80
+ ## Links
81
+
82
+ - GitHub: https://github.com/10000ms/linglong_web
83
+ - Issues: https://github.com/10000ms/linglong_web/issues
84
+ - Changelog: https://github.com/10000ms/linglong_web/blob/master/CHANGELOG.md
85
+
86
+ ## Why this library
87
+
88
+ When building microservices with FastAPI, you often need:
89
+
90
+ - **Service lifecycle management** - startup, shutdown, health checks, graceful termination
91
+ - **Resource orchestration** - database connections, cache, message queues, schedulers
92
+ - **Observability** - request-id propagation, structured logging, rate limiting
93
+ - **Extensibility** - plugin hooks for service registration, remote config, etc.
94
+
95
+ Linglong Web provides all these out of the box as modular components.
96
+
97
+ ## Features
98
+
99
+ - **AppServer lifecycle** - Built-in middleware, error handling, health checks, and signal handling
100
+ - **Extension hooks** - `on_config_ready`, `on_app_created`, `on_startup`, `on_shutdown` for custom logic injection
101
+ - **Thread-safe config** - `LinglongConfig` with hot reload support
102
+ - **Resource management** - Unified initialization for PostgreSQL, Redis, MongoDB, RabbitMQ, Celery
103
+ - **HTTP client** - aiohttp wrapper with request-id propagation and unified error handling
104
+ - **Decorators** - Redis cache, rate limit, and distributed lock decorators
105
+ - **Scheduler** - aioclock integration for periodic tasks
106
+ - **Bilingual comments** - Chinese and English comments throughout the codebase
107
+
108
+ ## Installation
109
+
110
+ ```bash
111
+ # Core: FastAPI bootstrapper + HTTP client + scheduler + Redis-backed decorators
112
+ pip install linglong-web
113
+
114
+ # Add resource backends on demand
115
+ pip install "linglong-web[postgres]" # PostgreSQL (asyncpg + SQLAlchemy)
116
+ pip install "linglong-web[mongo]" # MongoDB (PyMongo async)
117
+ pip install "linglong-web[rabbitmq]" # RabbitMQ (aio-pika)
118
+ pip install "linglong-web[celery]" # Celery
119
+ pip install "linglong-web[all]" # everything
120
+ ```
121
+
122
+ `import linglong_web` always works with just the core install; a backend you
123
+ haven't installed only raises a clear error if you actually initialize it.
124
+
125
+ ## Quick Start
126
+
127
+ ```python
128
+ import asyncio
129
+
130
+ from linglong_web import LinglongConfigBase, init_config
131
+ from linglong_web import build_success_response
132
+ from linglong_web import BaseRoute, ServerRouter
133
+ from linglong_web import LinglongAppServer
134
+
135
+
136
+ class DevConfig(LinglongConfigBase):
137
+ """Development configuration"""
138
+ DEBUG = True
139
+ SERVICE_NAME = "demo-service"
140
+
141
+
142
+ router = ServerRouter()
143
+ router.initialize([
144
+ BaseRoute(
145
+ path="/ping",
146
+ method="GET",
147
+ handler=lambda: build_success_response({"pong": True}),
148
+ )
149
+ ])
150
+
151
+ init_config({"dev": DevConfig}, mode_name="dev")
152
+
153
+
154
+ async def main():
155
+ app_server = LinglongAppServer()
156
+ await app_server.initialize(
157
+ service_name="demo-service",
158
+ router=router.get_router(),
159
+ config_dict={"dev": DevConfig},
160
+ )
161
+ await app_server.start(host="0.0.0.0", port=8080)
162
+
163
+
164
+ if __name__ == "__main__":
165
+ asyncio.run(main())
166
+ ```
167
+
168
+ ## Module Overview
169
+
170
+ | Module | Description |
171
+ | --- | --- |
172
+ | `server` | FastAPI bootstrapper with middlewares & extension hooks |
173
+ | `server_extensions` | Lifecycle extension protocol for custom capabilities |
174
+ | `config` | Thread-safe config proxy with hot reload |
175
+ | `resource` | Unified resource bootstrapper (DB, Cache, MQ, Scheduler) |
176
+ | `http` | aiohttp client with request-id injection |
177
+ | `cacher` | Redis cache decorator |
178
+ | `limiter` | Rate limit decorator |
179
+ | `cluster_lock` | Distributed lock decorator |
180
+ | `scheduler` | aioclock helpers for periodic tasks |
181
+ | `utils` | Context, logging, signal handling, time utilities |
182
+
183
+ ## Extension Example
184
+
185
+ ```python
186
+ from linglong_web.server_extensions import BaseServerExtension
187
+
188
+
189
+ class RegistryExtension(BaseServerExtension):
190
+ """Example: custom service registration logic"""
191
+
192
+ def __init__(self, client):
193
+ self._client = client
194
+
195
+ async def on_startup(self, server):
196
+ payload = {"service": server.service_name, "instance": server.instance_id}
197
+ await self._client.register(payload)
198
+ server.register_shutdown_callback(lambda: self._client.deregister(payload))
199
+
200
+
201
+ extensions = [RegistryExtension(client)]
202
+ await app_server.initialize(
203
+ service_name="demo",
204
+ router=router.get_router(),
205
+ config_dict={"dev": DevConfig},
206
+ extensions=extensions,
207
+ )
208
+ ```
209
+
210
+ > Linglong no longer bundles service registration or remote config capabilities. Implement them in your business repository using extension hooks.
211
+
212
+ ## Testing & Coverage
213
+
214
+ ```bash
215
+ # Run tests with coverage
216
+ pytest tests/ -v --cov=linglong_web --cov-report=term-missing
217
+
218
+ # Or with PYTHONPATH
219
+ PYTHONPATH=. pytest tests/ -v --cov=linglong_web --cov-report=term-missing
220
+ ```
221
+
222
+ - All new modules should maintain **80%+** test coverage.
223
+ - Use `pytest-asyncio` and `pytest-mock` for fine-grained mocking of resources, rate limiters, and signal handlers.
224
+
225
+ ## Project Layout
226
+
227
+ ```
228
+ linglong_web/
229
+ ├── linglong_web/
230
+ │ ├── core/ # Core modules
231
+ │ │ ├── server.py # FastAPI bootstrapper
232
+ │ │ ├── config.py # Config proxy
233
+ │ │ ├── resource.py # Resource manager
234
+ │ │ ├── http.py # HTTP client
235
+ │ │ ├── cacher.py # Cache decorator
236
+ │ │ ├── limiter.py # Rate limit decorator
237
+ │ │ └── ...
238
+ │ └── utils/ # Utilities
239
+ ├── tests/ # Test suite
240
+ └── docs/ # Documentation
241
+ ```
242
+
243
+ ## Versioning
244
+
245
+ The package version is sourced from `linglong_web/__version__.py`.
246
+
247
+ ## License
248
+
249
+ MIT License. See LICENSE.
@@ -0,0 +1,180 @@
1
+ # Linglong Web
2
+
3
+ [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
4
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
5
+ [![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
6
+
7
+ Linglong Web is a FastAPI toolkit for microservice scenarios, focusing on "simple startup, flexible extension, and complete observability".
8
+
9
+ 中文文档:see [README.zh-CN.md](README.zh-CN.md)
10
+
11
+ ## Links
12
+
13
+ - GitHub: https://github.com/10000ms/linglong_web
14
+ - Issues: https://github.com/10000ms/linglong_web/issues
15
+ - Changelog: https://github.com/10000ms/linglong_web/blob/master/CHANGELOG.md
16
+
17
+ ## Why this library
18
+
19
+ When building microservices with FastAPI, you often need:
20
+
21
+ - **Service lifecycle management** - startup, shutdown, health checks, graceful termination
22
+ - **Resource orchestration** - database connections, cache, message queues, schedulers
23
+ - **Observability** - request-id propagation, structured logging, rate limiting
24
+ - **Extensibility** - plugin hooks for service registration, remote config, etc.
25
+
26
+ Linglong Web provides all these out of the box as modular components.
27
+
28
+ ## Features
29
+
30
+ - **AppServer lifecycle** - Built-in middleware, error handling, health checks, and signal handling
31
+ - **Extension hooks** - `on_config_ready`, `on_app_created`, `on_startup`, `on_shutdown` for custom logic injection
32
+ - **Thread-safe config** - `LinglongConfig` with hot reload support
33
+ - **Resource management** - Unified initialization for PostgreSQL, Redis, MongoDB, RabbitMQ, Celery
34
+ - **HTTP client** - aiohttp wrapper with request-id propagation and unified error handling
35
+ - **Decorators** - Redis cache, rate limit, and distributed lock decorators
36
+ - **Scheduler** - aioclock integration for periodic tasks
37
+ - **Bilingual comments** - Chinese and English comments throughout the codebase
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ # Core: FastAPI bootstrapper + HTTP client + scheduler + Redis-backed decorators
43
+ pip install linglong-web
44
+
45
+ # Add resource backends on demand
46
+ pip install "linglong-web[postgres]" # PostgreSQL (asyncpg + SQLAlchemy)
47
+ pip install "linglong-web[mongo]" # MongoDB (PyMongo async)
48
+ pip install "linglong-web[rabbitmq]" # RabbitMQ (aio-pika)
49
+ pip install "linglong-web[celery]" # Celery
50
+ pip install "linglong-web[all]" # everything
51
+ ```
52
+
53
+ `import linglong_web` always works with just the core install; a backend you
54
+ haven't installed only raises a clear error if you actually initialize it.
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ import asyncio
60
+
61
+ from linglong_web import LinglongConfigBase, init_config
62
+ from linglong_web import build_success_response
63
+ from linglong_web import BaseRoute, ServerRouter
64
+ from linglong_web import LinglongAppServer
65
+
66
+
67
+ class DevConfig(LinglongConfigBase):
68
+ """Development configuration"""
69
+ DEBUG = True
70
+ SERVICE_NAME = "demo-service"
71
+
72
+
73
+ router = ServerRouter()
74
+ router.initialize([
75
+ BaseRoute(
76
+ path="/ping",
77
+ method="GET",
78
+ handler=lambda: build_success_response({"pong": True}),
79
+ )
80
+ ])
81
+
82
+ init_config({"dev": DevConfig}, mode_name="dev")
83
+
84
+
85
+ async def main():
86
+ app_server = LinglongAppServer()
87
+ await app_server.initialize(
88
+ service_name="demo-service",
89
+ router=router.get_router(),
90
+ config_dict={"dev": DevConfig},
91
+ )
92
+ await app_server.start(host="0.0.0.0", port=8080)
93
+
94
+
95
+ if __name__ == "__main__":
96
+ asyncio.run(main())
97
+ ```
98
+
99
+ ## Module Overview
100
+
101
+ | Module | Description |
102
+ | --- | --- |
103
+ | `server` | FastAPI bootstrapper with middlewares & extension hooks |
104
+ | `server_extensions` | Lifecycle extension protocol for custom capabilities |
105
+ | `config` | Thread-safe config proxy with hot reload |
106
+ | `resource` | Unified resource bootstrapper (DB, Cache, MQ, Scheduler) |
107
+ | `http` | aiohttp client with request-id injection |
108
+ | `cacher` | Redis cache decorator |
109
+ | `limiter` | Rate limit decorator |
110
+ | `cluster_lock` | Distributed lock decorator |
111
+ | `scheduler` | aioclock helpers for periodic tasks |
112
+ | `utils` | Context, logging, signal handling, time utilities |
113
+
114
+ ## Extension Example
115
+
116
+ ```python
117
+ from linglong_web.server_extensions import BaseServerExtension
118
+
119
+
120
+ class RegistryExtension(BaseServerExtension):
121
+ """Example: custom service registration logic"""
122
+
123
+ def __init__(self, client):
124
+ self._client = client
125
+
126
+ async def on_startup(self, server):
127
+ payload = {"service": server.service_name, "instance": server.instance_id}
128
+ await self._client.register(payload)
129
+ server.register_shutdown_callback(lambda: self._client.deregister(payload))
130
+
131
+
132
+ extensions = [RegistryExtension(client)]
133
+ await app_server.initialize(
134
+ service_name="demo",
135
+ router=router.get_router(),
136
+ config_dict={"dev": DevConfig},
137
+ extensions=extensions,
138
+ )
139
+ ```
140
+
141
+ > Linglong no longer bundles service registration or remote config capabilities. Implement them in your business repository using extension hooks.
142
+
143
+ ## Testing & Coverage
144
+
145
+ ```bash
146
+ # Run tests with coverage
147
+ pytest tests/ -v --cov=linglong_web --cov-report=term-missing
148
+
149
+ # Or with PYTHONPATH
150
+ PYTHONPATH=. pytest tests/ -v --cov=linglong_web --cov-report=term-missing
151
+ ```
152
+
153
+ - All new modules should maintain **80%+** test coverage.
154
+ - Use `pytest-asyncio` and `pytest-mock` for fine-grained mocking of resources, rate limiters, and signal handlers.
155
+
156
+ ## Project Layout
157
+
158
+ ```
159
+ linglong_web/
160
+ ├── linglong_web/
161
+ │ ├── core/ # Core modules
162
+ │ │ ├── server.py # FastAPI bootstrapper
163
+ │ │ ├── config.py # Config proxy
164
+ │ │ ├── resource.py # Resource manager
165
+ │ │ ├── http.py # HTTP client
166
+ │ │ ├── cacher.py # Cache decorator
167
+ │ │ ├── limiter.py # Rate limit decorator
168
+ │ │ └── ...
169
+ │ └── utils/ # Utilities
170
+ ├── tests/ # Test suite
171
+ └── docs/ # Documentation
172
+ ```
173
+
174
+ ## Versioning
175
+
176
+ The package version is sourced from `linglong_web/__version__.py`.
177
+
178
+ ## License
179
+
180
+ MIT License. See LICENSE.
@@ -0,0 +1,132 @@
1
+ """Linglong Web – 异步 FastAPI 工具集 / Asynchronous FastAPI toolkit."""
2
+ from .__version__ import (
3
+ __author__,
4
+ __description__,
5
+ __license__,
6
+ __version__,
7
+ )
8
+
9
+ from .core.auth import login_required
10
+ from .core.cacher import cacher
11
+ from .core.cluster_lock import cluster_lock
12
+ from .core.config import (
13
+ LinglongConfigBase,
14
+ LinglongConfig,
15
+ init_config,
16
+ )
17
+ from .core.constants import LinglongConst
18
+ from .core.cors import allow_cors_specific
19
+ from .core.db import TableBase
20
+ from .core.ddl_manager import (
21
+ AutoDDLManager,
22
+ DDLManagerConfig,
23
+ )
24
+ from .core.http import (
25
+ HTTPClientConfig,
26
+ AsyncHTTPClient,
27
+ LinglongHTTPError,
28
+ http_client,
29
+ )
30
+ from .core.limiter import LimiterGuard, limiter
31
+ from .core.limiter_local import (
32
+ limiter_local,
33
+ reset_limiter,
34
+ get_limiter_stats,
35
+ )
36
+ from .core.resource import (
37
+ ResourceManager,
38
+ Rmanager,
39
+ DEFAULT_DB_ALIAS,
40
+ init_resources,
41
+ close_resources,
42
+ )
43
+ from .core.response import (
44
+ APIError,
45
+ APIResponse,
46
+ build_api_response,
47
+ build_success_response,
48
+ build_error_response,
49
+ )
50
+ from .core.router import (
51
+ BaseRoute,
52
+ ServerRouter,
53
+ )
54
+ from .core.scheduler import (
55
+ BaseScheduler,
56
+ SchedulerGroup,
57
+ to_group,
58
+ )
59
+ from .core.server import LinglongAppServer
60
+ from .core.server_extensions import BaseServerExtension
61
+ from .core.schemas import (
62
+ PgsqlConfig,
63
+ RedisConfig,
64
+ RabbitMQConfig,
65
+ MongoConfig,
66
+ CeleryConfig,
67
+ ResourceInitConfig,
68
+ )
69
+ from .core.errors import (
70
+ ErrorCode,
71
+ ErrorMsg,
72
+ LinglongHTTPException,
73
+ LoginRequiredError,
74
+ LimiterError,
75
+ ClusterLockError,
76
+ )
77
+
78
+ __all__ = [
79
+ "login_required",
80
+ "cacher",
81
+ "cluster_lock",
82
+ "LinglongConfigBase",
83
+ "LinglongConfig",
84
+ "LinglongConst",
85
+ "init_config",
86
+ "allow_cors_specific",
87
+ "TableBase",
88
+ "AutoDDLManager",
89
+ "DDLManagerConfig",
90
+ "BaseRoute",
91
+ "ServerRouter",
92
+ "APIError",
93
+ "APIResponse",
94
+ "build_api_response",
95
+ "build_success_response",
96
+ "build_error_response",
97
+ "HTTPClientConfig",
98
+ "AsyncHTTPClient",
99
+ "LinglongHTTPError",
100
+ "http_client",
101
+ "LimiterGuard",
102
+ "limiter",
103
+ "limiter_local",
104
+ "reset_limiter",
105
+ "get_limiter_stats",
106
+ "ResourceManager",
107
+ "Rmanager",
108
+ "DEFAULT_DB_ALIAS",
109
+ "init_resources",
110
+ "close_resources",
111
+ "BaseScheduler",
112
+ "SchedulerGroup",
113
+ "to_group",
114
+ "LinglongAppServer",
115
+ "BaseServerExtension",
116
+ "PgsqlConfig",
117
+ "RedisConfig",
118
+ "RabbitMQConfig",
119
+ "MongoConfig",
120
+ "CeleryConfig",
121
+ "ResourceInitConfig",
122
+ "ErrorCode",
123
+ "ErrorMsg",
124
+ "LinglongHTTPException",
125
+ "LoginRequiredError",
126
+ "LimiterError",
127
+ "ClusterLockError",
128
+ "__version__",
129
+ "__author__",
130
+ "__license__",
131
+ "__description__",
132
+ ]
@@ -0,0 +1,9 @@
1
+ """Linglong Web metadata / 版本信息模块."""
2
+
3
+ __version__ = "0.0.1"
4
+ __author__ = "Victor Lai"
5
+ __license__ = "MIT"
6
+ __description__ = (
7
+ "Asynchronous FastAPI toolkit providing service bootstrap, registry hooks, resource orchestration, "
8
+ "and observability helpers"
9
+ )
@@ -0,0 +1,54 @@
1
+ """Linglong Web – 异步 FastAPI 工具集 / Asynchronous FastAPI toolkit."""
2
+ from .auth import login_required
3
+ from .cacher import cacher
4
+ from .cluster_lock import cluster_lock
5
+ from .config import (
6
+ LinglongConfigBase,
7
+ LinglongConfig,
8
+ LinglongConfigProxy,
9
+ init_config,
10
+ )
11
+ from .constants import LinglongConst
12
+ from .cors import allow_cors_specific
13
+ from .db import TableBase
14
+ from .ddl_manager import (
15
+ AutoDDLManager,
16
+ DDLManagerConfig,
17
+ )
18
+ from .http import (
19
+ HTTPClientConfig,
20
+ AsyncHTTPClient,
21
+ LinglongHTTPError,
22
+ http_client,
23
+ )
24
+ from .limiter import (
25
+ LimiterGuard,
26
+ limiter,
27
+ )
28
+ from .limiter_local import (
29
+ limiter_local,
30
+ reset_limiter,
31
+ get_limiter_stats,
32
+ )
33
+ from .resource import (
34
+ ResourceManager,
35
+ Rmanager,
36
+ DEFAULT_DB_ALIAS,
37
+ init_resources,
38
+ close_resources,
39
+ )
40
+ from .response import (
41
+ APIError,
42
+ APIResponse,
43
+ build_api_response,
44
+ build_success_response,
45
+ build_error_response,
46
+ )
47
+ from .router import BaseRoute, ServerRouter
48
+ from .scheduler import (
49
+ BaseScheduler,
50
+ SchedulerGroup,
51
+ to_group,
52
+ )
53
+ from .server import LinglongAppServer
54
+ from .server_extensions import BaseServerExtension
@@ -0,0 +1,31 @@
1
+ """Authentication helpers shared across Linglong services.
2
+
3
+ 提供 Linglong 服务统一的认证装饰器工具。
4
+ """
5
+ from functools import wraps
6
+ from typing import (
7
+ Awaitable,
8
+ Callable,
9
+ )
10
+
11
+ from .errors import LoginRequiredError
12
+ from .types import P, R
13
+ from ..utils.context import get_context_user_id
14
+ from ..utils.log import logger
15
+
16
+
17
+ def login_required(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]:
18
+ """Ensure the current request has a valid login user id.
19
+
20
+ 确保当前请求已经完成登录校验,如果缺少用户信息则抛出 ``LoginRequiredError``。
21
+ """
22
+
23
+ @wraps(func)
24
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
25
+ user_id = get_context_user_id()
26
+ if user_id is not None and isinstance(user_id, int):
27
+ return await func(*args, **kwargs)
28
+ logger.warning("user is not login")
29
+ raise LoginRequiredError()
30
+
31
+ return wrapper