Protect against None timestamps in Valkey layer (#6993)
Signed-off-by: Brennan Cathcart <brennancathcart@gmail.com>
This commit is contained in:
@@ -299,13 +299,8 @@ class ValkeyDB(VectorStoreBase):
|
||||
# Create the key for the hash
|
||||
key = f"{self.prefix}:{id}"
|
||||
|
||||
# Check for required fields and provide defaults if missing
|
||||
if "data" not in payload:
|
||||
# Silently use default value for missing 'data' field
|
||||
pass
|
||||
|
||||
# Ensure created_at is present
|
||||
if "created_at" not in payload:
|
||||
# Default created_at when missing or None to current time
|
||||
if not payload.get("created_at"):
|
||||
payload["created_at"] = datetime.now(pytz.timezone(self.timezone)).isoformat()
|
||||
|
||||
# Prepare the hash data
|
||||
@@ -499,13 +494,8 @@ class ValkeyDB(VectorStoreBase):
|
||||
try:
|
||||
key = f"{self.prefix}:{vector_id}"
|
||||
|
||||
# Check for required fields and provide defaults if missing
|
||||
if "data" not in payload:
|
||||
# Silently use default value for missing 'data' field
|
||||
pass
|
||||
|
||||
# Ensure created_at is present
|
||||
if "created_at" not in payload:
|
||||
# Default created_at when missing or None to current time
|
||||
if not payload.get("created_at"):
|
||||
payload["created_at"] = datetime.now(pytz.timezone(self.timezone)).isoformat()
|
||||
|
||||
# Prepare the hash data
|
||||
@@ -521,7 +511,7 @@ class ValkeyDB(VectorStoreBase):
|
||||
hash_data["embedding"] = np.array(vector, dtype=np.float32).tobytes()
|
||||
|
||||
# Add updated_at if available
|
||||
if "updated_at" in payload:
|
||||
if payload.get("updated_at"):
|
||||
hash_data["updated_at"] = int(datetime.fromisoformat(payload["updated_at"]).timestamp())
|
||||
|
||||
# Add optional fields
|
||||
|
||||
@@ -158,6 +158,32 @@ def test_insert_handles_missing_created_at(valkey_db, mock_valkey_client):
|
||||
assert "created_at" in kwargs["mapping"] # Should be added automatically
|
||||
|
||||
|
||||
def test_insert_and_update_with_none_timestamps(valkey_db, mock_valkey_client):
|
||||
"""Regression: a None timestamp must not crash insert() or update().
|
||||
|
||||
A None created_at falls back to now and a None updated_at is skipped, so
|
||||
neither reaches fromisoformat() which only accepts a str.
|
||||
"""
|
||||
vector = np.random.rand(1536).tolist()
|
||||
|
||||
valkey_db.insert(
|
||||
vectors=[vector],
|
||||
payloads=[{"hash": "h", "data": "d", "created_at": None, "updated_at": None}],
|
||||
ids=["id1"],
|
||||
)
|
||||
_, insert_kwargs = mock_valkey_client.hset.call_args
|
||||
assert isinstance(insert_kwargs["mapping"]["created_at"], int)
|
||||
|
||||
valkey_db.update(
|
||||
vector_id="id1",
|
||||
vector=vector,
|
||||
payload={"hash": "h", "data": "d", "created_at": None, "updated_at": None},
|
||||
)
|
||||
_, update_kwargs = mock_valkey_client.hset.call_args
|
||||
assert isinstance(update_kwargs["mapping"]["created_at"], int)
|
||||
assert "updated_at" not in update_kwargs["mapping"]
|
||||
|
||||
|
||||
def test_delete(valkey_db, mock_valkey_client):
|
||||
"""Test deleting a vector."""
|
||||
# Call delete
|
||||
|
||||
Reference in New Issue
Block a user