31
31
from pymongo .server_type import SERVER_TYPE
32
32
33
33
34
+ def _validate_max_staleness (max_staleness ,
35
+ heartbeat_frequency ,
36
+ idle_write_period ):
37
+ if max_staleness < heartbeat_frequency + idle_write_period :
38
+ raise ConfigurationError (
39
+ "maxStalenessSeconds must be at least heartbeatFrequencyMS +"
40
+ " %d seconds. maxStalenessSeconds is set to %d,"
41
+ " heartbeatFrequencyMS is set to %d." % (
42
+ idle_write_period , max_staleness ,
43
+ heartbeat_frequency * 1000 ))
44
+
45
+
34
46
def _with_primary (max_staleness , selection ):
35
47
"""Apply max_staleness, in seconds, to a Selection with a known primary."""
36
48
primary = selection .primary
49
+ assert primary
50
+
51
+ # Server Selection Spec: If the TopologyType is ReplicaSetWithPrimary, a
52
+ # client MUST raise an error if maxStaleness < heartbeatFrequency +
53
+ # (primary's idleWritePeriod).
54
+ _validate_max_staleness (max_staleness ,
55
+ selection .heartbeat_frequency ,
56
+ primary .idle_write_period )
57
+
37
58
sds = []
38
59
39
60
for s in selection .server_descriptions :
@@ -54,9 +75,25 @@ def _with_primary(max_staleness, selection):
54
75
55
76
def _no_primary (max_staleness , selection ):
56
77
"""Apply max_staleness, in seconds, to a Selection with no known primary."""
78
+ # Secondary that's replicated the most recent writes.
57
79
smax = selection .secondary_with_max_last_write_date ()
80
+ if not smax :
81
+ # No secondaries and no primary, short-circuit out of here.
82
+ return selection .with_server_descriptions ([])
83
+
84
+ # Secondary we've most recently checked.
85
+ srecent = selection .secondary_with_max_last_update_time ()
86
+ assert srecent
87
+
58
88
sds = []
59
89
90
+ # Server Selection Spec: If the TopologyType is ReplicaSetNoPrimary, a
91
+ # client MUST raise an error if maxStaleness < heartbeatFrequency +
92
+ # (idleWritePeriod of secondary with greatest lastUpdateTime).
93
+ _validate_max_staleness (max_staleness ,
94
+ selection .heartbeat_frequency ,
95
+ srecent .idle_write_period )
96
+
60
97
for s in selection .server_descriptions :
61
98
if s .server_type == SERVER_TYPE .RSSecondary :
62
99
# See max-staleness.rst for explanation of this formula.
@@ -77,13 +114,6 @@ def select(max_staleness, selection):
77
114
if not max_staleness :
78
115
return selection
79
116
80
- # Server Selection Spec: "A driver MUST raise an error if the
81
- # TopologyType is ReplicaSetWithPrimary or ReplicaSetNoPrimary and
82
- # maxStalenessSeconds * 1000 is less than twice heartbeatFrequencyMS."
83
- if max_staleness < 2 * selection .heartbeat_frequency :
84
- raise ConfigurationError (
85
- "maxStalenessSeconds must be twice heartbeatFrequencyMS" )
86
-
87
117
if selection .primary :
88
118
return _with_primary (max_staleness , selection )
89
119
else :
0 commit comments