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:
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user