more release lifetime cleanup and base class contextmanager stuff

This commit is contained in:
John Smith
2023-06-18 20:57:51 -04:00
parent 1f777a73b5
commit 2314fcb57e
6 changed files with 133 additions and 53 deletions

View File

@@ -1,13 +1,13 @@
# Routing context veilid tests
# # Routing context veilid tests
import veilid
import pytest
import asyncio
import json
from . import *
# import veilid
# import pytest
# import asyncio
# import json
# from . import *
##################################################################
BOGUS_KEY = veilid.TypedKey.from_value(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.PublicKey.from_bytes(b' '))
# ##################################################################
# BOGUS_KEY = veilid.TypedKey.from_value(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.PublicKey.from_bytes(b' '))
# @pytest.mark.asyncio
# async def test_get_dht_value_unopened(api_connection: veilid.VeilidAPI):
@@ -46,6 +46,29 @@ BOGUS_KEY = veilid.TypedKey.from_value(veilid.CryptoKind.CRYPTO_KIND_VLD0, veili
# await rc.close_dht_record(rec.key)
# await rc.delete_dht_record(rec.key)
# xxx make tests for tabledb api first
# xxx then make a test that creates a record, stores it in a table
# xxx then make another test that gets the keys from the table and closes/deletes them
# @pytest.mark.asyncio
# async def test_get_dht_value_nonexistent(api_connection: veilid.VeilidAPI):
# rc = await api_connection.new_routing_context()
# async with rc:
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
# assert await rc.get_dht_value(rec.key, 0, False) == None
# await rc.close_dht_record(rec.key)
# await rc.delete_dht_record(rec.key)
# @pytest.mark.asyncio
# async def test_set_get_dht_value(api_connection: veilid.VeilidAPI):
# rc = await api_connection.new_routing_context()
# async with rc:
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
# vd = await rc.set_dht_value(rec.key, 0, b"BLAH BLAH BLAH")
# assert vd != None
# vd2 = await rc.get_dht_value(rec.key, 0, False)
# assert vd2 != None
# assert vd == vd2
# await rc.close_dht_record(rec.key)
# await rc.delete_dht_record(rec.key)

View File

@@ -6,6 +6,18 @@ from .state import VeilidState
class RoutingContext(ABC):
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.is_done():
await self.release()
@abstractmethod
def is_done(self) -> bool:
pass
@abstractmethod
async def release(self):
pass
@@ -84,6 +96,17 @@ class RoutingContext(ABC):
class TableDbTransaction(ABC):
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.is_done():
await self.rollback()
@abstractmethod
def is_done(self) -> bool:
pass
@abstractmethod
async def commit(self):
pass
@@ -102,6 +125,17 @@ class TableDbTransaction(ABC):
class TableDb(ABC):
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.is_done():
await self.release()
@abstractmethod
def is_done(self) -> bool:
pass
@abstractmethod
async def release(self):
pass
@@ -132,6 +166,18 @@ class TableDb(ABC):
class CryptoSystem(ABC):
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.is_done():
await self.release()
@abstractmethod
def is_done(self) -> bool:
pass
@abstractmethod
async def release(self):
pass
@@ -246,6 +292,21 @@ class CryptoSystem(ABC):
class VeilidAPI(ABC):
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.is_done():
await self.release()
@abstractmethod
def is_done(self) -> bool:
pass
@abstractmethod
async def release(self):
pass
@abstractmethod
async def control(self, args: list[str]) -> str:
pass

View File

@@ -53,7 +53,8 @@ class _JsonVeilidAPI(VeilidAPI):
writer: Optional[asyncio.StreamWriter]
update_callback: Callable[[VeilidUpdate], Awaitable]
handle_recv_messages_task: Optional[asyncio.Task]
validate_schemas: bool
validate_schema: bool
done: bool
# Shared Mutable State
lock: asyncio.Lock
next_id: int
@@ -70,17 +71,12 @@ class _JsonVeilidAPI(VeilidAPI):
self.writer = writer
self.update_callback = update_callback
self.validate_schema = validate_schema
self.done = False
self.handle_recv_messages_task = None
self.lock = asyncio.Lock()
self.next_id = 1
self.in_flight_requests = dict()
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
await self.close()
async def _cleanup_close(self):
await self.lock.acquire()
try:
@@ -96,7 +92,10 @@ class _JsonVeilidAPI(VeilidAPI):
finally:
self.lock.release()
async def close(self):
def is_done(self) -> bool:
return self.done
async def release(self):
# Take the task
await self.lock.acquire()
try:
@@ -112,6 +111,7 @@ class _JsonVeilidAPI(VeilidAPI):
await handle_recv_messages_task
except asyncio.CancelledError:
pass
self.done = True
@classmethod
async def connect(
@@ -430,12 +430,8 @@ class _JsonRoutingContext(RoutingContext):
# complain
raise AssertionError("Should have released routing context before dropping object")
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.done:
await self.release()
def is_done(self) -> bool:
return self.done
async def release(self):
if self.done:
@@ -668,12 +664,8 @@ class _JsonTableDbTransaction(TableDbTransaction):
# complain
raise AssertionError("Should have committed or rolled back transaction before dropping object")
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.done:
await self.rollback()
def is_done(self) -> bool:
return self.done
async def commit(self):
if self.done:
@@ -753,12 +745,8 @@ class _JsonTableDb(TableDb):
# complain
raise AssertionError("Should have released table db before dropping object")
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.done:
await self.release()
def is_done(self) -> bool:
return self.done
async def release(self):
if self.done:
@@ -880,13 +868,9 @@ class _JsonCryptoSystem(CryptoSystem):
# complain
raise AssertionError("Should have released crypto system before dropping object")
async def __aenter__(self) -> Self:
return self
async def __aexit__(self, *excinfo):
if not self.done:
await self.release()
def is_done(self) -> bool:
return self.done
async def release(self):
if self.done:
return