@@ -113,7 +113,7 @@ function maxStalenessReducer(
113113 primaryFilter
114114 ) [ 0 ] ;
115115
116- return servers . reduce ( ( result : ServerDescription [ ] , server : ServerDescription ) => {
116+ return servers . filter ( ( server : ServerDescription ) => {
117117 const stalenessMS =
118118 server . lastUpdateTime -
119119 server . lastWriteDate -
@@ -122,12 +122,8 @@ function maxStalenessReducer(
122122
123123 const staleness = stalenessMS / 1000 ;
124124 const maxStalenessSeconds = readPreference . maxStalenessSeconds ?? 0 ;
125- if ( staleness <= maxStalenessSeconds ) {
126- result . push ( server ) ;
127- }
128-
129- return result ;
130- } , [ ] ) ;
125+ return staleness <= maxStalenessSeconds ;
126+ } ) ;
131127 }
132128
133129 if ( topologyDescription . type === TopologyType . ReplicaSetNoPrimary ) {
@@ -139,40 +135,38 @@ function maxStalenessReducer(
139135 s . lastWriteDate > max . lastWriteDate ? s : max
140136 ) ;
141137
142- return servers . reduce ( ( result : ServerDescription [ ] , server : ServerDescription ) => {
138+ return servers . filter ( ( server : ServerDescription ) => {
143139 const stalenessMS =
144140 sMax . lastWriteDate - server . lastWriteDate + topologyDescription . heartbeatFrequencyMS ;
145141
146142 const staleness = stalenessMS / 1000 ;
147143 const maxStalenessSeconds = readPreference . maxStalenessSeconds ?? 0 ;
148- if ( staleness <= maxStalenessSeconds ) {
149- result . push ( server ) ;
150- }
151-
152- return result ;
153- } , [ ] ) ;
144+ return staleness <= maxStalenessSeconds ;
145+ } ) ;
154146 }
155147
156148 return servers ;
157149}
158150
159151/**
160- * Determines whether a server's tags match a given set of tags
152+ * Determines whether a server's tags match a given set of tags.
153+ *
154+ * A tagset matches the server's tags if every k-v pair in the tagset
155+ * is also in the server's tagset.
156+ *
157+ * Note that this does not requires that every k-v pair in the server's tagset is also
158+ * in the client's tagset. The server's tagset is required only to be a superset of the
159+ * client's tags.
160+ *
161+ * @see https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.md#tag_sets
161162 *
162163 * @param tagSet - The requested tag set to match
163164 * @param serverTags - The server's tags
164165 */
165166function tagSetMatch ( tagSet : TagSet , serverTags : TagSet ) {
166- const keys = Object . keys ( tagSet ) ;
167- const serverTagKeys = Object . keys ( serverTags ) ;
168- for ( let i = 0 ; i < keys . length ; ++ i ) {
169- const key = keys [ i ] ;
170- if ( serverTagKeys . indexOf ( key ) === - 1 || serverTags [ key ] !== tagSet [ key ] ) {
171- return false ;
172- }
173- }
174-
175- return true ;
167+ return Object . entries ( tagSet ) . every (
168+ ( [ key , value ] ) => serverTags [ key ] != null && serverTags [ key ] === value
169+ ) ;
176170}
177171
178172/**
@@ -183,24 +177,17 @@ function tagSetMatch(tagSet: TagSet, serverTags: TagSet) {
183177 * @returns The list of servers matching the requested tags
184178 */
185179function tagSetReducer (
186- readPreference : ReadPreference ,
180+ { tags } : ReadPreference ,
187181 servers : ServerDescription [ ]
188182) : ServerDescription [ ] {
189- if (
190- readPreference . tags == null ||
191- ( Array . isArray ( readPreference . tags ) && readPreference . tags . length === 0 )
192- ) {
183+ if ( tags == null || tags . length === 0 ) {
184+ // empty tag sets match all servers
193185 return servers ;
194186 }
195187
196- for ( let i = 0 ; i < readPreference . tags . length ; ++ i ) {
197- const tagSet = readPreference . tags [ i ] ;
198- const serversMatchingTagset = servers . reduce (
199- ( matched : ServerDescription [ ] , server : ServerDescription ) => {
200- if ( tagSetMatch ( tagSet , server . tags ) ) matched . push ( server ) ;
201- return matched ;
202- } ,
203- [ ]
188+ for ( const tagSet of tags ) {
189+ const serversMatchingTagset = servers . filter ( ( s : ServerDescription ) =>
190+ tagSetMatch ( tagSet , s . tags )
204191 ) ;
205192
206193 if ( serversMatchingTagset . length ) {
0 commit comments