Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
chatbot-canifa-feedback
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
chatbot-canifa-feedback
Commits
906e5cc3
Commit
906e5cc3
authored
Apr 28, 2026
by
Vũ Hoàng Anh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: QA Gatekeeper audit fixes for backend concurrency and thread-safety
parent
24d87940
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
21 additions
and
18 deletions
+21
-18
router.py
backend/api/fashion_matches/router.py
+5
-5
starrocks_connection.py
backend/common/starrocks_connection.py
+16
-13
No files found.
backend/api/fashion_matches/router.py
View file @
906e5cc3
...
...
@@ -269,7 +269,7 @@ def _get_colors_by_group(group: str, color_groups_map: dict, exclude: str | None
@
router
.
get
(
"/{code}"
)
async
def
get_fashion_matches
(
code
:
str
):
def
get_fashion_matches
(
code
:
str
):
from
worker.stylist_engine
import
StylistEngine
engine
=
StylistEngine
()
...
...
@@ -426,7 +426,7 @@ async def color_logic(req: ColorLogicRequest):
@
router
.
post
(
"/outfit-suggest"
)
async
def
outfit_suggest
(
req
:
OutfitSuggestRequest
):
def
outfit_suggest
(
req
:
OutfitSuggestRequest
):
try
:
rules
=
_load_rules
()
color_keys
=
rules
.
get
(
"color_keys"
,
{})
...
...
@@ -531,7 +531,7 @@ class ScoreTestRequest(BaseModel):
@
router
.
post
(
"/score-test"
)
async
def
score_test
(
req
:
ScoreTestRequest
):
def
score_test
(
req
:
ScoreTestRequest
):
try
:
from
worker.stylist_engine
import
StylistEngine
...
...
@@ -569,7 +569,7 @@ async def score_test(req: ScoreTestRequest):
@
router
.
get
(
"/audit/tag-coverage"
)
async
def
audit_tag_coverage
(
limit
:
int
=
Query
(
300
,
ge
=
20
,
le
=
2000
),
q
:
str
=
""
):
def
audit_tag_coverage
(
limit
:
int
=
Query
(
300
,
ge
=
20
,
le
=
2000
),
q
:
str
=
""
):
"""Audit product tags vs rules coverage for data QA."""
try
:
from
worker.stylist_engine
import
StylistEngine
...
...
@@ -745,7 +745,7 @@ async def audit_tag_coverage(limit: int = Query(300, ge=20, le=2000), q: str = "
# --- Rules Framework HTML View ---
@
router
.
get
(
"/rules/view"
)
async
def
rules_view
():
def
rules_view
():
from
collections
import
defaultdict
from
fastapi.responses
import
HTMLResponse
...
...
backend/common/starrocks_connection.py
View file @
906e5cc3
...
...
@@ -6,6 +6,7 @@ Based on chatbot-rsa pattern
import
asyncio
import
logging
import
os
import
threading
from
typing
import
Any
import
aiomysql
...
...
@@ -47,8 +48,8 @@ get_db_connection = _manager.get_connection
class
StarRocksConnection
:
#
Shared connection (Singleton-like behavior) for all instance
s
_
shared_conn
=
None
#
Use thread-local storage to ensure thread-safety across FastAPI sync worker
s
_
thread_local
=
threading
.
local
()
def
__init__
(
self
,
...
...
@@ -71,16 +72,17 @@ class StarRocksConnection:
"""
Establish or reuse persistent connection.
"""
# 1. Try to reuse existing shared connection
if
StarRocksConnection
.
_shared_conn
and
StarRocksConnection
.
_shared_conn
.
open
:
# 1. Try to reuse existing thread-local connection
conn
=
getattr
(
StarRocksConnection
.
_thread_local
,
'conn'
,
None
)
if
conn
and
conn
.
open
:
try
:
# Ping to check if alive, reconnect if needed
StarRocksConnection
.
_shared_
conn
.
ping
(
reconnect
=
True
)
self
.
conn
=
StarRocksConnection
.
_shared_
conn
conn
.
ping
(
reconnect
=
True
)
self
.
conn
=
conn
return
self
.
conn
except
Exception
as
e
:
logger
.
warning
(
f
"⚠️ Connection lost, reconnecting: {e}"
)
StarRocksConnection
.
_
shared_
conn
=
None
StarRocksConnection
.
_
thread_local
.
conn
=
None
# 2. Create new connection if needed
print
(
f
" [DB] 🔌 Đang kết nối StarRocks (New Session): {self.host}:{self.port}..."
)
...
...
@@ -101,8 +103,8 @@ class StarRocksConnection:
print
(
" [DB] ✅ Kết nối thành công."
)
logger
.
info
(
"✅ Connected to StarRocks"
)
# Save to
class
variable
StarRocksConnection
.
_
shared_
conn
=
new_conn
# Save to
thread-local
variable
StarRocksConnection
.
_
thread_local
.
conn
=
new_conn
self
.
conn
=
new_conn
except
Exception
as
e
:
...
...
@@ -136,7 +138,7 @@ class StarRocksConnection:
print
(
f
" [DB] ❌ Lỗi truy vấn: {e!s}"
)
logger
.
error
(
f
"❌ StarRocks query error: {e}"
)
# Incase of query error due to connection, invalidate it
StarRocksConnection
.
_
shared_
conn
=
None
StarRocksConnection
.
_
thread_local
.
conn
=
None
raise
# FINALLY BLOCK REMOVED: Do NOT close connection
...
...
@@ -264,7 +266,8 @@ class StarRocksConnection:
def
close
(
self
):
"""Explicitly close if needed (e.g. app shutdown)"""
if
StarRocksConnection
.
_shared_conn
and
StarRocksConnection
.
_shared_conn
.
open
:
StarRocksConnection
.
_shared_conn
.
close
()
StarRocksConnection
.
_shared_conn
=
None
conn
=
getattr
(
StarRocksConnection
.
_thread_local
,
'conn'
,
None
)
if
conn
and
conn
.
open
:
conn
.
close
()
StarRocksConnection
.
_thread_local
.
conn
=
None
self
.
conn
=
None
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment