Skip to content

Commit 5e09ae2

Browse files
committed
Update per reviews as of 10am PT 21 April, except DocString revisions.
1 parent c7c1664 commit 5e09ae2

File tree

5 files changed

+98
-30
lines changed

5 files changed

+98
-30
lines changed

README.md

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,43 @@ Similar tools:
1414
# Usage
1515

1616
```sh
17-
→ pip install --editable .
17+
→ git clone https://github.com/letsencrypt/mariadb-sequential-partition-manager-py.git
18+
cd mariadb-sequential-partition-manager-py
19+
→ python3 -m venv .venv
20+
. .venv/bin/activate
21+
→ python3 -m pip install .
22+
→ tee /tmp/partman.conf.yml <<EOF
23+
partitionmanager:
24+
num_empty: 2
25+
partition_period:
26+
days: 90
27+
dburl: "sql://user:password@localhost3306:/test_db"
28+
tables:
29+
cats: {}
30+
dogs:
31+
partition_period:
32+
days: 30
33+
prometheus_stats: "/tmp/prometheus-textcollect-partition-manager.prom"
34+
EOF
35+
→ partition-manager --config /tmp/partman.conf.yml add --noop
36+
INFO:root:No-op mode
37+
INFO:partition:Evaluating Table dogs (duration=30 days, 0:00:00) (pos={'id': 150})
38+
INFO:partition:Table dogs planned SQL: ALTER TABLE `dogs` REORGANIZE PARTITION `p_20201204` INTO (PARTITION `p_20210422` VALUES LESS THAN (221), PARTITION `p_20210522` VALUES LESS THAN MAXVALUE);
39+
40+
dogs:
41+
sql: ALTER TABLE `dogs` REORGANIZE PARTITION `p_20201204` INTO (PARTITION `p_20210422` VALUES LESS THAN (221), PARTITION `p_20210522` VALUES LESS THAN MAXVALUE);
42+
noop: True
43+
```
44+
45+
46+
## Hacking on this Project
47+
48+
```sh
49+
→ git clone https://github.com/letsencrypt/mariadb-sequential-partition-manager-py.git
50+
cd mariadb-sequential-partition-manager-py
51+
→ python3 -m venv .venv
52+
. .venv/bin/activate
53+
→ python3 -m pip install --editable .
1854
→ partition-manager --log-level=debug \
1955
--mariadb test_tools/fake_mariadb.sh \
2056
add --noop --table tablename
@@ -28,7 +64,8 @@ ALTER TABLE `dbname`.`tablename` REORGANIZE PARTITION `p_20201204` INTO (PARTITI
2864

2965
```
3066

31-
You can also use a yaml configuration file with the `--config` parameter of the form:
67+
# Configuration
68+
You can use a yaml configuration file with the `--config` parameter of the form:
3269
```yaml
3370
partitionmanager:
3471
dburl: sql://user:password@localhost/db-name
@@ -48,6 +85,7 @@ partitionmanager:
4885
table3:
4986
retention:
5087
days: 14
88+
table4: {}
5189
```
5290
5391
For tables which are either partitioned but not yet using this tool's schema, or which have no empty partitions, the `bootstrap` command can be useful for proposing alterations to run manually. Note that `bootstrap` proposes commands that are likely to require partial copies of each table, so likely they will require a maintenance period.
@@ -66,7 +104,16 @@ orders:
66104

67105
```
68106

69-
# Algorithm
107+
# Procedure
108+
109+
## Configuration Processing
110+
111+
- At start, if any configuration file specified as a CLI argument, read that configuration file to set all other values.
112+
- Then, process all remaining command line arguments, overriding values loaded from the configuration file in case of conflicts.
113+
- From those command-line arguments, determine whether to collect statistics `stats`, determine an initial partition layout `bootstrap`, or operate in the normal `add` mode.
114+
- Use the configuration information as inputs to the required algorithm.
115+
116+
## "Add" Algorithm
70117

71118
The core algorithm is implemented in a method `plan_partition_changes` in `table_append_partition.py`. That algorithm is:
72119

@@ -105,6 +152,14 @@ Procedure:
105152
- Append the new partition to the intended empty partition list.
106153
- Return the lists of non-empty partitions, the current empty partitions, and the post-algorithm intended empty partitions.
107154

155+
### "Add" Finalization
156+
157+
The results of the algorithm are converted into `ALTER` statements; if the user configured `--noop` they're emitted to console and the logs for each table. If not set to `--noop`, the application will execute the ALTERs at the database server and emit the results, including execution time as prometheus statistics if so configured.
158+
159+
## "Bootstrap" Algorithm
160+
161+
The bootstrap mode is a limited form of the "Add" Algorithm, using a temporary state file to determine rates-of-change. The bootstrap mode also does not limit itself to only affecting empty partitions, it can and will request changes that will prmopt row copies, in order to prepare a table for future use of the "Add" algorithm.
162+
108163
# TODOs
109164

110165
Lots:

partitionmanager/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
write_state_info,
1515
)
1616
from partitionmanager.table_append_partition import (
17-
evaluate_partition_changes,
1817
generate_sql_reorganize_partition_commands,
1918
get_current_positions,
2019
get_partition_map,
2120
plan_partition_changes,
21+
should_run_changes,
2222
table_is_compatible,
2323
)
2424
from partitionmanager.types import (
@@ -289,7 +289,7 @@ def do_partition(conf):
289289
conf.num_empty,
290290
)
291291

292-
if not evaluate_partition_changes(partition_changes):
292+
if not should_run_changes(partition_changes):
293293
log.info(f"{table} does not need to be modified currently.")
294294
continue
295295
log.debug(f"{table} has changes waiting.")

partitionmanager/table_append_partition.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ def plan_partition_changes(
338338
# increasing until we get to "now" and the active partition. "Now" actually
339339
# takes place _after_ active partition's start date (naturally), but
340340
# contains a position that is before the top of active, by definition. For
341-
# the rate processing to work, we need to cross the "now" and the active
341+
# the rate processing to work, we need to swap the "now" and the active
342342
# partition's dates and positions.
343343
rate_relevant_partitions = filled_partitions + [
344344
InstantPartition(active_partition.timestamp(), current_positions),
@@ -422,14 +422,13 @@ def plan_partition_changes(
422422
return results
423423

424424

425-
def evaluate_partition_changes(altered_partitions):
425+
def should_run_changes(altered_partitions):
426426
"""
427427
Evaluate the list from plan_partition_changes and determine if the set of
428428
changes should be performed - if all the changes are minor, they shouldn't
429-
be run. Returns True if the changeset should run, otherwise logs the reason
430-
for skipping and returns False
429+
be run. Returns True if the changeset should run, otherwise returns False.
431430
"""
432-
log = logging.getLogger("evaluate_partition_changes")
431+
log = logging.getLogger("should_run_changes")
433432

434433
for p in altered_partitions:
435434
if isinstance(p, NewPlannedPartition):
@@ -460,6 +459,7 @@ def generate_sql_reorganize_partition_commands(table, changes):
460459
if isinstance(p, NewPlannedPartition):
461460
new_partitions.append(p)
462461
else:
462+
assert not new_partitions, "Modified partitions must preceed new partitions"
463463
modified_partitions.append(p)
464464

465465
# If there's not at least one modification, bail out

partitionmanager/table_append_partition_test.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
UnexpectedPartitionException,
2020
)
2121
from partitionmanager.table_append_partition import (
22-
evaluate_partition_changes,
2322
generate_sql_reorganize_partition_commands,
2423
generate_weights,
2524
get_current_positions,
@@ -30,6 +29,7 @@
3029
plan_partition_changes,
3130
predict_forward_position,
3231
predict_forward_time,
32+
should_run_changes,
3333
split_partitions_around_positions,
3434
table_information_schema_is_compatible,
3535
table_is_compatible,
@@ -709,15 +709,15 @@ def test_plan_partition_changes(self):
709709
],
710710
)
711711

712-
def test_evaluate_partition_changes(self):
712+
def test_should_run_changes(self):
713713
self.assertFalse(
714-
evaluate_partition_changes(
714+
should_run_changes(
715715
[ChangePlannedPartition(mkPPart("p_20210102", 200)).set_position([300])]
716716
)
717717
)
718718

719719
self.assertFalse(
720-
evaluate_partition_changes(
720+
should_run_changes(
721721
[
722722
ChangePlannedPartition(mkPPart("p_20210102", 200)).set_position(
723723
[300]
@@ -728,9 +728,9 @@ def test_evaluate_partition_changes(self):
728728
]
729729
)
730730
)
731-
with self.assertLogs("evaluate_partition_changes", level="DEBUG") as logctx:
731+
with self.assertLogs("should_run_changes", level="DEBUG") as logctx:
732732
self.assertTrue(
733-
evaluate_partition_changes(
733+
should_run_changes(
734734
[
735735
ChangePlannedPartition(mkPPart("p_20210102", 200)).set_position(
736736
[302]
@@ -749,15 +749,12 @@ def test_evaluate_partition_changes(self):
749749
)
750750
self.assertEqual(
751751
logctx.output,
752-
[
753-
"DEBUG:evaluate_partition_changes:Add: [542] 2021-01-16 "
754-
"00:00:00+00:00 is new"
755-
],
752+
["DEBUG:should_run_changes:Add: [542] 2021-01-16 " "00:00:00+00:00 is new"],
756753
)
757754

758-
with self.assertLogs("evaluate_partition_changes", level="DEBUG") as logctx:
755+
with self.assertLogs("should_run_changes", level="DEBUG") as logctx:
759756
self.assertTrue(
760-
evaluate_partition_changes(
757+
should_run_changes(
761758
[
762759
ChangePlannedPartition(mkPPart("p_20210102", 200)),
763760
NewPlannedPartition()
@@ -771,10 +768,7 @@ def test_evaluate_partition_changes(self):
771768
)
772769
self.assertEqual(
773770
logctx.output,
774-
[
775-
"DEBUG:evaluate_partition_changes:Add: [542] 2021-01-16 "
776-
"00:00:00+00:00 is new"
777-
],
771+
["DEBUG:should_run_changes:Add: [542] 2021-01-16 " "00:00:00+00:00 is new"],
778772
)
779773

780774
def test_generate_sql_reorganize_partition_commands_no_change(self):
@@ -901,6 +895,25 @@ def test_generate_sql_reorganize_partition_commands_with_duplicate(self):
901895
)
902896
)
903897

898+
def test_generate_sql_reorganize_partition_commands_out_of_order(self):
899+
with self.assertRaises(AssertionError):
900+
list(
901+
generate_sql_reorganize_partition_commands(
902+
Table("table_with_out_of_order_changeset"),
903+
[
904+
ChangePlannedPartition(mkTailPart("past"))
905+
.set_position([800])
906+
.set_timestamp(datetime(2021, 1, 14, tzinfo=timezone.utc)),
907+
NewPlannedPartition()
908+
.set_position([1000])
909+
.set_timestamp(datetime(2021, 1, 15, tzinfo=timezone.utc)),
910+
ChangePlannedPartition(mkTailPart("future"))
911+
.set_position([1200])
912+
.set_timestamp(datetime(2021, 1, 16, tzinfo=timezone.utc)),
913+
],
914+
)
915+
)
916+
904917
def test_plan_and_generate_sql_reorganize_partition_commands_with_future_partition(
905918
self
906919
):

partitionmanager/tools.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ def iter_show_end(iterable):
1919
iterable -> (s0, false), (s1, false), ... (s_n, true).
2020
"""
2121
it = iter(iterable)
22-
last = next(it)
22+
prev = next(it)
2323
for val in it:
24-
yield last, False
25-
last = val
26-
yield last, True
24+
yield prev, False
25+
prev = val
26+
yield prev, True

0 commit comments

Comments
 (0)