1010from pathlib import Path
1111from typing import List , Mapping , NamedTuple , Optional , Sequence , Tuple , Union
1212from urllib .parse import urlparse
13+ from filelock import FileLock
1314
1415import base58
1516from anoncreds import (
6263REV_REG_DEF_STATE_ACTIVE = "active"
6364
6465# Module level lock
65- _credential_creation_lock = asyncio .Lock ()
66+ class AsyncFileLock :
67+ def __init__ (self , lock_file_path : str ):
68+ self .lock = FileLock (lock_file_path )
69+
70+ async def __aenter__ (self ):
71+ await asyncio .get_event_loop ().run_in_executor (None , self .lock .acquire )
72+ return self
73+
74+ async def __aexit__ (self , exc_type , exc_val , exc_tb ):
75+ await asyncio .get_event_loop ().run_in_executor (None , self .lock .release )
76+
77+ _credential_creation_lock = AsyncFileLock ("/home/aries/.indy_client/acapy_credential_creation.lock" )
78+
6679class AnonCredsRevocationError (BaseError ):
6780 """Generic revocation error."""
6881
@@ -985,14 +998,14 @@ def _handle_missing_entries(rev_list: Entry, rev_reg_def: Entry, rev_key: Entry)
985998 raise AnonCredsRevocationError (
986999 "Revocation registry definition private data not found"
9871000 )
988-
1001+
9891002 def _has_required_id_and_tails_path ():
9901003 return rev_reg_def_id and tails_file_path
991-
1004+
9921005 revoc = None
9931006 credential_revocation_id = None
9941007 rev_list = None
995-
1008+
9961009 if _has_required_id_and_tails_path ():
9971010 async with self .profile .session () as session :
9981011 rev_reg_def = await session .handle .fetch (
@@ -1002,20 +1015,20 @@ def _has_required_id_and_tails_path():
10021015 rev_key = await session .handle .fetch (
10031016 CATEGORY_REV_REG_DEF_PRIVATE , rev_reg_def_id
10041017 )
1005-
1018+
10061019 _handle_missing_entries (rev_list , rev_reg_def , rev_key )
1007-
1020+
10081021 rev_list_value_json = rev_list .value_json
10091022 rev_list_tags = rev_list .tags
1010-
1023+
10111024 # If the rev_list state is failed then the tails file was never uploaded,
10121025 # try to upload it now and finish the revocation list
10131026 if rev_list_tags .get ("state" ) == RevListState .STATE_FAILED :
10141027 await self .upload_tails_file (
10151028 RevRegDef .deserialize (rev_reg_def .value_json )
10161029 )
10171030 rev_list_tags ["state" ] = RevListState .STATE_FINISHED
1018-
1031+
10191032 rev_reg_index = rev_list_value_json ["next_index" ]
10201033 try :
10211034 rev_reg_def = RevocationRegistryDefinition .load (rev_reg_def .raw_value )
@@ -1024,7 +1037,7 @@ def _has_required_id_and_tails_path():
10241037 raise AnonCredsRevocationError (
10251038 "Error loading revocation registry"
10261039 ) from err
1027-
1040+
10281041 # NOTE: we increment the index ahead of time to keep the
10291042 # transaction short. The revocation registry itself will NOT
10301043 # be updated because we always use ISSUANCE_BY_DEFAULT.
@@ -1041,19 +1054,19 @@ def _has_required_id_and_tails_path():
10411054 tags = rev_list_tags ,
10421055 )
10431056 await txn .commit ()
1044-
1057+
10451058 revoc = CredentialRevocationConfig (
10461059 rev_reg_def ,
10471060 rev_key .raw_value ,
10481061 rev_list ,
10491062 rev_reg_index ,
10501063 )
10511064 credential_revocation_id = str (rev_reg_index )
1052-
1065+
10531066 cred_def , cred_def_private = await self ._get_cred_def_objects (
10541067 credential_definition_id
10551068 )
1056-
1069+
10571070 try :
10581071 credential = await asyncio .get_event_loop ().run_in_executor (
10591072 None ,
@@ -1070,7 +1083,7 @@ def _has_required_id_and_tails_path():
10701083 )
10711084 except AnoncredsError as err :
10721085 raise AnonCredsRevocationError ("Error creating credential" ) from err
1073-
1086+
10741087 return credential .to_json (), credential_revocation_id
10751088
10761089 async def create_credential (
0 commit comments