Skip to content

Commit 676f8f3

Browse files
committed
wip
1 parent 52b3377 commit 676f8f3

File tree

4 files changed

+47
-16
lines changed

4 files changed

+47
-16
lines changed

src/connection_string.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,7 @@ import { PromiseProvider } from './promise_provider';
3434
import { Encrypter } from './encrypter';
3535
import { Compressor, CompressorName } from './cmap/wire_protocol/compression';
3636

37-
const VALID_TXT_RECORDS = [
38-
'authSource',
39-
'replicaSet',
40-
'loadBalanced',
41-
'srvMaxHosts',
42-
'srvServiceName'
43-
];
37+
const VALID_TXT_RECORDS = ['authSource', 'replicaSet', 'loadBalanced', 'srvMaxHosts'];
4438

4539
const LB_SINGLE_HOST_ERROR = 'loadBalanced option only supported with a single host in the URI';
4640
const LB_REPLICA_SET_ERROR = 'loadBalanced option not supported with a replicaSet option';
@@ -69,7 +63,10 @@ function matchesParentDomain(srvAddress: string, parentDomain: string): boolean
6963
* @param uri - The connection string to parse
7064
* @param options - Optional user provided connection string options
7165
*/
72-
export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostAddress[]>): void {
66+
export function resolveSRVRecord(
67+
options: MongoOptions,
68+
callback: Callback<{ hosts: HostAddress[]; records: dns.SrvRecord[] }>
69+
): void {
7370
if (typeof options.srvHost !== 'string') {
7471
return callback(new MongoAPIError('Option "srvHost" must not be empty'));
7572
}
@@ -130,7 +127,6 @@ export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostA
130127
const replicaSet = txtRecordOptions.get('replicaSet') ?? undefined;
131128
const loadBalanced = txtRecordOptions.get('loadBalanced') ?? undefined;
132129
const srvMaxHostsString = txtRecordOptions.get('srvMaxHosts') ?? undefined;
133-
// const srvServiceName = txtRecordOptions.get('srvServiceName') ?? undefined;
134130

135131
if (srvMaxHostsString) {
136132
try {
@@ -166,7 +162,7 @@ export function resolveSRVRecord(options: MongoOptions, callback: Callback<HostA
166162
}
167163
}
168164

169-
callback(undefined, hostAddresses);
165+
callback(undefined, { hosts: hostAddresses, records: addresses });
170166
});
171167
});
172168
}

src/operations/connect.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type * as dns from 'dns';
12
import { MongoRuntimeError, MongoInvalidArgumentError } from '../error';
23
import { Topology, TOPOLOGY_EVENTS } from '../sdam/topology';
34
import { resolveSRVRecord } from '../connection_string';
@@ -49,8 +50,10 @@ export function connect(
4950
};
5051

