transactions
This commit is contained in:
parent
632569a135
commit
d1564637f2
@ -89,6 +89,15 @@ class ErrorRequest(Request):
|
|||||||
await self.future
|
await self.future
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionRequest(Request):
|
||||||
|
def __init__(self, buffer: StringIO, future: Optional[asyncio.Future]):
|
||||||
|
super().__init__(future)
|
||||||
|
self.buffer = buffer
|
||||||
|
|
||||||
|
def line(self) -> str:
|
||||||
|
return self.buffer.getvalue()
|
||||||
|
|
||||||
|
|
||||||
class DbConnection:
|
class DbConnection:
|
||||||
__mmdb: dict
|
__mmdb: dict
|
||||||
__loop: asyncio.AbstractEventLoop
|
__loop: asyncio.AbstractEventLoop
|
||||||
@ -146,14 +155,14 @@ class DbConnection:
|
|||||||
self.__mmdb[key] = value
|
self.__mmdb[key] = value
|
||||||
self.__queue.put_nowait(self.factory.kvrequest_type(key, value, None))
|
self.__queue.put_nowait(self.factory.kvrequest_type(key, value, None))
|
||||||
|
|
||||||
async def _dump_buffer_or_request_so(self, request: KVRequest):
|
async def _dump_buffer_or_request_so(self, request: Request):
|
||||||
if self.__buffer.tell() >= self.factory.buffersize:
|
if self.__buffer.tell() >= self.factory.buffersize:
|
||||||
await self._dump_buffer()
|
await self._dump_buffer()
|
||||||
request.set_result(None)
|
request.set_result(None)
|
||||||
else:
|
else:
|
||||||
await self.__queue.put(DumpRequest(request.future))
|
await self.__queue.put(DumpRequest(request.future))
|
||||||
|
|
||||||
async def _write(self, line: str, request: KVRequest):
|
async def _write(self, line: str, request: Request):
|
||||||
self.__buffer.write(line)
|
self.__buffer.write(line)
|
||||||
await self._dump_buffer_or_request_so(request)
|
await self._dump_buffer_or_request_so(request)
|
||||||
|
|
||||||
@ -197,6 +206,8 @@ class DbConnection:
|
|||||||
request.set_result(None)
|
request.set_result(None)
|
||||||
elif isinstance(request, ErrorRequest):
|
elif isinstance(request, ErrorRequest):
|
||||||
await self._save_error(request.line)
|
await self._save_error(request.line)
|
||||||
|
elif isinstance(request, TransactionRequest):
|
||||||
|
await self._write(request.line(), request)
|
||||||
else:
|
else:
|
||||||
raise UnkownRequestType
|
raise UnkownRequestType
|
||||||
|
|
||||||
@ -282,6 +293,22 @@ class DbConnection:
|
|||||||
del self.__task
|
del self.__task
|
||||||
del self.__initial_size
|
del self.__initial_size
|
||||||
|
|
||||||
|
async def complete_transaction(self, delta: dict):
|
||||||
|
buffer = StringIO()
|
||||||
|
self.db2io(delta, buffer)
|
||||||
|
self.__mmdb.update(delta)
|
||||||
|
future = self.__loop.create_future()
|
||||||
|
self.__queue.put_nowait(TransactionRequest(buffer, future))
|
||||||
|
await future
|
||||||
|
|
||||||
|
async def commit(self):
|
||||||
|
future = self.__loop.create_future()
|
||||||
|
self.__queue.put_nowait(DumpRequest(future))
|
||||||
|
await future
|
||||||
|
|
||||||
|
def transaction(self) -> 'Transaction':
|
||||||
|
return Transaction(self)
|
||||||
|
|
||||||
|
|
||||||
class DbFactory:
|
class DbFactory:
|
||||||
def __init__(self, path: str | pathlib.Path, *, kvrequest_type: Type[KVRequest], buffersize=1048576):
|
def __init__(self, path: str | pathlib.Path, *, kvrequest_type: Type[KVRequest], buffersize=1048576):
|
||||||
@ -289,7 +316,7 @@ class DbFactory:
|
|||||||
self.kvrequest_type = kvrequest_type
|
self.kvrequest_type = kvrequest_type
|
||||||
self.buffersize = buffersize
|
self.buffersize = buffersize
|
||||||
|
|
||||||
async def __aenter__(self):
|
async def __aenter__(self) -> DbConnection:
|
||||||
self.db = await DbConnection.create(self)
|
self.db = await DbConnection.create(self)
|
||||||
return self.db
|
return self.db
|
||||||
|
|
||||||
@ -302,9 +329,37 @@ class Db(DbFactory, DbConnection):
|
|||||||
DbFactory.__init__(self, path, kvrequest_type=kvrequest_type, buffersize=buffersize)
|
DbFactory.__init__(self, path, kvrequest_type=kvrequest_type, buffersize=buffersize)
|
||||||
DbConnection.__init__(self, self)
|
DbConnection.__init__(self, self)
|
||||||
|
|
||||||
async def __aenter__(self):
|
async def __aenter__(self) -> DbConnection:
|
||||||
await self._initialize()
|
await self._initialize()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||||
await self.aclose()
|
await self.aclose()
|
||||||
|
|
||||||
|
|
||||||
|
class FallbackMapping:
|
||||||
|
def __init__(self, delta: dict, connection: DbConnection) -> None:
|
||||||
|
self.__delta = delta
|
||||||
|
self.__connection = connection
|
||||||
|
|
||||||
|
def get(self, key: Any, default: Any):
|
||||||
|
return self.__delta.get(key, self.__connection.get(key, default))
|
||||||
|
|
||||||
|
def set_nowait(self, key: Any, value: Any):
|
||||||
|
self.__delta[key] = value
|
||||||
|
|
||||||
|
|
||||||
|
class Transaction:
|
||||||
|
delta: dict
|
||||||
|
|
||||||
|
def __init__(self, connection: DbConnection) -> None:
|
||||||
|
self.connection = connection
|
||||||
|
|
||||||
|
async def __aenter__(self) -> FallbackMapping:
|
||||||
|
self.delta = {}
|
||||||
|
return FallbackMapping(self.delta, self.connection)
|
||||||
|
|
||||||
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
if exc_type is None:
|
||||||
|
await self.connection.complete_transaction(self.delta)
|
||||||
|
del self.delta
|
||||||
|
Loading…
Reference in New Issue
Block a user