tina4-python 3.13.22__tar.gz → 3.13.23__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.
- {tina4_python-3.13.22 → tina4_python-3.13.23}/PKG-INFO +1 -1
- {tina4_python-3.13.22 → tina4_python-3.13.23}/pyproject.toml +1 -1
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/CLAUDE.md +2 -2
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/__init__.py +1 -1
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/server.py +9 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/connection.py +47 -3
- {tina4_python-3.13.22 → tina4_python-3.13.23}/.gitignore +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/README.md +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/env.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/js/tina4-dev-admin.js +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -1836,10 +1836,10 @@ async def dashboard(request, response):
|
|
|
1836
1836
|
## v3 Features Summary
|
|
1837
1837
|
|
|
1838
1838
|
- **55 built-in features**, zero third-party dependencies
|
|
1839
|
-
- **2,
|
|
1839
|
+
- **2,866 tests** passing across all modules
|
|
1840
1840
|
- **Production server auto-detect**: `tina4python serve --production` auto-installs uvicorn
|
|
1841
1841
|
- **`tina4python generate`**: model, route, migration, middleware scaffolding
|
|
1842
|
-
- **Database**: 5 engines (SQLite, PostgreSQL, MySQL, MSSQL, Firebird), query caching (`
|
|
1842
|
+
- **Database**: 5 engines (SQLite, PostgreSQL, MySQL, MSSQL, Firebird), DB query caching — request-scoped auto cache **on by default** (`TINA4_AUTO_CACHING=true`, TTL `TINA4_AUTO_CACHING_TTL=5`s) dedupes identical reads within a request and flushes on writes; persistent cross-request cache opt-in via `TINA4_DB_CACHE=true` (TTL `TINA4_DB_CACHE_TTL=30`s); `cache_stats()` reports `mode` (request/persistent/off), `cache_clear()`
|
|
1843
1843
|
- **Sessions**: 4 backends (file, Redis/Valkey, MongoDB, database)
|
|
1844
1844
|
- **Queue**: file/RabbitMQ/Kafka/MongoDB backends, configured via env vars
|
|
1845
1845
|
- **Cache**: memory/Redis/file backends
|
|
@@ -1563,6 +1563,15 @@ async def handle(request: Request) -> Response:
|
|
|
1563
1563
|
if swagger_resp is not None:
|
|
1564
1564
|
return swagger_resp
|
|
1565
1565
|
|
|
1566
|
+
# Reset the request-scoped query cache so identical SELECTs are deduped
|
|
1567
|
+
# within this request but never served across requests (zero cross-request
|
|
1568
|
+
# staleness). No-op when TINA4_DB_CACHE=true (persistent mode) or disabled.
|
|
1569
|
+
try:
|
|
1570
|
+
from tina4_python.database.connection import Database as _Db
|
|
1571
|
+
_Db.reset_request_caches()
|
|
1572
|
+
except Exception:
|
|
1573
|
+
pass
|
|
1574
|
+
|
|
1566
1575
|
# Route matching and dispatch
|
|
1567
1576
|
route, params = Router.match(request.method, request.path)
|
|
1568
1577
|
|
|
@@ -13,6 +13,7 @@ import hashlib
|
|
|
13
13
|
import os
|
|
14
14
|
import threading
|
|
15
15
|
import time
|
|
16
|
+
import weakref
|
|
16
17
|
from urllib.parse import urlparse
|
|
17
18
|
from tina4_python.database.adapter import DatabaseAdapter, DatabaseResult
|
|
18
19
|
|
|
@@ -139,6 +140,10 @@ class Database:
|
|
|
139
140
|
operations to the adapter. This is what the rest of the framework uses.
|
|
140
141
|
"""
|
|
141
142
|
|
|
143
|
+
#: Live Database instances, so the request dispatcher can reset the
|
|
144
|
+
#: request-scoped query cache on every connection at the start of a request.
|
|
145
|
+
_instances: "weakref.WeakSet[Database]" = weakref.WeakSet()
|
|
146
|
+
|
|
142
147
|
@classmethod
|
|
143
148
|
def get_connection(cls, url: str = None, username: str = "", password: str = "", pool: int = 0, **kwargs) -> "Database":
|
|
144
149
|
"""Open a database connection — convention name matching SQLAlchemy
|
|
@@ -205,14 +210,27 @@ class Database:
|
|
|
205
210
|
# pool can't rotate mid-transaction and silently break atomicity.
|
|
206
211
|
self._tx_local = threading.local()
|
|
207
212
|
|
|
208
|
-
# Query cache
|
|
213
|
+
# Query cache. One store, two layers:
|
|
214
|
+
# • request-scoped (DEFAULT ON) — dedupes identical SELECTs to protect
|
|
215
|
+
# the DB from rapid repeat reads. Cleared at the start of every HTTP
|
|
216
|
+
# request (so it never serves data across requests) and on any write,
|
|
217
|
+
# with a short safety TTL for non-request contexts (scripts/workers).
|
|
218
|
+
# Off-switch: TINA4_AUTO_CACHING=false.
|
|
219
|
+
# • persistent (opt-in, TINA4_DB_CACHE=true) — cross-request TTL cache
|
|
220
|
+
# that is NOT cleared per request; entries expire by TINA4_DB_CACHE_TTL.
|
|
209
221
|
from tina4_python.dotenv import is_truthy
|
|
210
|
-
self.
|
|
211
|
-
self.
|
|
222
|
+
self._cache_persistent: bool = is_truthy(os.environ.get("TINA4_DB_CACHE", "false"))
|
|
223
|
+
self._cache_request_scoped: bool = is_truthy(os.environ.get("TINA4_AUTO_CACHING", "true"))
|
|
224
|
+
self._cache_enabled: bool = self._cache_persistent or self._cache_request_scoped
|
|
225
|
+
if self._cache_persistent:
|
|
226
|
+
self._cache_ttl: int = int(os.environ.get("TINA4_DB_CACHE_TTL", "30"))
|
|
227
|
+
else:
|
|
228
|
+
self._cache_ttl = int(os.environ.get("TINA4_AUTO_CACHING_TTL", "5"))
|
|
212
229
|
self._query_cache: dict[str, tuple[float, object]] = {} # key -> (expires_at, result)
|
|
213
230
|
self._cache_hits: int = 0
|
|
214
231
|
self._cache_misses: int = 0
|
|
215
232
|
self._cache_lock = threading.Lock()
|
|
233
|
+
Database._instances.add(self)
|
|
216
234
|
|
|
217
235
|
def _create_adapter(self) -> DatabaseAdapter:
|
|
218
236
|
"""Select adapter based on URL scheme."""
|
|
@@ -326,11 +344,37 @@ class Database:
|
|
|
326
344
|
with self._cache_lock:
|
|
327
345
|
self._query_cache.clear()
|
|
328
346
|
|
|
347
|
+
def cache_new_request(self):
|
|
348
|
+
"""Clear the request-scoped query cache at the start of an HTTP request.
|
|
349
|
+
|
|
350
|
+
No-op in persistent mode (TINA4_DB_CACHE=true) so cross-request entries
|
|
351
|
+
survive up to their TTL. Cumulative hit/miss counters are preserved.
|
|
352
|
+
"""
|
|
353
|
+
if self._cache_request_scoped and not self._cache_persistent:
|
|
354
|
+
with self._cache_lock:
|
|
355
|
+
self._query_cache.clear()
|
|
356
|
+
|
|
357
|
+
@classmethod
|
|
358
|
+
def reset_request_caches(cls):
|
|
359
|
+
"""Clear the request-scoped query cache on every live Database instance.
|
|
360
|
+
|
|
361
|
+
The request dispatcher calls this at the start of each HTTP request so
|
|
362
|
+
request-scoped caching never serves rows across requests (zero
|
|
363
|
+
cross-request staleness). Persistent-mode connections are left alone.
|
|
364
|
+
"""
|
|
365
|
+
for inst in list(cls._instances):
|
|
366
|
+
try:
|
|
367
|
+
inst.cache_new_request()
|
|
368
|
+
except Exception:
|
|
369
|
+
pass
|
|
370
|
+
|
|
329
371
|
def cache_stats(self) -> dict:
|
|
330
372
|
"""Return query cache statistics."""
|
|
331
373
|
with self._cache_lock:
|
|
332
374
|
return {
|
|
333
375
|
"enabled": self._cache_enabled,
|
|
376
|
+
"mode": ("persistent" if self._cache_persistent
|
|
377
|
+
else "request" if self._cache_request_scoped else "off"),
|
|
334
378
|
"hits": self._cache_hits,
|
|
335
379
|
"misses": self._cache_misses,
|
|
336
380
|
"size": len(self._query_cache),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/images/tina4-logo-icon.webp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/public/swagger/oauth2-redirect.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/queue_backends/rabbitmq_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/templates/docker/python/Dockerfile
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.22 → tina4_python-3.13.23}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|