read_preference.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.ReadPreference = exports.ReadPreferenceMode = void 0;
  4. const error_1 = require("./error");
  5. /** @public */
  6. exports.ReadPreferenceMode = Object.freeze({
  7. primary: 'primary',
  8. primaryPreferred: 'primaryPreferred',
  9. secondary: 'secondary',
  10. secondaryPreferred: 'secondaryPreferred',
  11. nearest: 'nearest'
  12. });
  13. /**
  14. * The **ReadPreference** class is a class that represents a MongoDB ReadPreference and is
  15. * used to construct connections.
  16. * @public
  17. *
  18. * @see https://www.mongodb.com/docs/manual/core/read-preference/
  19. */
  20. class ReadPreference {
  21. /**
  22. * @param mode - A string describing the read preference mode (primary|primaryPreferred|secondary|secondaryPreferred|nearest)
  23. * @param tags - A tag set used to target reads to members with the specified tag(s). tagSet is not available if using read preference mode primary.
  24. * @param options - Additional read preference options
  25. */
  26. constructor(mode, tags, options) {
  27. if (!ReadPreference.isValid(mode)) {
  28. throw new error_1.MongoInvalidArgumentError(`Invalid read preference mode ${JSON.stringify(mode)}`);
  29. }
  30. if (options == null && typeof tags === 'object' && !Array.isArray(tags)) {
  31. options = tags;
  32. tags = undefined;
  33. }
  34. else if (tags && !Array.isArray(tags)) {
  35. throw new error_1.MongoInvalidArgumentError('ReadPreference tags must be an array');
  36. }
  37. this.mode = mode;
  38. this.tags = tags;
  39. this.hedge = options?.hedge;
  40. this.maxStalenessSeconds = undefined;
  41. this.minWireVersion = undefined;
  42. options = options ?? {};
  43. if (options.maxStalenessSeconds != null) {
  44. if (options.maxStalenessSeconds <= 0) {
  45. throw new error_1.MongoInvalidArgumentError('maxStalenessSeconds must be a positive integer');
  46. }
  47. this.maxStalenessSeconds = options.maxStalenessSeconds;
  48. // NOTE: The minimum required wire version is 5 for this read preference. If the existing
  49. // topology has a lower value then a MongoError will be thrown during server selection.
  50. this.minWireVersion = 5;
  51. }
  52. if (this.mode === ReadPreference.PRIMARY) {
  53. if (this.tags && Array.isArray(this.tags) && this.tags.length > 0) {
  54. throw new error_1.MongoInvalidArgumentError('Primary read preference cannot be combined with tags');
  55. }
  56. if (this.maxStalenessSeconds) {
  57. throw new error_1.MongoInvalidArgumentError('Primary read preference cannot be combined with maxStalenessSeconds');
  58. }
  59. if (this.hedge) {
  60. throw new error_1.MongoInvalidArgumentError('Primary read preference cannot be combined with hedge');
  61. }
  62. }
  63. }
  64. // Support the deprecated `preference` property introduced in the porcelain layer
  65. get preference() {
  66. return this.mode;
  67. }
  68. static fromString(mode) {
  69. return new ReadPreference(mode);
  70. }
  71. /**
  72. * Construct a ReadPreference given an options object.
  73. *
  74. * @param options - The options object from which to extract the read preference.
  75. */
  76. static fromOptions(options) {
  77. if (!options)
  78. return;
  79. const readPreference = options.readPreference ?? options.session?.transaction.options.readPreference;
  80. const readPreferenceTags = options.readPreferenceTags;
  81. if (readPreference == null) {
  82. return;
  83. }
  84. if (typeof readPreference === 'string') {
  85. return new ReadPreference(readPreference, readPreferenceTags, {
  86. maxStalenessSeconds: options.maxStalenessSeconds,
  87. hedge: options.hedge
  88. });
  89. }
  90. else if (!(readPreference instanceof ReadPreference) && typeof readPreference === 'object') {
  91. const mode = readPreference.mode || readPreference.preference;
  92. if (mode && typeof mode === 'string') {
  93. return new ReadPreference(mode, readPreference.tags ?? readPreferenceTags, {
  94. maxStalenessSeconds: readPreference.maxStalenessSeconds,
  95. hedge: options.hedge
  96. });
  97. }
  98. }
  99. if (readPreferenceTags) {
  100. readPreference.tags = readPreferenceTags;
  101. }
  102. return readPreference;
  103. }
  104. /**
  105. * Replaces options.readPreference with a ReadPreference instance
  106. */
  107. static translate(options) {
  108. if (options.readPreference == null)
  109. return options;
  110. const r = options.readPreference;
  111. if (typeof r === 'string') {
  112. options.readPreference = new ReadPreference(r);
  113. }
  114. else if (r && !(r instanceof ReadPreference) && typeof r === 'object') {
  115. const mode = r.mode || r.preference;
  116. if (mode && typeof mode === 'string') {
  117. options.readPreference = new ReadPreference(mode, r.tags, {
  118. maxStalenessSeconds: r.maxStalenessSeconds
  119. });
  120. }
  121. }
  122. else if (!(r instanceof ReadPreference)) {
  123. throw new error_1.MongoInvalidArgumentError(`Invalid read preference: ${r}`);
  124. }
  125. return options;
  126. }
  127. /**
  128. * Validate if a mode is legal
  129. *
  130. * @param mode - The string representing the read preference mode.
  131. */
  132. static isValid(mode) {
  133. const VALID_MODES = new Set([
  134. ReadPreference.PRIMARY,
  135. ReadPreference.PRIMARY_PREFERRED,
  136. ReadPreference.SECONDARY,
  137. ReadPreference.SECONDARY_PREFERRED,
  138. ReadPreference.NEAREST,
  139. null
  140. ]);
  141. return VALID_MODES.has(mode);
  142. }
  143. /**
  144. * Validate if a mode is legal
  145. *
  146. * @param mode - The string representing the read preference mode.
  147. */
  148. isValid(mode) {
  149. return ReadPreference.isValid(typeof mode === 'string' ? mode : this.mode);
  150. }
  151. /**
  152. * Indicates that this readPreference needs the "SecondaryOk" bit when sent over the wire
  153. * @see https://www.mongodb.com/docs/manual/reference/mongodb-wire-protocol/#op-query
  154. */
  155. secondaryOk() {
  156. const NEEDS_SECONDARYOK = new Set([
  157. ReadPreference.PRIMARY_PREFERRED,
  158. ReadPreference.SECONDARY,
  159. ReadPreference.SECONDARY_PREFERRED,
  160. ReadPreference.NEAREST
  161. ]);
  162. return NEEDS_SECONDARYOK.has(this.mode);
  163. }
  164. /**
  165. * Check if the two ReadPreferences are equivalent
  166. *
  167. * @param readPreference - The read preference with which to check equality
  168. */
  169. equals(readPreference) {
  170. return readPreference.mode === this.mode;
  171. }
  172. /** Return JSON representation */
  173. toJSON() {
  174. const readPreference = { mode: this.mode };
  175. if (Array.isArray(this.tags))
  176. readPreference.tags = this.tags;
  177. if (this.maxStalenessSeconds)
  178. readPreference.maxStalenessSeconds = this.maxStalenessSeconds;
  179. if (this.hedge)
  180. readPreference.hedge = this.hedge;
  181. return readPreference;
  182. }
  183. }
  184. ReadPreference.PRIMARY = exports.ReadPreferenceMode.primary;
  185. ReadPreference.PRIMARY_PREFERRED = exports.ReadPreferenceMode.primaryPreferred;
  186. ReadPreference.SECONDARY = exports.ReadPreferenceMode.secondary;
  187. ReadPreference.SECONDARY_PREFERRED = exports.ReadPreferenceMode.secondaryPreferred;
  188. ReadPreference.NEAREST = exports.ReadPreferenceMode.nearest;
  189. ReadPreference.primary = new ReadPreference(exports.ReadPreferenceMode.primary);
  190. ReadPreference.primaryPreferred = new ReadPreference(exports.ReadPreferenceMode.primaryPreferred);
  191. ReadPreference.secondary = new ReadPreference(exports.ReadPreferenceMode.secondary);
  192. ReadPreference.secondaryPreferred = new ReadPreference(exports.ReadPreferenceMode.secondaryPreferred);
  193. ReadPreference.nearest = new ReadPreference(exports.ReadPreferenceMode.nearest);
  194. exports.ReadPreference = ReadPreference;
  195. //# sourceMappingURL=read_preference.js.map