Skip to content

Commit 0fb8734

Browse files
committed
Add migration_helper reldb
1 parent 86f70a8 commit 0fb8734

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
2+
from re import match, Match
3+
from os import listdir
4+
from importlib import import_module
5+
6+
from openslides_backend.database.db_connection_handling import (
7+
os_conn_pool
8+
)
9+
10+
# relative path to the migrations
11+
MIGRATIONS_RELATIVE_DIRECTORY_PATH = ""
12+
FIRST_REL_DB_MIGRATION = 0
13+
14+
class MigrationHelper:
15+
'''
16+
Helper class containing static methods for handling the migrations. Reads and executes them.
17+
'''
18+
migrations : dict = {}
19+
20+
21+
@staticmethod
22+
def run_migrations() -> None:
23+
'''
24+
Runs the full migration process.
25+
26+
Returns:
27+
- None
28+
'''
29+
MigrationHelper.load_migrations()
30+
MigrationHelper.execute_migrations()
31+
32+
33+
@staticmethod
34+
def load_migrations() -> None:
35+
'''
36+
Checks wether current migration_index is equal to or above the FIRST_REL_DB_MIGRATION and
37+
accesses MIGRATION_DIRECTORY_PATH. Lists every migration file above the migration_index
38+
and stores them in MigrationHelper.migrations for future reference.
39+
40+
Returns:
41+
- None
42+
'''
43+
migrations : list
44+
migration_file : str
45+
migration_index : int
46+
migration_number : int
47+
reMatch : Match
48+
49+
migration_index = MigrationHelper.pull_migration_index_from_db()
50+
51+
if migration_index >= FIRST_REL_DB_MIGRATION:
52+
migrations = listdir(MIGRATIONS_RELATIVE_DIRECTORY_PATH)
53+
54+
for n, migration in enumerate(migrations[:]):
55+
reMatch = match(r'(?P<migration>\d{4}_.*)\.py', migration)
56+
# \d{4}_.*\.py : 4 digits, 1 underscore, any characters, [dot]py
57+
if reMatch is not None:
58+
migration_file = reMatch.groupdict()["migration"]
59+
migration_number = int(migration_file[:4])
60+
if migration_number > migration_index:
61+
MigrationHelper.migrations[migration_number] = migration
62+
63+
MigrationHelper.migrations = dict(sorted(MigrationHelper.migrations.items()))
64+
65+
66+
@staticmethod
67+
def pull_migration_index_from_db() -> migration_index:
68+
'''
69+
Reads the current migration_index from the psql database.
70+
1. MAX(migration_index) of positions while position is used for the index
71+
2. migration_index from version after the second migration to eliminate the table position
72+
73+
Returns:
74+
- migration_index : integer
75+
'''
76+
77+
with os_conn_pool.connection() as conn:
78+
with conn.cursor() as cur:
79+
cur.execute("SELECT MAX(migration_index) FROM positions;")
80+
row = cur.fetchone()
81+
if row is None:
82+
cur.execute("SELECT migration_index FROM version;")
83+
row = cur.fetchone()
84+
85+
# idx 0 is a wild guess anticipating that (migration_index.value) is delivered by cur.fetchone()
86+
migration_index = row[0]
87+
88+
assert type(migration_index) == int, f'Type {type(migration_index)} of migration_index must be int.'
89+
90+
return migration_index
91+
92+
93+
@staticmethod
94+
def execute_migrations() -> None:
95+
'''
96+
Executes the migrations stored in MigrationHelper.migrations.
97+
Every migration could provide all of the three methods data_definition,
98+
data_manipulation and cleanup.
99+
100+
Returns:
101+
- None
102+
'''
103+
module_path : str
104+
module_name : str
105+
106+
module_path = MIGRATIONS_RELATIVE_DIRECTORY_PATH.replace("/",".")
107+
108+
for index, migration in MigrationHelper.migrations.items():
109+
module_name = migration.replace(".py","")
110+
migration_module = import_module(f"{module_path}{module_name}")
111+
if getattr(migration_module, "IN_MEMORY", False):
112+
migration_module.in_memory_method()
113+
else:
114+
# checks wether the methods are available and executes them.
115+
if callable(getattr(migration_module, "data_definition", None)):
116+
migration_module.data_definition()
117+
if callable(getattr(migration_module, "data_manipulation", None)):
118+
migration_module.data_manipulation()
119+
if callable(getattr(migration_module, "cleanup", None)):
120+
migration_module.cleanup()
121+
122+
# TODO In-Memory migration

0 commit comments

Comments
 (0)