srv_polling.js 3.3 KB

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