Skip to content

Commit 1384990

Browse files
committed
feat(entities): simplify Topic to Relation
1 parent 43d4a12 commit 1384990

File tree

12 files changed

+179
-360
lines changed

12 files changed

+179
-360
lines changed

src/tgdb/entities/horizon/effect.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
from dataclasses import dataclass
33
from uuid import UUID
44

5-
from tgdb.entities.topic.partition import PartitionTuple, PartitionTupleID
5+
from tgdb.entities.relation.tuple import Tuple, TupleID
66

77

88
@dataclass(frozen=True)
99
class ViewedTuple:
10-
id: PartitionTupleID
10+
id: TupleID
1111

1212
def __and__(self, effect: "TupleEffect") -> "TupleEffect":
1313
return effect
1414

1515

1616
@dataclass(frozen=True)
1717
class NewTuple:
18-
tuple: PartitionTuple
18+
tuple: Tuple
1919

2020
def __and__(self, effect: "TupleEffect") -> "TupleEffect":
2121
match effect:
@@ -27,13 +27,13 @@ def __and__(self, effect: "TupleEffect") -> "TupleEffect":
2727
return effect
2828

2929
@property
30-
def id(self) -> PartitionTupleID:
30+
def id(self) -> TupleID:
3131
return self.tuple.id
3232

3333

3434
@dataclass(frozen=True)
3535
class MutatedTuple:
36-
tuple: PartitionTuple
36+
tuple: Tuple
3737

3838
def __and__(self, effect: "TupleEffect") -> "TupleEffect":
3939
match effect:
@@ -45,13 +45,13 @@ def __and__(self, effect: "TupleEffect") -> "TupleEffect":
4545
return effect
4646

4747
@property
48-
def id(self) -> PartitionTupleID:
48+
def id(self) -> TupleID:
4949
return self.tuple.id
5050

5151

5252
@dataclass(frozen=True)
5353
class DeletedTuple:
54-
id: PartitionTupleID
54+
id: TupleID
5555

5656
def __and__(self, effect: "TupleEffect") -> "TupleEffect":
5757
match effect:

src/tgdb/entities/horizon/horizon.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from collections import OrderedDict
2-
from collections.abc import Sequence
32
from dataclasses import dataclass
43
from uuid import UUID
54

@@ -94,7 +93,7 @@ def complete(
9493

9594
if (
9695
transaction is None
97-
or transaction.state is not TransactionState.prepared
96+
or transaction.state() is not TransactionState.prepared
9897
):
9998
return None
10099

src/tgdb/entities/horizon/transaction.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
TupleEffect,
1212
ViewedTuple,
1313
)
14+
from tgdb.entities.relation.tuple import TupleID
1415
from tgdb.entities.time.logic_time import LogicTime
15-
from tgdb.entities.topic.partition import PartitionTupleID
1616

1717

1818
@dataclass(frozen=True)
@@ -88,7 +88,7 @@ class SerializableTransaction(Transaction):
8888
_id: UUID
8989
_state: TransactionState
9090
_beginning: LogicTime
91-
_space_map: dict[PartitionTupleID, TupleEffect]
91+
_space_map: dict[TupleID, TupleEffect]
9292
_claims: set[Claim]
9393
_concurrent_transactions: set["Transaction"]
9494
_transactions_with_possible_conflict: set["SerializableTransaction"]
@@ -205,7 +205,7 @@ def _conflict(self) -> TransactionConflict | None:
205205

206206
return None
207207

208-
def _space(self) -> set[PartitionTupleID]:
208+
def _space(self) -> set[TupleID]:
209209
return set(self._space_map)
210210

211211
def _effect(self) -> TransactionEffect:

