mcp-code-indexer 4.2.17__py3-none-any.whl → 4.2.18__py3-none-any.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.
- mcp_code_indexer/database/database.py +52 -2
- mcp_code_indexer/logging_config.py +16 -9
- {mcp_code_indexer-4.2.17.dist-info → mcp_code_indexer-4.2.18.dist-info}/METADATA +3 -3
- {mcp_code_indexer-4.2.17.dist-info → mcp_code_indexer-4.2.18.dist-info}/RECORD +7 -7
- {mcp_code_indexer-4.2.17.dist-info → mcp_code_indexer-4.2.18.dist-info}/WHEEL +0 -0
- {mcp_code_indexer-4.2.17.dist-info → mcp_code_indexer-4.2.18.dist-info}/entry_points.txt +0 -0
- {mcp_code_indexer-4.2.17.dist-info → mcp_code_indexer-4.2.18.dist-info}/licenses/LICENSE +0 -0
|
@@ -409,14 +409,30 @@ class DatabaseManager:
|
|
|
409
409
|
operation_name: Name of the operation for monitoring
|
|
410
410
|
timeout_seconds: Transaction timeout in seconds
|
|
411
411
|
"""
|
|
412
|
+
import time
|
|
413
|
+
acquire_start = time.monotonic()
|
|
412
414
|
async with self.get_write_connection_with_retry(operation_name) as conn:
|
|
415
|
+
write_lock_time = time.monotonic() - acquire_start
|
|
416
|
+
logger.debug(
|
|
417
|
+
f"[{operation_name}] Write lock acquired in {write_lock_time*1000:.1f}ms"
|
|
418
|
+
)
|
|
413
419
|
try:
|
|
414
420
|
# Start immediate transaction with timeout
|
|
421
|
+
begin_start = time.monotonic()
|
|
415
422
|
await asyncio.wait_for(
|
|
416
423
|
conn.execute("BEGIN IMMEDIATE"), timeout=timeout_seconds
|
|
417
424
|
)
|
|
425
|
+
begin_time = time.monotonic() - begin_start
|
|
426
|
+
logger.debug(
|
|
427
|
+
f"[{operation_name}] BEGIN IMMEDIATE completed in {begin_time*1000:.1f}ms"
|
|
428
|
+
)
|
|
418
429
|
yield conn
|
|
430
|
+
commit_start = time.monotonic()
|
|
419
431
|
await conn.commit()
|
|
432
|
+
commit_time = time.monotonic() - commit_start
|
|
433
|
+
logger.debug(
|
|
434
|
+
f"[{operation_name}] COMMIT completed in {commit_time*1000:.1f}ms"
|
|
435
|
+
)
|
|
420
436
|
except asyncio.TimeoutError:
|
|
421
437
|
logger.warning(
|
|
422
438
|
(
|
|
@@ -476,13 +492,34 @@ class DatabaseManager:
|
|
|
476
492
|
|
|
477
493
|
async def execute_transaction() -> Any:
|
|
478
494
|
"""Inner function to execute transaction - retried by executor."""
|
|
495
|
+
import time
|
|
496
|
+
start_time = time.monotonic()
|
|
497
|
+
logger.debug(
|
|
498
|
+
f"[{operation_name}] Starting transaction "
|
|
499
|
+
f"(timeout={timeout_seconds}s, pool_size={len(self._connection_pool)})"
|
|
500
|
+
)
|
|
479
501
|
try:
|
|
480
502
|
async with self.get_immediate_transaction(
|
|
481
503
|
operation_name, timeout_seconds
|
|
482
504
|
) as conn:
|
|
505
|
+
lock_acquired_time = time.monotonic()
|
|
506
|
+
logger.debug(
|
|
507
|
+
f"[{operation_name}] Lock acquired in "
|
|
508
|
+
f"{(lock_acquired_time - start_time)*1000:.1f}ms"
|
|
509
|
+
)
|
|
483
510
|
result = await operation_func(conn)
|
|
511
|
+
exec_time = time.monotonic()
|
|
512
|
+
logger.debug(
|
|
513
|
+
f"[{operation_name}] Operation executed in "
|
|
514
|
+
f"{(exec_time - lock_acquired_time)*1000:.1f}ms"
|
|
515
|
+
)
|
|
484
516
|
|
|
485
517
|
# Record successful operation metrics
|
|
518
|
+
total_time = time.monotonic() - start_time
|
|
519
|
+
logger.debug(
|
|
520
|
+
f"[{operation_name}] Transaction completed successfully "
|
|
521
|
+
f"in {total_time*1000:.1f}ms"
|
|
522
|
+
)
|
|
486
523
|
if self._metrics_collector:
|
|
487
524
|
self._metrics_collector.record_operation(
|
|
488
525
|
operation_name,
|
|
@@ -494,17 +531,26 @@ class DatabaseManager:
|
|
|
494
531
|
return result
|
|
495
532
|
|
|
496
533
|
except aiosqlite.OperationalError as e:
|
|
497
|
-
|
|
534
|
+
elapsed = time.monotonic() - start_time
|
|
498
535
|
error_msg = str(e).lower()
|
|
536
|
+
logger.debug(
|
|
537
|
+
f"[{operation_name}] OperationalError after {elapsed*1000:.1f}ms: {e}"
|
|
538
|
+
)
|
|
499
539
|
if self._metrics_collector and "locked" in error_msg:
|
|
500
540
|
self._metrics_collector.record_locking_event(operation_name, str(e))
|
|
501
541
|
|
|
502
542
|
# For retryable errors (locked/busy), re-raise the ORIGINAL error
|
|
503
543
|
# so tenacity can retry. Only classify non-retryable errors.
|
|
504
544
|
if "locked" in error_msg or "busy" in error_msg:
|
|
545
|
+
logger.debug(
|
|
546
|
+
f"[{operation_name}] Retryable error, will retry: {e}"
|
|
547
|
+
)
|
|
505
548
|
raise # Let tenacity retry this
|
|
506
549
|
|
|
507
550
|
# Non-retryable OperationalError - classify and raise
|
|
551
|
+
logger.warning(
|
|
552
|
+
f"[{operation_name}] Non-retryable OperationalError: {e}"
|
|
553
|
+
)
|
|
508
554
|
classified_error = classify_sqlite_error(e, operation_name)
|
|
509
555
|
if self._metrics_collector:
|
|
510
556
|
self._metrics_collector.record_operation(
|
|
@@ -516,7 +562,11 @@ class DatabaseManager:
|
|
|
516
562
|
raise classified_error
|
|
517
563
|
|
|
518
564
|
except asyncio.TimeoutError as e:
|
|
519
|
-
|
|
565
|
+
elapsed = time.monotonic() - start_time
|
|
566
|
+
logger.warning(
|
|
567
|
+
f"[{operation_name}] Timeout after {elapsed*1000:.1f}ms "
|
|
568
|
+
f"waiting for database lock (timeout={timeout_seconds}s)"
|
|
569
|
+
)
|
|
520
570
|
if self._metrics_collector:
|
|
521
571
|
self._metrics_collector.record_locking_event(
|
|
522
572
|
operation_name, "timeout waiting for lock"
|
|
@@ -81,22 +81,29 @@ def setup_logging(
|
|
|
81
81
|
root_logger.warning(f"Failed to set up file logging: {e}")
|
|
82
82
|
|
|
83
83
|
# Configure specific loggers
|
|
84
|
+
effective_level = getattr(logging, log_level.upper())
|
|
84
85
|
|
|
85
|
-
# Quiet down noisy libraries
|
|
86
|
+
# Quiet down noisy libraries (always WARNING+)
|
|
86
87
|
logging.getLogger("aiosqlite").setLevel(logging.WARNING)
|
|
87
88
|
logging.getLogger("tiktoken").setLevel(logging.WARNING)
|
|
88
89
|
|
|
89
|
-
# MCP specific loggers
|
|
90
|
+
# MCP specific loggers - respect the configured log level
|
|
90
91
|
mcp_logger = logging.getLogger("mcp")
|
|
91
|
-
mcp_logger.setLevel(
|
|
92
|
+
mcp_logger.setLevel(effective_level)
|
|
92
93
|
|
|
93
|
-
# Database logger
|
|
94
|
-
db_logger = logging.getLogger("
|
|
95
|
-
db_logger.setLevel(
|
|
94
|
+
# Database logger - respect the configured log level
|
|
95
|
+
db_logger = logging.getLogger("mcp_code_indexer.database")
|
|
96
|
+
db_logger.setLevel(effective_level)
|
|
96
97
|
|
|
97
|
-
#
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
# Also set the old logger names for backwards compatibility
|
|
99
|
+
logging.getLogger("src.database").setLevel(effective_level)
|
|
100
|
+
|
|
101
|
+
# Server logger - respect the configured log level
|
|
102
|
+
server_logger = logging.getLogger("mcp_code_indexer.server")
|
|
103
|
+
server_logger.setLevel(effective_level)
|
|
104
|
+
|
|
105
|
+
# Also set the old logger names for backwards compatibility
|
|
106
|
+
logging.getLogger("src.server").setLevel(effective_level)
|
|
100
107
|
|
|
101
108
|
return root_logger
|
|
102
109
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-code-indexer
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.18
|
|
4
4
|
Summary: MCP server that tracks file descriptions across codebases, enabling AI agents to efficiently navigate and understand code through searchable summaries and token-aware overviews.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -49,8 +49,8 @@ Description-Content-Type: text/markdown
|
|
|
49
49
|
|
|
50
50
|
# MCP Code Indexer 🚀
|
|
51
51
|
|
|
52
|
-
[](https://badge.fury.io/py/mcp-code-indexer)
|
|
53
|
+
[](https://pypi.org/project/mcp-code-indexer/)
|
|
54
54
|
[](https://opensource.org/licenses/MIT)
|
|
55
55
|
|
|
56
56
|
A production-ready **Model Context Protocol (MCP) server** that revolutionizes how AI agents navigate and understand codebases. Built for high-concurrency environments with advanced database resilience, the server provides instant access to intelligent descriptions, semantic search, and context-aware recommendations while maintaining 800+ writes/sec throughput.
|
|
@@ -8,7 +8,7 @@ mcp_code_indexer/commands/makelocal.py,sha256=T_44so96jcs1FNlft9E3nAq0LlOzQLhjLd
|
|
|
8
8
|
mcp_code_indexer/data/stop_words_english.txt,sha256=feRGP8WG5hQPo-wZN5ralJiSv1CGw4h3010NBJnJ0Z8,6344
|
|
9
9
|
mcp_code_indexer/database/__init__.py,sha256=aPq_aaRp0aSwOBIq9GkuMNjmLxA411zg2vhdrAuHm-w,38
|
|
10
10
|
mcp_code_indexer/database/connection_health.py,sha256=jZr3tCbfjUJujdXe_uxtm1N4c31dMV4euiSY4ulamOE,25497
|
|
11
|
-
mcp_code_indexer/database/database.py,sha256=
|
|
11
|
+
mcp_code_indexer/database/database.py,sha256=uDtghexmwJjqq_H8H4MG8VZyJpGIySqkdrgGWQ7FVzA,60327
|
|
12
12
|
mcp_code_indexer/database/database_factory.py,sha256=VMw0tlutGgZoTI7Q_PCuFy5zAimq2xuMtDFAlF_FKtc,4316
|
|
13
13
|
mcp_code_indexer/database/exceptions.py,sha256=zciu7fDwF8y0Z4tkzTBFPPvXCvdnEJiA-Wd-cBLZBWw,10473
|
|
14
14
|
mcp_code_indexer/database/models.py,sha256=w1U9zMGNt0LQeCiifYeXKW_Cia9BKV5uPChbOve-FZY,13467
|
|
@@ -18,7 +18,7 @@ mcp_code_indexer/deepask_handler.py,sha256=qI9h_Me5WQAbt3hzzDG8XDBMZlnvx-I9R7Osm
|
|
|
18
18
|
mcp_code_indexer/error_handler.py,sha256=ylciEM-cR7E8Gmd8cfh5olcllJm0FnaYBGH86yayFic,12530
|
|
19
19
|
mcp_code_indexer/file_scanner.py,sha256=OCLnzPTneIiMtGcV3NB5qvnZrO3zxCqPEZXtCk75dfA,15178
|
|
20
20
|
mcp_code_indexer/git_hook_handler.py,sha256=sTtZV3-Yy1Evt06R5NZclELeepM4Ia9OQoR2O6BK3Hk,45517
|
|
21
|
-
mcp_code_indexer/logging_config.py,sha256=
|
|
21
|
+
mcp_code_indexer/logging_config.py,sha256=NNB5iKCc-Hdognf-UdjuEKB9H_e4UIp3QTVnf69Rc2k,10504
|
|
22
22
|
mcp_code_indexer/main.py,sha256=byM0Y9EwDa0616dEkx2p_1rUdJmDNeKAG41o5_AJago,41084
|
|
23
23
|
mcp_code_indexer/middleware/__init__.py,sha256=UCEPzOlZldlqFzYEfrXw1HvCDvY1jpLvyaDGUzVr2aw,368
|
|
24
24
|
mcp_code_indexer/middleware/auth.py,sha256=4HkHMDZBNsyPA1VE8qF7pRNKbqG4xIDZjllENbgynxI,7258
|
|
@@ -65,8 +65,8 @@ mcp_code_indexer/vector_mode/services/vector_mode_tools_service.py,sha256=K1_STy
|
|
|
65
65
|
mcp_code_indexer/vector_mode/services/vector_storage_service.py,sha256=JI3VUc2mG8xZ_YqOvfKJivuMi4imeBLr2UFVrWgDWhk,21193
|
|
66
66
|
mcp_code_indexer/vector_mode/types.py,sha256=M4lUF43FzjiVUezoRqozx_u0g1-xrX9qcRcRn-u65yw,1222
|
|
67
67
|
mcp_code_indexer/vector_mode/utils.py,sha256=XtHrpOw0QJ0EjdzJ85jrbkmHy8Slkq_t7hz-q4RP-10,1283
|
|
68
|
-
mcp_code_indexer-4.2.
|
|
69
|
-
mcp_code_indexer-4.2.
|
|
70
|
-
mcp_code_indexer-4.2.
|
|
71
|
-
mcp_code_indexer-4.2.
|
|
72
|
-
mcp_code_indexer-4.2.
|
|
68
|
+
mcp_code_indexer-4.2.18.dist-info/METADATA,sha256=KSfwzQpXfijIn6qqogm57T7r5mINsTeVhr0wpD7YL_E,27689
|
|
69
|
+
mcp_code_indexer-4.2.18.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
|
|
70
|
+
mcp_code_indexer-4.2.18.dist-info/entry_points.txt,sha256=UABj7HZ0mC6rvF22gxaz2LLNLGQShTrFmp5u00iUtvo,67
|
|
71
|
+
mcp_code_indexer-4.2.18.dist-info/licenses/LICENSE,sha256=JN9dyPPgYwH9C-UjYM7FLNZjQ6BF7kAzpF3_4PwY4rY,1086
|
|
72
|
+
mcp_code_indexer-4.2.18.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|