5152
if (typeof options.srvHost === 'string') {
52-
return resolveSRVRecord(options, (err, hosts) => {
53-
if (err || !hosts) return callback(err);
53+
return resolveSRVRecord(options, (err, res) => {
54+
if (err || !res) return callback(err);
55+
56+
const { hosts, records } = res;
5457

5558
const selectedHosts =
5659
options.srvMaxHosts === 0 || options.srvMaxHosts >= hosts.length
@@ -61,7 +64,11 @@ export function connect(
6164
options.hosts[index] = host;
6265
}
6366

64-
return createTopology(mongoClient, options, connectCallback);
67+
return createTopology(
68+
mongoClient,
69+
{ ...options, initialSrvResults: records },
70+
connectCallback
71+
);
6572
});
6673
}
6774

@@ -70,7 +77,7 @@ export function connect(
7077

7178
function createTopology(
7279
mongoClient: MongoClient,
73-
options: MongoOptions,
80+
options: MongoOptions & { initialSrvResults?: dns.SrvRecord[] },
7481
callback: Callback<Topology>
7582
) {
7683
// Create the topology

src/sdam/srv_polling.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ export class SrvPollingEvent {
3232
hostnames(): Set<string> {
3333
return new Set(this.srvRecords.map(r => HostAddress.fromSrvRecord(r).toString()));
3434
}
35+
36+
equals(other: SrvPollingEvent): boolean {
37+
return (
38+
this.srvRecords.length !== 0 &&
39+
other.srvRecords.length !== 0 &&
40+
this.srvRecords.length === other.srvRecords.length &&
41+
this.srvRecords.every(
42+
(record, index) =>
43+
record.name === other.srvRecords[index].name &&
44+
record.port === other.srvRecords[index].port &&
45+
record.weight === other.srvRecords[index].weight &&
46+
record.priority === other.srvRecords[index].priority
47+
)
48+
);
49+
}
3550
}
3651

3752
/** @internal */
@@ -41,6 +56,8 @@ export interface SrvPollerOptions extends LoggerOptions {
4156
srvMaxHosts: number;
4257
srvHost: string;
4358
heartbeatFrequencyMS: number;
59+
60+
initialSrvResults?: dns.SrvRecord[];
4461
}
4562

4663
/** @internal */
@@ -58,6 +75,7 @@ export class SrvPoller extends TypedEventEmitter<SrvPollerEvents> {
5875
generation: number;
5976
srvMaxHosts: number;
6077
srvServiceName: string;
78+
lastSrvPollingEvent?: SrvPollingEvent;
6179
_timeout?: NodeJS.Timeout;
6280

6381
/** @event */
@@ -75,6 +93,9 @@ export class SrvPoller extends TypedEventEmitter<SrvPollerEvents> {
7593
this.srvServiceName = options.srvServiceName ?? 'mongodb';
7694
this.rescanSrvIntervalMS = options.rescanSrvIntervalMS ?? 60000;
7795
this.heartbeatFrequencyMS = options.heartbeatFrequencyMS ?? 10000;
96+
this.lastSrvPollingEvent = Array.isArray(options.initialSrvResults)
97+
? new SrvPollingEvent(options.initialSrvResults)
98+
: undefined;
7899
this.logger = new Logger('srvPoller', options);
79100

80101
this.haMode = false;
@@ -116,7 +137,11 @@ export class SrvPoller extends TypedEventEmitter<SrvPollerEvents> {
116137
success(srvRecords: dns.SrvRecord[]): void {
117138
this.haMode = false;
118139
this.schedule();
119-
this.emit(SrvPoller.SRV_RECORD_DISCOVERY, new SrvPollingEvent(srvRecords));
140+
const event = new SrvPollingEvent(srvRecords);
141+
if (!this.lastSrvPollingEvent?.equals(event)) {
142+
this.emit(SrvPoller.SRV_RECORD_DISCOVERY, event);
143+
}
144+
this.lastSrvPollingEvent = event;
120145
}
121146

122147
failure(message: string, obj?: NodeJS.ErrnoException): void {

src/sdam/topology.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Denque = require('denque');
2+
import type * as dns from 'dns';
23
import { ReadPreference, ReadPreferenceLike } from '../read_preference';
34
import { compareTopologyVersion, ServerDescription } from './server_description';
45
import { TopologyDescription } from './topology_description';
@@ -143,6 +144,7 @@ export interface TopologyOptions extends BSONSerializeOptions, ServerOptions {
143144
srvMaxHosts: number;
144145
srvServiceName: string;
145146
rescanSrvIntervalMS: number;
147+
initialSrvResults?: dns.SrvRecord[];
146148
hosts: HostAddress[];
147149
retryWrites: boolean;
148150
retryReads: boolean;
@@ -345,7 +347,8 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
345347
srvHost: options.srvHost,
346348
srvMaxHosts: options.srvMaxHosts,
347349
srvServiceName: options.srvServiceName,
348-
rescanSrvIntervalMS: options.rescanSrvIntervalMS
350+
rescanSrvIntervalMS: options.rescanSrvIntervalMS,
351+
initialSrvResults: options.initialSrvResults
349352
});
350353

351354
this.on(Topology.TOPOLOGY_DESCRIPTION_CHANGED, this.s.detectShardedTopology);

0 commit comments

Comments
 (0)