fix(anki): anki api concurrency issues

This commit is contained in:
arne314
2024-12-24 14:01:22 +01:00
parent 1f2bc8e486
commit c3331683e5
2 changed files with 24 additions and 13 deletions

View File

@@ -13,9 +13,12 @@ class AnkiConnectError(Exception):
class AnkiConnectApi: class AnkiConnectApi:
url: str url: str
api_key: str
def __init__(self, url="http://127.0.0.1:8765"): def __init__(self, url: str, api_key: str):
self.url = url self.url = url
self.api_key = api_key
self.semaphore = asyncio.Semaphore(2) # increase in case Anki implements multithreading
async def push_flashcards(self, cards: List[Flashcard]): async def push_flashcards(self, cards: List[Flashcard]):
add = [] add = []
@@ -33,15 +36,17 @@ class AnkiConnectApi:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
data = { data = {
"action": action, "action": action,
"version": 6, "key": self.api_key,
"params": params, "params": params,
"version": 6,
} }
try: try:
async with session.post(url=self.url, json=data) as response: async with self.semaphore:
result = await response.json(encoding="utf-8") async with session.post(url=self.url, json=data) as response:
if err := result["error"]: result = await response.json(encoding="utf-8")
raise AnkiConnectError(err) if err := result["error"]:
return result["result"] raise AnkiConnectError(err)
return result["result"]
except aiohttp.ClientError as e: except aiohttp.ClientError as e:
raise AnkiConnectError(f"Could not connect to Anki: {e}") raise AnkiConnectError(f"Could not connect to Anki: {e}")
@@ -73,5 +78,8 @@ class AnkiConnectApi:
await self._update(cards) await self._update(cards)
async def _update(self, cards: List[Flashcard]): async def _update(self, cards: List[Flashcard]):
await asyncio.gather(*(self._update_note_model(card) for card in cards), results = await asyncio.gather(*(self._update_note_model(card) for card in cards),
*(self._store_media(card) for card in cards)) *(self._store_media(card) for card in cards), return_exceptions=True)
for result in results:
if isinstance(result, Exception):
raise result

View File

@@ -13,10 +13,10 @@ from anki.typst_compiler import TypstCompiler
cli = typer.Typer(name="typstar-anki") cli = typer.Typer(name="typstar-anki")
async def export_flashcards(root_dir, typst_cmd): async def export_flashcards(root_dir, typst_cmd, anki_url, anki_key):
parser = FlashcardParser() parser = FlashcardParser()
compiler = TypstCompiler(root_dir, typst_cmd) compiler = TypstCompiler(root_dir, typst_cmd)
api = AnkiConnectApi() api = AnkiConnectApi(anki_url, anki_key)
# parse flashcards # parse flashcards
flashcards = parser.parse_directory(root_dir) flashcards = parser.parse_directory(root_dir)
@@ -36,8 +36,11 @@ async def export_flashcards(root_dir, typst_cmd):
@cli.command() @cli.command()
def cmd(root_dir: Annotated[ def cmd(root_dir: Annotated[
str, typer.Option(help="Directory scanned for flashcards and passed over to typst compile command")] = os.getcwd(), str, typer.Option(help="Directory scanned for flashcards and passed over to typst compile command")] = os.getcwd(),
typst_cmd: Annotated[str, typer.Option(help="Typst command used for flashcard compilation")] = "typst"): typst_cmd: Annotated[str, typer.Option(help="Typst command used for flashcard compilation")] = "typst",
asyncio.run(export_flashcards(root_dir, typst_cmd)) anki_url: Annotated[str, typer.Option(help="Url for Anki-Connect")] = "http://127.0.0.1:8765",
anki_key: Annotated[str, typer.Option(help="Api key for Anki-Connect")] = None,
):
asyncio.run(export_flashcards(root_dir, typst_cmd, anki_url, anki_key))
def main(): def main():