src/tgdb/entities/numeration/number.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@ class Number:
1010
:raises tgdb.entities.numeration.number.NegativeNumberError:
1111
"""
1212

13-
int: int
13+
_int: int
1414

1515
def __post_init__(self) -> None:
16-
if self.int < 0:
16+
if self._int < 0:
1717
raise NegativeNumberError
1818

1919
def __int__(self) -> "int":
20-
return self.int
20+
return self._int
2121

2222
def __next__(self) -> "Number":
23-
return Number(self.int + 1)
23+
return Number(self._int + 1)
2424

2525
def __lt__(self, other: "Number") -> bool:
26-
return self.int < other.int
26+
return self._int < other._int
2727

2828
def __le__(self, other: "Number") -> bool:
29-
return self.int <= other.int
29+
return self._int <= other._int

src/tgdb/entities/relation/domain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class SetDomain[T: bool | int | str | datetime | UUID](Domain):
6060
_type: type[T]
6161
_is_nonable: bool
6262

63-
def type(self) -> type[T]:
63+
def type(self) -> type[T]: # type: ignore[override]
6464
return self._type
6565

6666
def is_nonable(self) -> bool:
Lines changed: 127 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,138 @@
1+
from collections.abc import Iterator, Sequence
12
from dataclasses import dataclass
3+
from itertools import pairwise
4+
from uuid import UUID
25

3-
from tgdb.entities.relation.scalar import Scalar
6+
from tgdb.entities.numeration.number import Number
7+
from tgdb.entities.relation.domain import Domain
48
from tgdb.entities.relation.schema import Schema
59

610

711
@dataclass(frozen=True)
8-
class UniversalRelation:
9-
schema: Schema
12+
class InitialRelationVersion[IDDomainT: Domain]:
13+
number: Number
14+
schema: Schema[IDDomainT]
1015

11-
def __bool__(self) -> bool:
12-
return bool(self.schema)
1316

14-
def __contains__(self, tuple_: tuple[Scalar, ...]) -> bool:
15-
if not self.schema:
16-
return False
17+
@dataclass(frozen=True)
18+
class DerivativeRelationVersion[IDDomainT: Domain]:
19+
number: Number
20+
schema: Schema[IDDomainT]
21+
migration_id: UUID
22+
23+
24+
type RelationVersion[IDDomainT: Domain] = (
25+
InitialRelationVersion[IDDomainT] | DerivativeRelationVersion[IDDomainT]
26+
)
27+
28+
29+
class NotIncrementedRelationVersionError(Exception): ...
30+
31+
32+
class RelationWithoutLastVersionError(Exception): ...
33+
34+
35+
@dataclass
36+
class Relation[IDDomainT: Domain]:
37+
"""
38+
:raises tgdb.entities.relation.relation.RelationWithoutLastVersionError:
39+
:raises tgdb.entities.relation.relation.NotIncrementedRelationVersionError:
40+
"""
1741

18-
if len(tuple_) != len(self.schema):
19-
return False
42+
_id: Number
43+
_inital_version: InitialRelationVersion[IDDomainT]
44+
_intermediate_versions: list[DerivativeRelationVersion[IDDomainT]]
2045

21-
return all(
22-
scalar in domain
23-
for scalar, domain in zip(tuple_, self.schema, strict=True)
46+
def __post_init__(self) -> None:
47+
if not self._intermediate_versions or not self._inital_version:
48+
raise RelationWithoutLastVersionError
49+
50+
for version, next_version in pairwise(self._versions()):
51+
if next(version.number) != next_version.number:
52+
raise NotIncrementedRelationVersionError
53+
54+
def __len__(self) -> int:
55+
return len(self._intermediate_versions) + 1
56+
57+
def __iter__(self) -> Iterator[RelationVersion[IDDomainT]]:
58+
return iter(self._versions())
59+
60+
def inital_version(self) -> InitialRelationVersion[IDDomainT] | None:
61+
return self._inital_version
62+
63+
def intermediate_versions(
64+
self
65+
) -> Sequence[DerivativeRelationVersion[IDDomainT]]:
66+
return self._intermediate_versions
67+
68+
def last_version(self) -> RelationVersion[IDDomainT]:
69+
return (
70+
self._intermediate_versions[-1]
71+
if self._intermediate_versions
72+
else self._inital_version
2473
)
74+
75+
def recent_versions(
76+
self, current_version_number: Number
77+
) -> Sequence[DerivativeRelationVersion[IDDomainT]]:
78+
if current_version_number < self._inital_version.number:
79+
return tuple()
80+
81+
if current_version_number == self._inital_version.number:
82+
return self._intermediate_versions
83+
84+
if current_version_number >= self._intermediate_versions[-1].number:
85+
return tuple()
86+
87+
if not self._intermediate_versions:
88+
return tuple()
89+
90+
current_version_index = (
91+
int(self._intermediate_versions[0].number)
92+
- int(current_version_number)
93+
)
94+
95+
return self._intermediate_versions[current_version_index + 1:]
96+
97+
def migrate(
98+
self,
99+
new_version_schema: Schema[IDDomainT],
100+
new_version_migration_id: UUID,
101+
) -> None:
102+
last_version = DerivativeRelationVersion(
103+
next(self.last_version().number),
104+
new_version_schema,
105+
new_version_migration_id,
106+
)
107+
self._intermediate_versions.append(last_version)
108+
109+
def remove_old_versions(self, count: int) -> None:
110+
count_to_remove_intermediate_versions = count - 1
111+
count_to_remove_intermediate_versions = (
112+
min(count_to_remove_intermediate_versions, len(self) - 1)
113+
)
114+
del self._intermediate_versions[:count_to_remove_intermediate_versions]
115+
116+
version_to_make_inital = self._intermediate_versions[0]
117+
118+
self._inital_version = InitialRelationVersion(
119+
version_to_make_inital.number,
120+
version_to_make_inital.schema,
121+
)
122+
del self._intermediate_versions[0]
123+
124+
@classmethod
125+
def new(
126+
cls, id: Number, schema: Schema[IDDomainT]
127+
) -> "Relation[IDDomainT]":
128+
return Relation(
129+
id,
130+
InitialRelationVersion(Number(0), schema),
131+
list(),
132+
)
133+
134+
def _versions(self) -> Sequence[RelationVersion[IDDomainT]]:
135+
if self._inital_version:
136+
return (self._inital_version, *self._intermediate_versions)
137+
138+
return self._intermediate_versions
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1+
from collections.abc import Iterator
2+
from dataclasses import dataclass
3+
14
from tgdb.entities.relation.domain import Domain
25

36

4-
type Schema = tuple[Domain, ...]
7+
@dataclass(frozen=True)
8+
class Schema[IDDomainT: Domain]:
9+
id_domain: IDDomainT
10+
other_domains: tuple[Domain, ...]
11+
12+
def __iter__(self) -> Iterator[Domain]:
13+
yield self.id_domain
14+
yield from self.other_domains
15+
16+
def __len__(self) -> int:
17+
return len(self.other_domains) + 1
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from collections.abc import Iterator
2+
from dataclasses import dataclass
3+
4+
from tgdb.entities.numeration.number import Number
5+
from tgdb.entities.relation.scalar import Scalar
6+
7+
8+
@dataclass(frozen=True)
9+
class TupleID:
10+
relation_id: Number
11+
scalar: Scalar
12+
13+
14+
@dataclass(frozen=True)
15+
class Tuple:
16+
id: TupleID
17+
scalars: tuple[Scalar, ...]
18+
19+
def __iter__(self) -> Iterator[Scalar]:
20+
return iter(self.scalars)

src/tgdb/entities/topic/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)