File size: 3,251 Bytes
9756872
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SrvPoller = exports.SrvPollingEvent = void 0;
const dns = require("dns");
const timers_1 = require("timers");
const error_1 = require("../error");
const mongo_types_1 = require("../mongo_types");
const utils_1 = require("../utils");
/**
 * @internal
 * @category Event
 */
class SrvPollingEvent {
    constructor(srvRecords) {
        this.srvRecords = srvRecords;
    }
    hostnames() {
        return new Set(this.srvRecords.map(r => utils_1.HostAddress.fromSrvRecord(r).toString()));
    }
}
exports.SrvPollingEvent = SrvPollingEvent;
/** @internal */
class SrvPoller extends mongo_types_1.TypedEventEmitter {
    constructor(options) {
        super();
        if (!options || !options.srvHost) {
            throw new error_1.MongoRuntimeError('Options for SrvPoller must exist and include srvHost');
        }
        this.srvHost = options.srvHost;
        this.srvMaxHosts = options.srvMaxHosts ?? 0;
        this.srvServiceName = options.srvServiceName ?? 'mongodb';
        this.rescanSrvIntervalMS = 60000;
        this.heartbeatFrequencyMS = options.heartbeatFrequencyMS ?? 10000;
        this.haMode = false;
        this.generation = 0;
        this._timeout = undefined;
    }
    get srvAddress() {
        return `_${this.srvServiceName}._tcp.${this.srvHost}`;
    }
    get intervalMS() {
        return this.haMode ? this.heartbeatFrequencyMS : this.rescanSrvIntervalMS;
    }
    start() {
        if (!this._timeout) {
            this.schedule();
        }
    }
    stop() {
        if (this._timeout) {
            (0, timers_1.clearTimeout)(this._timeout);
            this.generation += 1;
            this._timeout = undefined;
        }
    }
    // TODO(NODE-4994): implement new logging logic for SrvPoller failures
    schedule() {
        if (this._timeout) {
            (0, timers_1.clearTimeout)(this._timeout);
        }
        this._timeout = (0, timers_1.setTimeout)(() => {
            // eslint-disable-next-line github/no-then
            this._poll().then(undefined, utils_1.squashError);
        }, this.intervalMS);
    }
    success(srvRecords) {
        this.haMode = false;
        this.schedule();
        this.emit(SrvPoller.SRV_RECORD_DISCOVERY, new SrvPollingEvent(srvRecords));
    }
    failure() {
        this.haMode = true;
        this.schedule();
    }
    async _poll() {
        const generation = this.generation;
        let srvRecords;
        try {
            srvRecords = await dns.promises.resolveSrv(this.srvAddress);
        }
        catch (dnsError) {
            this.failure();
            return;
        }
        if (generation !== this.generation) {
            return;
        }
        const finalAddresses = [];
        for (const record of srvRecords) {
            if ((0, utils_1.matchesParentDomain)(record.name, this.srvHost)) {
                finalAddresses.push(record);
            }
        }
        if (!finalAddresses.length) {
            this.failure();
            return;
        }
        this.success(finalAddresses);
    }
}
/** @event */
SrvPoller.SRV_RECORD_DISCOVERY = 'srvRecordDiscovery';
exports.SrvPoller = SrvPoller;
//# sourceMappingURL=srv_polling.js.map