Skip to content

Commit 43922b5

Browse files
committed
Refactor a get_pending_sql_reorganize_partition_commands entry for the Maintain algo
The README.md expresses the "Maintain" algorithm in its ideal form, which got messy in implementation. The get_pending_sql_reorganize_partition_commands makes that clean again, so that there's a clear map to the algorithm description.
1 parent 42dcdfa commit 43922b5

File tree

5 files changed

+188
-72
lines changed

5 files changed

+188
-72
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ orders:
115115

116116
## "Maintain" Algorithm
117117

118-
The core algorithm is implemented in a method `plan_partition_changes` in `table_append_partition.py`. That algorithm is:
118+
The core algorithm is implemented in a method `get_pending_sql_reorganize_partition_commands` in `table_append_partition.py`. That algorithm is:
119119

120120
For a given table and that table's intended partition period, desired end-state is to have:
121121
- All the existing partitions containing data,

partitionmanager/cli.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,22 +294,19 @@ def do_partition(conf):
294294

295295
ordered_positions = [positions[col] for col in map_data["range_cols"]]
296296

297-
partition_changes = pm_tap.plan_partition_changes(
298-
map_data["partitions"],
299-
ordered_positions,
300-
conf.curtime,
301-
duration,
302-
conf.num_empty,
297+
sql_cmds = pm_tap.get_pending_sql_reorganize_partition_commands(
298+
table=table,
299+
partition_list=map_data["partitions"],
300+
current_positions=ordered_positions,
301+
allowed_lifespan=duration,
302+
num_empty_partitions=conf.num_empty,
303+
evaluation_time=conf.curtime,
303304
)
304305

305-
if not pm_tap.should_run_changes(partition_changes):
306-
log.info(f"{table} does not need to be modified currently.")
306+
if not sql_cmds:
307+
log.debug(f"{table} has no pending SQL updates.")
307308
continue
308-
log.debug(f"{table} has changes waiting.")
309309

310-
sql_cmds = pm_tap.generate_sql_reorganize_partition_commands(
311-
table, partition_changes
312-
)
313310
composite_sql_command = "\n".join(sql_cmds)
314311

315312
if conf.noop:

partitionmanager/cli_test.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -201,17 +201,32 @@ def test_partition_period_daily(self):
201201
)
202202

