44import logging
55import os
66import sys
7+ from asyncio import Lock
78from dataclasses import dataclass , field , fields
89from datetime import datetime
910from enum import Enum , StrEnum
1011from pathlib import Path
11- from typing import Any , Generator , Iterable , Optional , Sequence , Union
12+ from typing import (
13+ Any ,
14+ Generator ,
15+ Iterable ,
16+ Literal ,
17+ Optional ,
18+ Sequence ,
19+ Type ,
20+ Union ,
21+ overload ,
22+ )
1223
1324import json5
1425import shtab
@@ -644,12 +655,15 @@ def config_logging(
644655 )
645656
646657
658+ LockType = AsyncFileLock | Lock
659+
660+
647661class LockManager :
648662 """
649663 A class that manages file locks that protects the database files in daemon processes (LSP, MCP).
650664 """
651665
652- __locks : dict [str , AsyncFileLock ]
666+ __locks : dict [tuple [ str , Type [ LockType ]], LockType ]
653667 singleton : Optional ["LockManager" ] = None
654668
655669 def __new__ (cls ) -> "LockManager" :
@@ -658,7 +672,23 @@ def __new__(cls) -> "LockManager":
658672 cls .singleton .__locks = {}
659673 return cls .singleton
660674
661- def get_lock (self , path : str | os .PathLike ) -> AsyncFileLock :
675+ @overload
676+ def get_lock (
677+ self , path : str | os .PathLike , lock_type_name : Literal ["asyncio" ]
678+ ) -> Lock : ...
679+
680+ @overload
681+ def get_lock (
682+ self ,
683+ path : str | os .PathLike ,
684+ lock_type_name : Literal ["filelock" ] | None ,
685+ ) -> AsyncFileLock : ...
686+
687+ def get_lock (
688+ self ,
689+ path : str | os .PathLike ,
690+ lock_type_name : Literal ["filelock" ] | Literal ["asyncio" ] | None = "filelock" ,
691+ ):
662692 path = str (expand_path (str (path ), True ))
663693 if os .path .isdir (path ):
664694 lock_file = os .path .join (path , "vectorcode.lock" )
@@ -667,9 +697,19 @@ def get_lock(self, path: str | os.PathLike) -> AsyncFileLock:
667697 with open (lock_file , mode = "w" ) as fin :
668698 fin .write ("" )
669699 path = lock_file
670- if self .__locks .get (path ) is None :
671- self .__locks [path ] = AsyncFileLock (path ) # pyright: ignore[reportArgumentType]
672- return self .__locks [path ]
700+ lock : LockType
701+ match lock_type_name :
702+ case "filelock" :
703+ lock = AsyncFileLock (path ) # pyright: ignore[reportAssignmentType]
704+ case "asyncio" :
705+ lock = Lock ()
706+ case _: # pragma: nocover
707+ raise ValueError (f"Unsupported lock type: { lock_type_name } " )
708+
709+ cache_key = (path , type (lock ))
710+ if self .__locks .get (cache_key ) is None :
711+ self .__locks [cache_key ] = lock
712+ return self .__locks [cache_key ]
673713
674714
675715class SpecResolver :
0 commit comments