earthsnake/earthsnake/replica/memory.py

100 lines
2.8 KiB
Python
Raw Normal View History

2022-04-12 13:25:29 +00:00
"""A share driver that stores data in memory
"""
2022-05-06 12:11:28 +00:00
from typing import Dict, List, Tuple
from ..document import Document
from ..exc import ReplicaIsClosedError
from ..identity import Identity
from ..path import Path
2022-04-12 13:25:29 +00:00
from ..query import HistoryMode, Query
2022-05-06 12:11:28 +00:00
from ..share import Share
from . import Replica
class InMemoryReplica(Replica):
2022-04-12 13:25:29 +00:00
"""In-memory Replica"""
def __init__(self, share: Share, **driver_kwargs) -> None:
2022-05-06 12:11:28 +00:00
self.share = share
self._is_closed = False
self._max_local_index = -1
# Local Index <=> Document pairs
self._documents: List[Tuple[int, Document]] = {}
@property
2022-04-12 13:25:29 +00:00
def is_closed(self) -> bool:
2022-05-06 12:11:28 +00:00
return self._is_closed
2022-04-12 13:25:29 +00:00
def close(self, erase: bool = False) -> None:
if self._is_closed:
raise ReplicaIsClosedError()
2022-05-06 12:11:28 +00:00
if erase:
self._local_index = -1
self._documents = []
self._is_closed = True
@property
def max_local_index(self) -> int:
2022-04-12 13:25:29 +00:00
if self._is_closed:
raise ReplicaIsClosedError()
2022-05-06 12:11:28 +00:00
return self._max_local_index
def _get_all_docs(self) -> List[Document]:
2022-04-12 13:25:29 +00:00
"""Get all documents"""
2022-05-06 12:11:28 +00:00
if self._is_closed:
raise ReplicaIsClosedError()
return [document for _, document in self._documents]
def _get_latest_docs(self) -> List[Document]:
2022-04-12 13:25:29 +00:00
"""Get the latest version of each document"""
2022-05-06 12:11:28 +00:00
if self._is_closed:
raise ReplicaIsClosedError()
docs_by_path: Dict[str, Document] = {}
for document in self._documents:
if (
str(document.path) not in docs_by_path
or docs_by_path[str(document.path)].timestamp <= document.timestamp
):
docs_by_path[str(document.path)] = document
return list(docs_by_path.values())
def query_docs(self, query: Query) -> List[Document]:
2022-04-12 13:25:29 +00:00
"""Query a list of documents"""
2022-05-06 12:11:28 +00:00
if self._is_closed:
raise ReplicaIsClosedError()
if query.history_mode == HistoryMode.ALL:
docs = self._get_all_docs()
else:
docs = self._get_latest_docs()
docs_to_local_index = {
document: local_index for document, local_index in self.docs_by_local_index
}
return query({docs_to_local_index[document]: document for document in docs})
def upsert(self, new_document: Document) -> None:
if self._is_closed:
raise ReplicaIsClosedError()
2022-04-12 13:25:29 +00:00
self._max_local_index += 1
2022-05-06 12:11:28 +00:00
self._documents = [
(local_index, document)
for local_index, document in self._documents
if document.author != new_document.author or document.path != new_document.path
]
self._documents.append((self._local_index, new_document))