starrocks-br 0.5.2__py3-none-any.whl → 0.7.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
starrocks_br/schema.py CHANGED
@@ -15,71 +15,117 @@
15
15
  from . import logger
16
16
 
17
17
 
18
- def initialize_ops_schema(db) -> None:
18
+ def initialize_ops_schema(
19
+ db, ops_database: str = "ops", table_inventory_entries: list[tuple[str, str, str]] | None = None
20
+ ) -> None:
19
21
  """Initialize the ops database and all required control tables.
20
22
 
21
- Creates empty ops tables. Does NOT populate with sample data.
22
- Users must manually insert their table inventory records.
23
+ Creates empty ops tables. Optionally populates table_inventory from entries.
24
+
25
+ Args:
26
+ db: Database connection
27
+ ops_database: Name of the ops database (defaults to "ops")
28
+ table_inventory_entries: Optional list of (group, database, table) tuples to bootstrap
23
29
  """
24
30
 
25
- logger.info("Creating ops database...")
26
- db.execute("CREATE DATABASE IF NOT EXISTS ops")
27
- logger.success("ops database created")
31
+ logger.info(f"Creating {ops_database} database...")
32
+ db.execute(f"CREATE DATABASE IF NOT EXISTS {ops_database}")
33
+ logger.success(f"{ops_database} database created")
34
+
35
+ logger.info(f"Creating {ops_database}.table_inventory...")
36
+ db.execute(get_table_inventory_schema(ops_database=ops_database))
37
+ logger.success(f"{ops_database}.table_inventory created")
38
+
39
+ logger.info(f"Creating {ops_database}.backup_history...")
40
+ db.execute(get_backup_history_schema(ops_database=ops_database))
41
+ logger.success(f"{ops_database}.backup_history created")
28
42
 
29
- logger.info("Creating ops.table_inventory...")
30
- db.execute(get_table_inventory_schema())
31
- logger.success("ops.table_inventory created")
43
+ logger.info(f"Creating {ops_database}.restore_history...")
44
+ db.execute(get_restore_history_schema(ops_database=ops_database))
45
+ logger.success(f"{ops_database}.restore_history created")
32
46
 
33
- logger.info("Creating ops.backup_history...")
34
- db.execute(get_backup_history_schema())
35
- logger.success("ops.backup_history created")
47
+ logger.info(f"Creating {ops_database}.run_status...")
48
+ db.execute(get_run_status_schema(ops_database=ops_database))
49
+ logger.success(f"{ops_database}.run_status created")
36
50
 
37
- logger.info("Creating ops.restore_history...")
38
- db.execute(get_restore_history_schema())
39
- logger.success("ops.restore_history created")
51
+ logger.info(f"Creating {ops_database}.backup_partitions...")
52
+ db.execute(get_backup_partitions_schema(ops_database=ops_database))
53
+ logger.success(f"{ops_database}.backup_partitions created")
40
54
 
41
- logger.info("Creating ops.run_status...")
42
- db.execute(get_run_status_schema())
43
- logger.success("ops.run_status created")
55
+ if table_inventory_entries:
56
+ logger.info(f"Bootstrapping {ops_database}.table_inventory from configuration...")
57
+ bootstrap_table_inventory(db, table_inventory_entries, ops_database=ops_database)
58
+ logger.success(
59
+ f"{ops_database}.table_inventory bootstrapped with {len(table_inventory_entries)} entries"
60
+ )
44
61
 
45
- logger.info("Creating ops.backup_partitions...")
46
- db.execute(get_backup_partitions_schema())
47
- logger.success("ops.backup_partitions created")
48
62
  logger.info("")
49
63
  logger.success("Schema initialized successfully!")
50
64
 
51
65
 
52
- def ensure_ops_schema(db) -> bool:
66
+ def ensure_ops_schema(db, ops_database: str = "ops") -> bool:
53
67
  """Ensure ops schema exists, creating it if necessary.
54
68
 
55
69
  Returns True if schema was created, False if it already existed.
56
70
  This is called automatically before backup/restore operations.
57
71
  """
58
72
  try:
59
- result = db.query("SHOW DATABASES LIKE 'ops'")
73
+ result = db.query(f"SHOW DATABASES LIKE '{ops_database}'")
60
74
 
61
75
  if not result:
62
- initialize_ops_schema(db)
76
+ initialize_ops_schema(db, ops_database=ops_database)
63
77
  return True
64
78
 
65
- db.execute("USE ops")
79
+ db.execute(f"USE {ops_database}")
66
80
  tables_result = db.query("SHOW TABLES")
67
81
 
68
82
  if not tables_result or len(tables_result) < 5:
69
- initialize_ops_schema(db)
83
+ initialize_ops_schema(db, ops_database=ops_database)
70
84
  return True
71
85
 
72
86
  return False
73
87
 
74
88
  except Exception:
75
- initialize_ops_schema(db)
89
+ initialize_ops_schema(db, ops_database=ops_database)
76
90
  return True
77
91
 
78
92
 
79
- def get_table_inventory_schema() -> str:
93
+ def bootstrap_table_inventory(
94
+ db, entries: list[tuple[str, str, str]], ops_database: str = "ops"
95
+ ) -> None:
96
+ """Bootstrap table_inventory table with entries from configuration.
97
+
98
+ Args:
99
+ db: Database connection
100
+ entries: List of (group, database, table) tuples
101
+ ops_database: Name of the ops database (defaults to "ops")
102
+ """
103
+ if not entries:
104
+ return
105
+
106
+ unique_databases = {database for _, database, _ in entries}
107
+
108
+ for database_name in unique_databases:
109
+ result = db.query(f"SHOW DATABASES LIKE '{database_name}'")
110
+ if not result:
111
+ logger.warning(
112
+ f"Database '{database_name}' does not exist. "
113
+ f"Table inventory entries will be created, but backups will fail until the database is created."
114
+ )
115
+
116
+ for group, database, table in entries:
117
+ sql = f"""
118
+ INSERT INTO {ops_database}.table_inventory
119
+ (inventory_group, database_name, table_name)
120
+ VALUES ('{group}', '{database}', '{table}')
121
+ """
122
+ db.execute(sql)
123
+
124
+
125
+ def get_table_inventory_schema(ops_database: str = "ops") -> str:
80
126
  """Get CREATE TABLE statement for table_inventory."""
81
- return """
82
- CREATE TABLE IF NOT EXISTS ops.table_inventory (
127
+ return f"""
128
+ CREATE TABLE IF NOT EXISTS {ops_database}.table_inventory (
83
129
  inventory_group STRING NOT NULL COMMENT "Group name for a set of tables",
84
130
  database_name STRING NOT NULL COMMENT "Database name",
85
131
  table_name STRING NOT NULL COMMENT "Table name, or '*' for all tables in database",
@@ -92,10 +138,10 @@ def get_table_inventory_schema() -> str:
92
138
  """
93
139
 
94
140
 
95
- def get_backup_history_schema() -> str:
141
+ def get_backup_history_schema(ops_database: str = "ops") -> str:
96
142
  """Get CREATE TABLE statement for backup_history."""
97
- return """
98
- CREATE TABLE IF NOT EXISTS ops.backup_history (
143
+ return f"""
144
+ CREATE TABLE IF NOT EXISTS {ops_database}.backup_history (
99
145
  label STRING NOT NULL COMMENT "Unique backup snapshot label",
100
146
  backup_type STRING NOT NULL COMMENT "Type of backup: full or incremental",
101
147
  status STRING NOT NULL COMMENT "Final backup status: FINISHED, FAILED, CANCELLED, TIMEOUT",
@@ -110,10 +156,10 @@ def get_backup_history_schema() -> str:
110
156
  """
111
157
 
112
158
 
113
- def get_restore_history_schema() -> str:
159
+ def get_restore_history_schema(ops_database: str = "ops") -> str:
114
160
  """Get CREATE TABLE statement for restore_history."""
115
- return """
116
- CREATE TABLE IF NOT EXISTS ops.restore_history (
161
+ return f"""
162
+ CREATE TABLE IF NOT EXISTS {ops_database}.restore_history (
117
163
  job_id STRING NOT NULL COMMENT "Unique restore job identifier",
118
164
  backup_label STRING NOT NULL COMMENT "Source backup snapshot label",
119
165
  restore_type STRING NOT NULL COMMENT "Type of restore: partition, table, or database",
@@ -130,10 +176,10 @@ def get_restore_history_schema() -> str:
130
176
  """
131
177
 
132
178
 
133
- def get_run_status_schema() -> str:
179
+ def get_run_status_schema(ops_database: str = "ops") -> str:
134
180
  """Get CREATE TABLE statement for run_status."""
135
- return """
136
- CREATE TABLE IF NOT EXISTS ops.run_status (
181
+ return f"""
182
+ CREATE TABLE IF NOT EXISTS {ops_database}.run_status (
137
183
  scope STRING NOT NULL COMMENT "Job scope: backup or restore",
138
184
  label STRING NOT NULL COMMENT "Job label or identifier",
139
185
  state STRING NOT NULL DEFAULT "ACTIVE" COMMENT "Job state: ACTIVE, FINISHED, FAILED, or CANCELLED",
@@ -145,12 +191,12 @@ def get_run_status_schema() -> str:
145
191
  """
146
192
 
147
193
 
148
- def get_backup_partitions_schema() -> str:
194
+ def get_backup_partitions_schema(ops_database: str = "ops") -> str:
149
195
  """Get CREATE TABLE statement for backup_partitions."""
150
- return """
151
- CREATE TABLE IF NOT EXISTS ops.backup_partitions (
196
+ return f"""
197
+ CREATE TABLE IF NOT EXISTS {ops_database}.backup_partitions (
152
198
  key_hash STRING NOT NULL COMMENT "MD5 hash of composite key (label, database_name, table_name, partition_name)",
153
- label STRING NOT NULL COMMENT "The backup label this partition belongs to. FK to ops.backup_history.label.",
199
+ label STRING NOT NULL COMMENT "The backup label this partition belongs to. FK to {ops_database}.backup_history.label.",
154
200
  database_name STRING NOT NULL COMMENT "The name of the database the partition belongs to.",
155
201
  table_name STRING NOT NULL COMMENT "The name of the table the partition belongs to.",
156
202
  partition_name STRING NOT NULL COMMENT "The name of the specific partition.",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: starrocks-br
3
- Version: 0.5.2
3
+ Version: 0.7.0a1
4
4
  Summary: StarRocks Backup and Restore automation tool
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -56,6 +56,7 @@ This tool adds **incremental backup capabilities** to StarRocks by leveraging na
56
56
  - ✅ **Complete operation tracking** - Every backup and restore is logged with status, timestamps, and error details
57
57
  - ✅ **Intelligent restore** - Automatically resolves backup chains (full + incremental) for you
58
58
  - ✅ **Inventory groups** - Organize tables into groups with different backup strategies
59
+ - ✅ **Backup lifecycle management** - Prune old backups with flexible retention policies (keep-last, older-than, specific snapshots)
59
60
  - ✅ **Job concurrency control** - Prevents conflicting operations
60
61
  - ✅ **Safe restores** - Atomic rename mechanism prevents data loss during restore
61
62
  - ✅ **Metadata management** - Dedicated `ops` database tracks all backup metadata and partition manifests
@@ -95,6 +96,15 @@ port: 9030 # MySQL protocol port
95
96
  user: "root" # Database user with backup/restore privileges
96
97
  database: "your_database" # Database containing tables to backup
97
98
  repository: "your_repo_name" # Repository created via CREATE REPOSITORY in StarRocks
99
+
100
+ # Optional: Define table inventory groups directly in config
101
+ table_inventory:
102
+ - group: "production"
103
+ tables:
104
+ - database: "mydb"
105
+ table: "users"
106
+ - database: "mydb"
107
+ table: "orders"
98
108
  ```
99
109
 
100
110
  Set password:
@@ -111,7 +121,11 @@ See [Configuration Reference](docs/configuration.md) for TLS and advanced option
111
121
  starrocks-br init --config config.yaml
112
122
  ```
113
123
 
114
- **Define inventory groups** (in StarRocks):
124
+ This creates the `ops` database and automatically populates table inventory from your config (if defined).
125
+
126
+ **Note:** If you modify the `table_inventory` in your config file, rerun `starrocks-br init --config config.yaml` to update the database.
127
+
128
+ **Alternative: Define inventory groups manually** (in StarRocks):
115
129
  ```sql
116
130
  INSERT INTO ops.table_inventory (inventory_group, database_name, table_name)
117
131
  VALUES
@@ -134,6 +148,15 @@ starrocks-br backup incremental --config config.yaml --group production
134
148
  starrocks-br restore --config config.yaml --target-label mydb_20251118_full
135
149
  ```
136
150
 
151
+ **Prune old backups:**
152
+ ```bash
153
+ # Keep only last 5 backups
154
+ starrocks-br prune --config config.yaml --keep-last 5
155
+
156
+ # Delete backups older than a date
157
+ starrocks-br prune --config config.yaml --older-than "2024-01-01 00:00:00"
158
+ ```
159
+
137
160
  See [Commands Reference](docs/commands.md) for all options.
138
161
 
139
162
  ## How It Works
@@ -0,0 +1,25 @@
1
+ starrocks_br/__init__.py,sha256=SeQqVuym4h6mvf4ar0UpBs_qDWbP0XOYH65Qj7WT4HI,600
2
+ starrocks_br/cli.py,sha256=X0qUWDsocBsZnH7HvtgEqH_ZicyUKmyBEHm3IqhTM8w,34243
3
+ starrocks_br/concurrency.py,sha256=k06-9hPdAayXGnN_9gfJNkdZTVGnFsHGsws5RK7GauE,6586
4
+ starrocks_br/config.py,sha256=JooRqqNm39UqbXSFqgFn3x84heOb-i0ZezNKpRTxqj0,5463
5
+ starrocks_br/db.py,sha256=abGG12e4JN4ydrz1ZdahKvOkk9CKbkGbkLnRxjUMFA8,5518
6
+ starrocks_br/error_handler.py,sha256=PnmjUWDzP5P_5SymT-cYTiyrSe8M0DDW4pXUNYv_HOc,15890
7
+ starrocks_br/exceptions.py,sha256=i1XUEmV1q60oTSN8u3xb7SQb3ZCaCcKvvAua4ZXd0lM,5061
8
+ starrocks_br/executor.py,sha256=w3jMKuchdqlNf5xDA6L-AagQ1yHgktzhJyARBu6xCp0,12238
9
+ starrocks_br/health.py,sha256=4CEX6nFKN1Vdc2cP_b89IVFZq6eaHKGMrs-FFDC4T9Q,1594
10
+ starrocks_br/history.py,sha256=UOQqw8-bKfImQkvq6_gIIb8i7R5BaIjKiDiku-koaas,3621
11
+ starrocks_br/labels.py,sha256=IqoNgPd-LCbZYGrVZxa0Lj9TNa8XcNCxp1oU2yiLHHU,2397
12
+ starrocks_br/logger.py,sha256=a44M_VDhVqnaU5sxqJ0tVoXBdY4tAmWG5P3DRNOdbWE,2004
13
+ starrocks_br/planner.py,sha256=B0K9Qi0ILoEJq_oc6q8sPBofALLSBpo94QgbjzCl7MU,12758
14
+ starrocks_br/prune.py,sha256=QbPYQDginF1wQDcxksvvC-en_qalg6uH4lN6ELdk5Nk,7101
15
+ starrocks_br/repository.py,sha256=hcl5ehoHdi0wgWKYl1wQYVjSpkdgrpSUPbDS2vV6BwM,1807
16
+ starrocks_br/restore.py,sha256=mLU42XbeSr6zcLOCrbiZA4JXpwBBHITJCD4DpZcFS9w,26654
17
+ starrocks_br/schema.py,sha256=KCQEm6h6umEWA1lb80_Sfa8ZDBARMcWNZYcF2UAlMLs,9072
18
+ starrocks_br/timezone.py,sha256=DLoOJ2-Z65a__PEcZS1eYauVIbRJNWOOX5lpfdHfqGc,4150
19
+ starrocks_br/utils.py,sha256=bmEZpD_CQ1_7hy51ZkRG7KKYOglhqW3EZYsWwFPUPow,2749
20
+ starrocks_br-0.7.0a1.dist-info/licenses/LICENSE,sha256=HV8aogcPFdRayUZanMcDj73f-B3qg2YstudemA_Qi5U,11369
21
+ starrocks_br-0.7.0a1.dist-info/METADATA,sha256=UVEsR7lD3jWosNhEa6PN19WsweGjvE7UuO99sI7Cuow,6777
22
+ starrocks_br-0.7.0a1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
23
+ starrocks_br-0.7.0a1.dist-info/entry_points.txt,sha256=AKUt01G2MAlh85s1Q9kNQDOUio14kaTnT3dmg9gjdNg,54
24
+ starrocks_br-0.7.0a1.dist-info/top_level.txt,sha256=CU1tGVo0kjulhDr761Sndg-oTeRKsisDnWm8UG95aBE,13
25
+ starrocks_br-0.7.0a1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,24 +0,0 @@
1
- starrocks_br/__init__.py,sha256=SeQqVuym4h6mvf4ar0UpBs_qDWbP0XOYH65Qj7WT4HI,600
2
- starrocks_br/cli.py,sha256=9DQzFDYwqDVfoQSNamHBtQrwBKH99agsIFWrCs096wM,23496
3
- starrocks_br/concurrency.py,sha256=aLHLjXy8ccmtfOXUuL-HJx_xQYIR0lpQE4TI4LI9y1k,6130
4
- starrocks_br/config.py,sha256=6A4BdHC7OT6RQSpK_cZ_8e8M6oHIMJwu6jKDa4ZtHRg,2822
5
- starrocks_br/db.py,sha256=abGG12e4JN4ydrz1ZdahKvOkk9CKbkGbkLnRxjUMFA8,5518
6
- starrocks_br/error_handler.py,sha256=vHNaEiLkTVBkhcrNJyjboaqikpxeTMA0ZsNsE01ysB8,13657
7
- starrocks_br/exceptions.py,sha256=Z9zoiCdSjKAxYKIKf0rwYjTlkoCichIz7WwoFIfnmi8,4482
8
- starrocks_br/executor.py,sha256=aQA6lQuUc0TGy9CqqpAi9f7JDJsdwatmI-TvETuFTPs,12016
9
- starrocks_br/health.py,sha256=4CEX6nFKN1Vdc2cP_b89IVFZq6eaHKGMrs-FFDC4T9Q,1594
10
- starrocks_br/history.py,sha256=FM8uwqjIuDbKYJSf1XKr1Sila98a6uz1CESD2MsVjtI,3536
11
- starrocks_br/labels.py,sha256=93AROzHxTa5eCEVZlqJi9Jjv7w-YpYTANqTu-n3ujP8,2234
12
- starrocks_br/logger.py,sha256=a44M_VDhVqnaU5sxqJ0tVoXBdY4tAmWG5P3DRNOdbWE,2004
13
- starrocks_br/planner.py,sha256=zJwOx16y3Chn_WEmPgKdJ_Zfy-8Hfnp_w212qdrfxao,11326
14
- starrocks_br/repository.py,sha256=jYzu2EMR7RPp86c6PkuHTA-cld6qX-Jj0yTD-lryZR0,1823
15
- starrocks_br/restore.py,sha256=B9m6bFONyUiUGTYnb6ac3CUpW-Ev-S820-q-LD7R5Po,20677
16
- starrocks_br/schema.py,sha256=KayDhOL3NQq_ShwCvGrTxbFkvX7BaBybfEAe2Dxuuu0,6771
17
- starrocks_br/timezone.py,sha256=DLoOJ2-Z65a__PEcZS1eYauVIbRJNWOOX5lpfdHfqGc,4150
18
- starrocks_br/utils.py,sha256=bmEZpD_CQ1_7hy51ZkRG7KKYOglhqW3EZYsWwFPUPow,2749
19
- starrocks_br-0.5.2.dist-info/licenses/LICENSE,sha256=HV8aogcPFdRayUZanMcDj73f-B3qg2YstudemA_Qi5U,11369
20
- starrocks_br-0.5.2.dist-info/METADATA,sha256=Np4XYVJQmW3hkIkpbfCeOvTZmFHLLYLzUqUV9ShHU6A,5931
21
- starrocks_br-0.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- starrocks_br-0.5.2.dist-info/entry_points.txt,sha256=AKUt01G2MAlh85s1Q9kNQDOUio14kaTnT3dmg9gjdNg,54
23
- starrocks_br-0.5.2.dist-info/top_level.txt,sha256=CU1tGVo0kjulhDr761Sndg-oTeRKsisDnWm8UG95aBE,13
24
- starrocks_br-0.5.2.dist-info/RECORD,,