203203
def test_partition_period_seven_days(self):
204-
o = run_partition_cmd_yaml(
205-
f"""
206-
partitionmanager:
207-
num_empty: 1
208-
partition_period:
209-
days: 7
210-
tables:
211-
partitioned_yesterday:
212-
partitioned_last_week:
213-
mariadb: {str(fake_exec)}
214-
"""
204+
with self.assertLogs("partition", level="DEBUG") as logctx:
205+
o = run_partition_cmd_yaml(
206+
f"""
207+
partitionmanager:
208+
num_empty: 1
209+
partition_period:
210+
days: 7
211+
tables:
212+
partitioned_yesterday:
213+
partitioned_last_week:
214+
mariadb: {str(fake_exec)}
215+
"""
216+
)
217+
218+
self.assertEqual(
219+
set(logctx.output),
220+
set(
221+
[
222+
"INFO:partition:Evaluating Table partitioned_last_week "
223+
"(duration=7 days, 0:00:00) (pos={'id': 150})",
224+
"DEBUG:partition:Table partitioned_last_week has no pending SQL updates.",
225+
"INFO:partition:Evaluating Table partitioned_yesterday "
226+
"(duration=7 days, 0:00:00) (pos={'id': 150})",
227+
"DEBUG:partition:Table partitioned_yesterday has no pending SQL updates.",
228+
]
229+
),
215230
)
216231
self.assertSequenceEqual(list(o), [])
217232

partitionmanager/table_append_partition.py

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def _parse_partition_map(rows):
8787
The "partitions" is a list of the Partition objects representing each
8888
defined partition. There will be at least one partitionmanager.types.MaxValuePartition.
8989
"""
90-
log = logging.getLogger("_parse_partition_map")
90+
log = logging.getLogger("parse_partition_map")
9191

9292
partition_range = re.compile(
9393
r"[ ]*PARTITION BY RANGE\s+(COLUMNS)?\((?P<cols>[\w,` ]+)\)"
@@ -321,7 +321,7 @@ def _calculate_start_time(last_changed_time, evaluation_time, allowed_lifespan):
321321
return partition_start_time
322322

323323

324-
def plan_partition_changes(
324+
def _plan_partition_changes(
325325
partition_list,
326326
current_positions,
327327
evaluation_time,
@@ -333,23 +333,6 @@ def plan_partition_changes(
333333
This method makes recommendations in order to meet the supplied table
334334
requirements, using an estimate as to the rate of fill from the supplied
335335
partition_list, current_positions, and evaluation_time.
336-
337-
Args:
338-
339-
partition_list: the currently-existing partition objects, each with
340-
a name and either a starting position or are the tail MAXVALUE.
341-
342-
current_positions: a position-list representing the position IDs for
343-
this table at the evaluation_time.
344-
345-
evaluation_time: a datetime instance that represents the time the
346-
algorithm is running.
347-
348-
allowed_lifespan: a timedelta that represents how long a span of time
349-
a partition should seek to cover.
350-
351-
num_empty_partitions: the number of empty partitions to seek to keep at the
352-
tail, each aiming to span allowed_lifespan.
353336
"""
354337
log = logging.getLogger("plan_partition_changes")
355338

@@ -464,7 +447,7 @@ def plan_partition_changes(
464447
return results
465448

466449

467-
def should_run_changes(altered_partitions):
450+
def _should_run_changes(altered_partitions):
468451
"""Returns True if the changeset should run, otherwise returns False.
469452
470453
Evaluate the list from plan_partition_changes and determine if the set of
@@ -487,7 +470,14 @@ def should_run_changes(altered_partitions):
487470

488471

489472
def generate_sql_reorganize_partition_commands(table, changes):
490-
"""Generates SQL commands to reorganize table to apply the changes."""
473+
"""Generates SQL commands to reorganize table to apply the changes.
474+
475+
Args:
476+
477+
table: a types.Table object
478+
479+
changes: a list of objects implenting types.PlannedPartition
480+
"""
491481
log = logging.getLogger(f"generate_sql_reorganize_partition_commands:{table.name}")
492482

493483
modified_partitions = list()
@@ -548,3 +538,54 @@ def generate_sql_reorganize_partition_commands(table, changes):
548538
log.debug(f"Yielding {alter_cmd}")
549539

550540
yield alter_cmd
541+
542+
543+
def get_pending_sql_reorganize_partition_commands(
544+
*,
545+
table,
546+
partition_list,
547+
current_positions,
548+
allowed_lifespan,
549+
num_empty_partitions,
550+
evaluation_time,
551+
):
552+
"""Return a list of SQL commands to produce an optimally-partitioend table.
553+
554+
This algorithm is described in the README.md file as the Maintain Algorithm.
555+
556+
Args:
557+
558+
table: The table name and properties
559+
560+
partition_list: the currently-existing partition objects, each with
561+
a name and either a starting position or are the tail MAXVALUE.
562+
563+
current_positions: a position-list representing the position IDs for
564+
this table at the evaluation_time.
565+
566+
allowed_lifespan: a timedelta that represents how long a span of time
567+
a partition should seek to cover.
568+
569+
num_empty_partitions: the number of empty partitions to seek to keep at the
570+
tail, each aiming to span allowed_lifespan.
571+
572+
evaluation_time: a datetime instance that represents the time the
573+
algorithm is running.
574+
"""
575+
576+
log = logging.getLogger("get_pending_sql_reorganize_partition_commands")
577+
578+
partition_changes = _plan_partition_changes(
579+
partition_list,
580+
current_positions,
581+
evaluation_time,
582+
allowed_lifespan,
583+
num_empty_partitions,
584+
)
585+
586+
if not _should_run_changes(partition_changes):
587+
log.info(f"{table} does not need to be modified currently.")
588+
return list()
589+
590+
log.debug(f"{table} has changes waiting.")
591+
return generate_sql_reorganize_partition_commands(table, partition_changes)

0 commit comments

Comments
 (0)