Skip to content

Commit 0951fb1

Browse files
authored
V0.2.2 (#25)
* Don't require PyMySQL, as it's an optional runtime dependency now * Make logging more specific if we turn down the level from INFO to WARNING * Don't use --noop if read-only, let's explicitly just do statistics * Make pyyaml an optional dependency for CircleCI / tests * Update README to note the extra dependency * Permit Stats to work even if there are misbehaving tables
1 parent d72648d commit 0951fb1

File tree

6 files changed

+71
-32
lines changed

6 files changed

+71
-32
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
executor: python/default
99
steps:
1010
- checkout
11-
- run: pip install --editable .
11+
- run: pip install --editable ".[pymysql]"
1212
- run:
1313
name: make test-reesults dir
1414
command: |

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Similar tools:
2020
cd mariadb-sequential-partition-manager-py
2121
→ python3 -m venv .venv
2222
. .venv/bin/activate
23-
→ python3 -m pip install .
23+
→ python3 -m pip install ".[pymysql]"
2424
→ tee /tmp/partman.conf.yml <<EOF
2525
partitionmanager:
2626
num_empty: 2
@@ -51,7 +51,7 @@ dogs:
5151
cd mariadb-sequential-partition-manager-py
5252
→ python3 -m venv .venv
5353
. .venv/bin/activate
54-
→ python3 -m pip install --editable .
54+
→ python3 -m pip install --editable ".[pymysql]"
5555
→ partition-manager --log-level=debug \
5656
--mariadb test_tools/fake_mariadb.sh \
5757
maintain --noop --table tablename

partitionmanager/cli.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,14 @@ def all_configured_tables_are_compatible(conf):
156156
Returns True only if all are compatible, otherwise logs errors and returns
157157
False.
158158
"""
159+
log = logging.getLogger("all_configured_tables_are_compatible")
160+
159161
problems = dict()
160162
for table in conf.tables:
161163
table_problems = pm_tap.get_table_compatibility_problems(conf.dbcmd, table)
162164
if table_problems:
163165
problems[table.name] = table_problems
164-
logging.error(f"Cannot proceed: {table} {table_problems}")
166+
log.error(f"Cannot proceed: {table} {table_problems}")
165167
return len(problems) == 0
166168

167169

@@ -282,8 +284,10 @@ def do_partition(conf):
282284

283285
# Preflight
284286
if is_read_only(conf):
285-
log.info("Database is read-only, forcing noop mode")
286-
conf.noop = True
287+
log.info("Database is read-only, only emitting statistics")
288+
if conf.prometheus_stats_path:
289+
do_stats(conf)
290+
return dict()
287291

288292
if not all_configured_tables_are_compatible(conf):
289293
return dict()
@@ -355,17 +359,22 @@ def do_partition(conf):
355359
)
356360

357361
if conf.prometheus_stats_path:
358-
do_stats(conf, metrics)
362+
do_stats(conf, metrics=metrics)
359363
return all_results
360364

361365

362366
def do_stats(conf, metrics=partitionmanager.stats.PrometheusMetrics()):
363367
"""Populates a metrics object from the tables in the configuration."""
364-
if not all_configured_tables_are_compatible(conf):
365-
return dict()
368+
369+
log = logging.getLogger("do_stats")
366370

367371
all_results = dict()
368372
for table in conf.tables:
373+
table_problems = pm_tap.get_table_compatibility_problems(conf.dbcmd, table)
374+
if table_problems:
375+
log.error(f"Cannot proceed: {table} {table_problems}")
376+
continue
377+
369378
map_data = pm_tap.get_partition_map(conf.dbcmd, table)
370379
statistics = partitionmanager.stats.get_statistics(
371380
map_data["partitions"], conf.curtime, table
@@ -433,7 +442,8 @@ def do_stats(conf, metrics=partitionmanager.stats.PrometheusMetrics()):
433442
def main():
434443
"""Start here."""
435444
args = PARSER.parse_args()
436-
logging.basicConfig(level=args.log_level)
445+
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
446+
logging.basicConfig(level=args.log_level, format=log_format)
437447
if "func" not in args:
438448
PARSER.print_help()
439449
return

partitionmanager/table_append_partition.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ def _calculate_start_time(last_changed_time, evaluation_time, allowed_lifespan):
361361

362362

363363
def _plan_partition_changes(
364+
table,
364365
partition_list,
365366
current_position,
366367
evaluation_time,
@@ -373,7 +374,7 @@ def _plan_partition_changes(
373374
requirements, using an estimate as to the rate of fill from the supplied
374375
partition_list, current_position, and evaluation_time.
375376
"""
376-
log = logging.getLogger("plan_partition_changes")
377+
log = logging.getLogger(f"plan_partition_changes:{table.name}")
377378

378379
filled_partitions, active_partition, empty_partitions = _split_partitions_around_position(
379380
partition_list, current_position
@@ -526,14 +527,14 @@ def _plan_partition_changes(
526527
return results
527528

528529

529-
def _should_run_changes(altered_partitions):
530+
def _should_run_changes(table, altered_partitions):
530531
"""Returns True if the changeset should run, otherwise returns False.
531532
532533
Evaluate the list from plan_partition_changes and determine if the set of
533534
changes should be performed - if all the changes are minor, they shouldn't
534535
be run.
535536
"""
536-
log = logging.getLogger("should_run_changes")
537+
log = logging.getLogger(f"should_run_changes:{table.name}")
537538

538539
for p in altered_partitions:
539540
if isinstance(p, partitionmanager.types.NewPlannedPartition):
@@ -650,17 +651,20 @@ def get_pending_sql_reorganize_partition_commands(
650651
algorithm is running.
651652
"""
652653

653-
log = logging.getLogger("get_pending_sql_reorganize_partition_commands")
654+
log = logging.getLogger(
655+
f"get_pending_sql_reorganize_partition_commands:{table.name}"
656+
)
654657

655658
partition_changes = _plan_partition_changes(
659+
table,
656660
partition_list,
657661
current_position,
658662
evaluation_time,
659663
allowed_lifespan,
660664
num_empty_partitions,
661665
)
662666

663-
if not _should_run_changes(partition_changes):
667+
if not _should_run_changes(table, partition_changes):
664668
log.info(f"{table} does not need to be modified currently.")
665669
return list()
666670

partitionmanager/table_append_partition_test.py

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ def test_predict_forward_time(self):
497497
def test_plan_partition_changes_no_empty_partitions(self):
498498
with self.assertRaises(NoEmptyPartitionsAvailableException):
499499
_plan_partition_changes(
500+
Table("table"),
500501
[mkPPart("p_20201231", 0), mkPPart("p_20210102", 200)],
501502
mkPos(50),
502503
datetime(2021, 1, 1, tzinfo=timezone.utc),
@@ -505,8 +506,9 @@ def test_plan_partition_changes_no_empty_partitions(self):
505506
)
506507

507508
def test_plan_partition_changes_imminent(self):
508-
with self.assertLogs("plan_partition_changes", level="INFO") as logctx:
509+
with self.assertLogs("plan_partition_changes:table", level="INFO") as logctx:
509510
planned = _plan_partition_changes(
511+
Table("table"),
510512
[
511513
mkPPart("p_20201231", 100),
512514
mkPPart("p_20210102", 200),
@@ -521,7 +523,7 @@ def test_plan_partition_changes_imminent(self):
521523
self.assertEqual(
522524
logctx.output,
523525
[
524-
"INFO:plan_partition_changes:Start-of-fill predicted at "
526+
"INFO:plan_partition_changes:table:Start-of-fill predicted at "
525527
"2021-01-03 which is not 2021-01-02. This change will be marked "
526528
"as important to ensure that p_20210102: (200) is moved to "
527529
"2021-01-03"
@@ -545,8 +547,9 @@ def test_plan_partition_changes_imminent(self):
545547
)
546548

547549
def test_plan_partition_changes_wildly_off_dates(self):
548-
with self.assertLogs("plan_partition_changes", level="INFO") as logctx:
550+
with self.assertLogs("plan_partition_changes:table", level="INFO") as logctx:
549551
planned = _plan_partition_changes(
552+
Table("table"),
550553
[
551554
mkPPart("p_20201231", 100),
552555
mkPPart("p_20210104", 200),
@@ -561,7 +564,7 @@ def test_plan_partition_changes_wildly_off_dates(self):
561564
self.assertEqual(
562565
logctx.output,
563566
[
564-
"INFO:plan_partition_changes:Start-of-fill predicted at "
567+
"INFO:plan_partition_changes:table:Start-of-fill predicted at "
565568
"2021-01-02 which is not 2021-01-04. This change will be marked "
566569
"as important to ensure that p_20210104: (200) is moved to "
567570
"2021-01-02"
@@ -583,6 +586,7 @@ def test_plan_partition_changes_wildly_off_dates(self):
583586

584587
def test_plan_partition_changes_long_delay(self):
585588
planned = _plan_partition_changes(
589+
Table("table"),
586590
[
587591
mkPPart("p_20210101", 100),
588592
mkPPart("p_20210415", 200),
@@ -610,6 +614,7 @@ def test_plan_partition_changes_long_delay(self):
610614
def test_plan_partition_changes_short_names(self):
611615
self.maxDiff = None
612616
planned = _plan_partition_changes(
617+
Table("table"),
613618
[
614619
mkPPart("p_2019", 1912499867),
615620
mkPPart("p_2020", 8890030931),
@@ -651,6 +656,7 @@ def test_plan_partition_changes_short_names(self):
651656

652657
def test_plan_partition_changes_bespoke_names(self):
653658
planned = _plan_partition_changes(
659+
Table("table"),
654660
[mkPPart("p_start", 100), mkTailPart("p_future")],
655661
mkPos(50),
656662
datetime(2021, 1, 6, tzinfo=timezone.utc),
@@ -686,6 +692,7 @@ def test_plan_partition_changes_bespoke_names(self):
686692
def test_plan_partition_changes(self):
687693
self.maxDiff = None
688694
planned = _plan_partition_changes(
695+
Table("table"),
689696
[
690697
mkPPart("p_20201231", 100),
691698
mkPPart("p_20210102", 200),
@@ -710,6 +717,7 @@ def test_plan_partition_changes(self):
710717

711718
self.assertEqual(
712719
_plan_partition_changes(
720+
Table("table"),
713721
[
714722
mkPPart("p_20201231", 100),
715723
mkPPart("p_20210102", 200),
@@ -739,6 +747,7 @@ def test_plan_partition_changes_misprediction(self):
739747
match reality. """
740748
self.maxDiff = None
741749
planned = _plan_partition_changes(
750+
Table("table"),
742751
[
743752
mkPPart("p_20210505", 9505010028),
744753
mkPPart("p_20210604", 10152257517),
@@ -770,25 +779,32 @@ def test_plan_partition_changes_misprediction(self):
770779
def test_should_run_changes(self):
771780
self.assertFalse(
772781
_should_run_changes(
773-
[ChangePlannedPartition(mkPPart("p_20210102", 200)).set_position([300])]
782+
Table("table"),
783+
[
784+
ChangePlannedPartition(mkPPart("p_20210102", 200)).set_position(
785+
[300]
786+
)
787+
],
774788
)
775789
)
776790

777791
self.assertFalse(
778792
_should_run_changes(
793+
Table("table"),
779794
[
780795
ChangePlannedPartition(mkPPart("p_20210102", 200)).set_position(
781796
[300]
782797
),
783798
ChangePlannedPartition(mkPPart("p_20210109", 1000)).set_position(
784799
[1300]
785800
),
786-
]
801+
],
787802
)
788803
)
789-
with self.assertLogs("should_run_changes", level="DEBUG") as logctx:
804+
with self.assertLogs("should_run_changes:table", level="DEBUG") as logctx:
790805
self.assertTrue(
791806
_should_run_changes(
807+
Table("table"),
792808
[
793809
ChangePlannedPartition(mkPPart("p_20210102", 200)).set_position(
794810
[302]
@@ -802,17 +818,21 @@ def test_should_run_changes(self):
802818
NewPlannedPartition()
803819
.set_position([662])
804820
.set_timestamp(datetime(2021, 1, 23, tzinfo=timezone.utc)),
805-
]
821+
],
806822
)
807823
)
808824
self.assertEqual(
809825
logctx.output,
810-
["DEBUG:should_run_changes:Add: [542] 2021-01-16 " "00:00:00+00:00 is new"],
826+
[
827+
"DEBUG:should_run_changes:table:Add: [542] 2021-01-16 "
828+
"00:00:00+00:00 is new"
829+
],
811830
)
812831

813-
with self.assertLogs("should_run_changes", level="DEBUG") as logctx:
832+
with self.assertLogs("should_run_changes:table", level="DEBUG") as logctx:
814833
self.assertTrue(
815834
_should_run_changes(
835+
Table("table"),
816836
[
817837
ChangePlannedPartition(mkPPart("p_20210102", 200)),
818838
NewPlannedPartition()
@@ -821,12 +841,15 @@ def test_should_run_changes(self):
821841
NewPlannedPartition()
822842
.set_position([662])
823843
.set_timestamp(datetime(2021, 1, 23, tzinfo=timezone.utc)),
824-
]
844+
],
825845
)
826846
)
827847
self.assertEqual(
828848
logctx.output,
829-
["DEBUG:should_run_changes:Add: [542] 2021-01-16 " "00:00:00+00:00 is new"],
849+
[
850+
"DEBUG:should_run_changes:table:Add: [542] 2021-01-16 "
851+
"00:00:00+00:00 is new"
852+
],
830853
)
831854

832855
def testgenerate_sql_reorganize_partition_commands_no_change(self):
@@ -976,6 +999,7 @@ def test_plan_andgenerate_sql_reorganize_partition_commands_with_future_partitio
976999
self
9771000
):
9781001
planned = _plan_partition_changes(
1002+
Table("table"),
9791003
[
9801004
mkPPart("p_20201231", 100),
9811005
mkPPart("p_20210104", 200),
@@ -999,7 +1023,7 @@ def test_plan_andgenerate_sql_reorganize_partition_commands_with_future_partitio
9991023

10001024
def test_get_pending_sql_reorganize_partition_commands_no_changes(self):
10011025
with self.assertLogs(
1002-
"get_pending_sql_reorganize_partition_commands", level="INFO"
1026+
"get_pending_sql_reorganize_partition_commands:plushies", level="INFO"
10031027
) as logctx:
10041028
cmds = get_pending_sql_reorganize_partition_commands(
10051029
table=Table("plushies"),
@@ -1017,7 +1041,7 @@ def test_get_pending_sql_reorganize_partition_commands_no_changes(self):
10171041
self.assertEqual(
10181042
logctx.output,
10191043
[
1020-
"INFO:get_pending_sql_reorganize_partition_commands:"
1044+
"INFO:get_pending_sql_reorganize_partition_commands:plushies:"
10211045
"Table plushies does not need to be modified currently."
10221046
],
10231047
)
@@ -1026,7 +1050,7 @@ def test_get_pending_sql_reorganize_partition_commands_no_changes(self):
10261050

10271051
def test_get_pending_sql_reorganize_partition_commands_with_changes(self):
10281052
with self.assertLogs(
1029-
"get_pending_sql_reorganize_partition_commands", level="DEBUG"
1053+
"get_pending_sql_reorganize_partition_commands:plushies", level="DEBUG"
10301054
) as logctx:
10311055
cmds = get_pending_sql_reorganize_partition_commands(
10321056
table=Table("plushies"),
@@ -1044,7 +1068,7 @@ def test_get_pending_sql_reorganize_partition_commands_with_changes(self):
10441068
self.assertEqual(
10451069
logctx.output,
10461070
[
1047-
"DEBUG:get_pending_sql_reorganize_partition_commands:"
1071+
"DEBUG:get_pending_sql_reorganize_partition_commands:plushies:"
10481072
"Table plushies has changes waiting."
10491073
],
10501074
)

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
zip_safe=False,
2020
include_package_data=True,
2121
python_requires=">=3.6",
22-
install_requires=["PyMySQL >= 1.0.2", "pyyaml"],
22+
install_requires=["pyyaml"],
23+
extras_require={"pymysql": ["PyMySQL >= 1.0.2"]},
2324
packages=["partitionmanager"],
2425
entry_points={"console_scripts": ["partition-manager=partitionmanager.cli:main"]},
2526
)

0 commit comments

Comments
 (0)