SIENTIAPDE-2007 SIENTIAPDE-2007: Compare native datetime in load_latest_data $gt filter and bump sientia_do pin to 1.12.2

Notification.timestamp is now stored as a native BSON Date instead of a
string, so load_latest_data must parse the ISO string coming from Redis
back to datetime before building the $gt filter, or the comparison
silently breaks (BSON String vs Date always evaluates False). Also fixes
put_last_data_timestamp, which would otherwise raise TypeError trying to
json.dumps a pandas Timestamp when persisting the new watermark to Redis.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Eduardo Rios
2026-08-12 13:45:38 -03:00
parent 7352b1c1df
commit c3cd58028c
6 changed files with 79 additions and 29 deletions

View File

@@ -2,7 +2,7 @@ from temporalio import activity, workflow
with workflow.unsafe.imports_passed_through():
import traceback
from datetime import UTC
from datetime import UTC, datetime
from logging import Logger
from typing import Any
@@ -452,7 +452,8 @@ class MongoDB(SientiaMonitoring):
Required fields:
- metadata (dict[str, Any]): Workflow execution metadata
- collection_name (str): Name of the MongoDB collection
- last_data_timestamp (str | None): Last processed timestamp for filtering
- last_data_timestamp (str | None): Last processed timestamp
(ISO-format string) for filtering
- base_data_filter (dict[str, Any]): Base query filter conditions
Returns:
@@ -472,19 +473,14 @@ class MongoDB(SientiaMonitoring):
if last_data_timestamp is None:
data_filter = base_data_filter
else:
# ``notification_queue.timestamp`` is stored as a string in
# ``DATETIME_FORMAT_WITH_TZ`` (``Notification`` writes it as
# ``now().strftime(DATETIME_FORMAT_WITH_TZ)``). Coercing
# ``last_data_timestamp`` to ``datetime`` here would force a
# BSON ``String`` vs ``Date`` comparison, which always yields
# ``False`` (``String < Date`` in BSON sort order) and breaks
# incremental loading entirely. Comparing strings preserves the
# intended chronological filter because the format is
# lexicographically ordered when the timezone is fixed
# (``Notification.timestamp`` always uses UTC).
# ``notification_queue.timestamp`` is stored as a native BSON
# ``Date`` (``Notification.timestamp`` is a ``datetime``).
# ``last_data_timestamp`` arrives here as an ISO-format string
# (round-tripped through Redis), so it must be parsed back to
# ``datetime`` for the ``$gt`` comparison to be type-correct.
data_filter = {
**base_data_filter,
'timestamp': {'$gt': last_data_timestamp},
'timestamp': {'$gt': datetime.fromisoformat(last_data_timestamp)},
}
self.debug(f'Data filter: {data_filter}', metadata=metadata)

View File

@@ -335,6 +335,11 @@ class SlotManager(SientiaMonitoring):
self.debug(f'Last collected timestamp to insert: {last_data_timestamp}', metadata=metadata)
# ``timestamp`` is a native ``datetime``/``Timestamp`` (BSON Date from
# Mongo), which the Redis repository's plain ``json.dumps`` cannot
# serialize. Store it as an ISO-format string instead.
last_data_timestamp = last_data_timestamp.isoformat()
try:
self.redis_repository.set(key, last_data_timestamp, ttl=60 * 60 * 5)
except Exception as e: