|
4 | 4 |
|
5 | 5 | import pandas as pd |
6 | 6 | import shutil |
| 7 | +from datetime import datetime as dt |
| 8 | +import json |
| 9 | +import os |
7 | 10 |
|
8 | 11 | from typing import Dict, List |
9 | 12 | from data_pipeline.shared.run_context import RunContext |
@@ -157,7 +160,7 @@ def promote_semantic_version(run_context: RunContext) -> Dict: |
157 | 160 | report = init_report() |
158 | 161 |
|
159 | 162 | semantic_path = run_context.semantic_path |
160 | | - version_path = run_context.version_path |
| 163 | + version_path = run_context.version_path / "seller_semantic" |
161 | 164 |
|
162 | 165 | if version_path.exists(): |
163 | 166 | report["status"] = "failed" |
@@ -191,6 +194,57 @@ def promote_semantic_version(run_context: RunContext) -> Dict: |
191 | 194 | return report |
192 | 195 |
|
193 | 196 |
|
| 197 | +# ------------------------------------------------------------ |
| 198 | +# PUBLISHED ATOMIC POINTER |
| 199 | +# ------------------------------------------------------------ |
| 200 | + |
| 201 | + |
| 202 | +def activate_published_version(run_context: RunContext) -> Dict: |
| 203 | + """ |
| 204 | + Published version activation step. |
| 205 | +
|
| 206 | + Atomically updates the latest-version pointer to the newly promotedsemantic snapshot. <br> |
| 207 | + Guarantee BI dashboards read only fully published versions. |
| 208 | +
|
| 209 | + Chronological behavior: |
| 210 | +
|
| 211 | + - Initializes run-scoped reporting. |
| 212 | + - Builds the pointer payload with run lineage metadata. |
| 213 | + - Writes payload to a temporary pointer file. |
| 214 | + - Atomically swaps the temporary file into the latest pointer path. |
| 215 | + - Emits success signal when the swap completes. |
| 216 | +
|
| 217 | + Notes: |
| 218 | + - Uses temp-file + os.replace for atomicity. |
| 219 | + - Assumes version promotion has already succeeded. |
| 220 | + """ |
| 221 | + |
| 222 | + report = init_report() |
| 223 | + |
| 224 | + latest_path = run_context.latest_pointer_path |
| 225 | + tmp_path = latest_path.with_suffix(".tmp") |
| 226 | + |
| 227 | + payload = { |
| 228 | + "run_id": run_context.run_id, |
| 229 | + "version": f"v{run_context.run_id}", |
| 230 | + "published_at": dt.utcnow().isoformat(), |
| 231 | + } |
| 232 | + |
| 233 | + try: |
| 234 | + with open(tmp_path, "w") as file: |
| 235 | + json.dump(payload, file, indent=2) |
| 236 | + |
| 237 | + os.replace(tmp_path, latest_path) |
| 238 | + |
| 239 | + except Exception as e: |
| 240 | + report["status"] = "failed" |
| 241 | + log_error(str(e), report) |
| 242 | + |
| 243 | + log_info("Atomic pointer swap successful", report) |
| 244 | + |
| 245 | + return report |
| 246 | + |
| 247 | + |
194 | 248 | # ============================================================================= |
195 | 249 | # END OF SCRIPT |
196 | 250 | # ============================================================================= |
0 commit comments