Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions datamasque/client/models/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from datetime import datetime
from enum import Enum
from typing import Any, Callable, Literal, NewType, Optional
from typing import Any, Callable, ClassVar, Literal, NewType, Optional

from pydantic import BaseModel, ConfigDict, Field, model_serializer, model_validator

Expand Down Expand Up @@ -195,6 +195,9 @@ class MongoConnectionConfig(ConnectionConfig):
mask_type: Literal["database"] = "database"
db_type: Literal["mongodb"] = "mongodb"

# Whether `retry_writes` is sent even when it equals this class's default.
always_send_retry_writes: ClassVar[bool] = False

@property
def database_type(self) -> DatabaseType:
return DatabaseType.mongodb
Expand Down Expand Up @@ -222,7 +225,7 @@ def _serialize(self, handler: Callable) -> dict:
d.pop("tls", None)
if not d.get("direct_connection"):
d.pop("direct_connection", None)
if d.get("retry_writes") == defaults["retry_writes"].default:
if not self.always_send_retry_writes and d.get("retry_writes") == defaults["retry_writes"].default:
d.pop("retry_writes", None)
if not d.get("replica_set"):
d.pop("replica_set", None)
Expand All @@ -241,15 +244,22 @@ def _strip_encrypted_password(cls, data: dict) -> dict:

class DocumentDbConnectionConfig(MongoConnectionConfig):
"""
Connection configuration for an AWS DocumentDB cluster.
Connection configuration for an Amazon DocumentDB cluster.

DocumentDB is MongoDB wire-compatible,
so it reuses `MongoConnectionConfig` (including the TLS handling)
and only differs by `db_type`/`database_type`.
so it reuses `MongoConnectionConfig` (including the TLS handling).
It differs by `db_type`/`database_type` and by `retry_writes`,
which defaults to `False` because DocumentDB engine versions before 8.0.2 reject retryable writes.

`retry_writes` is always sent. Some server versions store `true` for a DocumentDB connection
that leaves the field out, and DocumentDB then rejects the run-history insert.
"""

# Narrowing the inherited Literal is a deliberate Pydantic discriminator override.
db_type: Literal["documentdb"] = "documentdb" # type: ignore[assignment]
retry_writes: bool = False

always_send_retry_writes: ClassVar[bool] = True

@property
def database_type(self) -> DatabaseType:
Expand Down
18 changes: 15 additions & 3 deletions tests/test_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -1225,14 +1225,26 @@ def test_mongo_connection_sends_retry_writes_when_disabled():
assert api_dict["retry_writes"] is False


def test_documentdb_connection_sends_retry_writes_when_disabled():
"""A DocumentDB connection inherits retry_writes and sends it when disabled."""
conn = DocumentDbConnectionConfig(name="docdb", host="docdb.example", database="people", retry_writes=False)
def test_documentdb_connection_defaults_retry_writes_off_and_sends_it():
"""
DocumentDB engine versions before 8.0.2 reject retryable writes, so the config defaults them off.

The value is sent even though it equals the default, because some server versions store `true`
for a DocumentDB connection that leaves the field out.
"""
conn = DocumentDbConnectionConfig(name="docdb", host="docdb.example", database="people")
api_dict = conn.model_dump(exclude_none=True, by_alias=True, mode="json")
assert api_dict["db_type"] == "documentdb"
assert conn.retry_writes is False
assert api_dict["retry_writes"] is False


def test_documentdb_connection_sends_retry_writes_when_enabled():
conn = DocumentDbConnectionConfig(name="docdb", host="docdb.example", database="people", retry_writes=True)
api_dict = conn.model_dump(exclude_none=True, by_alias=True, mode="json")
assert api_dict["retry_writes"] is True


def test_mongo_connection_model_validate_blanks_encrypted_password():
payload = {
"id": "mongo-id-1",
Expand Down
Loading