Implement workspace history reconciliation

This commit is contained in:
2026-03-03 17:35:45 +00:00
parent 2898d9e832
commit 18351abb00
14 changed files with 556 additions and 57 deletions

View File

@@ -14,6 +14,7 @@ from core.models import (
WorkspaceMetricSnapshot,
)
from core.views.workspace import _conversation_for_person
from core.workspace import compact_snapshot_rows
def _score_from_lag(lag_ms, target_hours=4):
@@ -219,6 +220,7 @@ class Command(BaseCommand):
parser.add_argument("--limit", type=int, default=200000)
parser.add_argument("--dry-run", action="store_true", default=False)
parser.add_argument("--no-reset", action="store_true", default=False)
parser.add_argument("--skip-compact", action="store_true", default=False)
def handle(self, *args, **options):
days = max(1, int(options.get("days") or 365))
@@ -229,6 +231,7 @@ class Command(BaseCommand):
limit = max(1, int(options.get("limit") or 200000))
dry_run = bool(options.get("dry_run"))
reset = not bool(options.get("no_reset"))
compact_enabled = not bool(options.get("skip_compact"))
today_start = dj_timezone.now().astimezone(timezone.utc).replace(
hour=0,
minute=0,
@@ -250,6 +253,7 @@ class Command(BaseCommand):
deleted = 0
snapshots_created = 0
checkpoints_total = 0
compacted_deleted = 0
for person in people:
identifiers_qs = PersonIdentifier.objects.filter(user=person.user, person=person)
@@ -410,6 +414,28 @@ class Command(BaseCommand):
"participant_feedback",
]
)
if compact_enabled:
snapshot_rows = list(
WorkspaceMetricSnapshot.objects.filter(conversation=conversation)
.order_by("computed_at", "id")
.values("id", "computed_at", "source_event_ts")
)
now_ts_ms = int(dj_timezone.now().timestamp() * 1000)
keep_ids = compact_snapshot_rows(
snapshot_rows=snapshot_rows,
now_ts_ms=now_ts_ms,
cutoff_ts_ms=cutoff_ts,
)
if keep_ids:
compacted_deleted += (
WorkspaceMetricSnapshot.objects.filter(conversation=conversation)
.exclude(id__in=list(keep_ids))
.delete()[0]
)
else:
compacted_deleted += WorkspaceMetricSnapshot.objects.filter(
conversation=conversation
).delete()[0]
self.stdout.write(
self.style.SUCCESS(
@@ -418,6 +444,8 @@ class Command(BaseCommand):
f"checkpoints={checkpoints_total} "
f"created={snapshots_created} "
f"deleted={deleted} "
f"compacted_deleted={compacted_deleted} "
f"compact_enabled={compact_enabled} "
f"reset={reset} dry_run={dry_run} "
f"days={days} step_messages={step_messages} limit={limit}"
)