* Reduces the passed in array of servers by the rules of the "Max Staleness" specification * found here: * * @see https://github.com/mongodb/specifications/blob/master/source/max-staleness/max-staleness.md * * @param readPreference - The read preference providing max staleness guidance * @para
( readPreference: ReadPreference, topologyDescription: TopologyDescription, servers: ServerDescription[] )
| 117 | * @returns The list of servers that satisfy the requirements of max staleness |
| 118 | */ |
| 119 | function maxStalenessReducer( |
| 120 | readPreference: ReadPreference, |
| 121 | topologyDescription: TopologyDescription, |
| 122 | servers: ServerDescription[] |
| 123 | ): ServerDescription[] { |
| 124 | if (readPreference.maxStalenessSeconds == null || readPreference.maxStalenessSeconds < 0) { |
| 125 | return servers; |
| 126 | } |
| 127 | |
| 128 | const maxStaleness = readPreference.maxStalenessSeconds; |
| 129 | const maxStalenessVariance = |
| 130 | (topologyDescription.heartbeatFrequencyMS + IDLE_WRITE_PERIOD) / 1000; |
| 131 | if (maxStaleness < maxStalenessVariance) { |
| 132 | throw new MongoInvalidArgumentError( |
| 133 | `Option "maxStalenessSeconds" must be at least ${maxStalenessVariance} seconds` |
| 134 | ); |
| 135 | } |
| 136 | |
| 137 | if (maxStaleness < SMALLEST_MAX_STALENESS_SECONDS) { |
| 138 | throw new MongoInvalidArgumentError( |
| 139 | `Option "maxStalenessSeconds" must be at least ${SMALLEST_MAX_STALENESS_SECONDS} seconds` |
| 140 | ); |
| 141 | } |
| 142 | |
| 143 | if (topologyDescription.type === TopologyType.ReplicaSetWithPrimary) { |
| 144 | const primary: ServerDescription = Array.from(topologyDescription.servers.values()).filter( |
| 145 | primaryFilter |
| 146 | )[0]; |
| 147 | |
| 148 | return servers.filter((server: ServerDescription) => { |
| 149 | const stalenessMS = |
| 150 | server.lastUpdateTime - |
| 151 | server.lastWriteDate - |
| 152 | (primary.lastUpdateTime - primary.lastWriteDate) + |
| 153 | topologyDescription.heartbeatFrequencyMS; |
| 154 | |
| 155 | const staleness = stalenessMS / 1000; |
| 156 | const maxStalenessSeconds = readPreference.maxStalenessSeconds ?? 0; |
| 157 | return staleness <= maxStalenessSeconds; |
| 158 | }); |
| 159 | } |
| 160 | |
| 161 | if (topologyDescription.type === TopologyType.ReplicaSetNoPrimary) { |
| 162 | if (servers.length === 0) { |
| 163 | return servers; |
| 164 | } |
| 165 | |
| 166 | const sMax = servers.reduce((max: ServerDescription, s: ServerDescription) => |
| 167 | s.lastWriteDate > max.lastWriteDate ? s : max |
| 168 | ); |
| 169 | |
| 170 | return servers.filter((server: ServerDescription) => { |
| 171 | const stalenessMS = |
| 172 | sMax.lastWriteDate - server.lastWriteDate + topologyDescription.heartbeatFrequencyMS; |
| 173 | |
| 174 | const staleness = stalenessMS / 1000; |
| 175 | const maxStalenessSeconds = readPreference.maxStalenessSeconds ?? 0; |
| 176 | return staleness <= maxStalenessSeconds; |
no test coverage detected