mongodb 3.3.0-beta1 → 3.3.0-beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,10 @@
3
3
  const MongoError = require('../core').MongoError;
4
4
  const Aspect = require('./operation').Aspect;
5
5
  const OperationBase = require('./operation').OperationBase;
6
+ const ReadPreference = require('../core').ReadPreference;
7
+ const isRetryableError = require('../core/error').isRetryableError;
8
+ const maxWireVersion = require('../core/utils').maxWireVersion;
9
+ const isUnifiedTopology = require('../core/utils').isUnifiedTopology;
6
10
 
7
11
  /**
8
12
  * Executes the given operation with provided arguments.
@@ -26,6 +30,25 @@ function executeOperation(topology, operation, callback) {
26
30
  throw new TypeError('This method requires a valid operation instance');
27
31
  }
28
32
 
33
+ if (
34
+ isUnifiedTopology(topology) &&
35
+ !operation.hasAspect(Aspect.SKIP_SESSION) &&
36
+ topology.shouldCheckForSessionSupport()
37
+ ) {
38
+ // TODO: this is only supported for unified topology, the first part of this check
39
+ // should go away when we drop legacy topology types.
40
+ topology.selectServer(ReadPreference.primaryPreferred, err => {
41
+ if (err) {
42
+ callback(err);
43
+ return;
44
+ }
45
+
46
+ executeOperation(topology, operation, callback);
47
+ });
48
+
49
+ return;
50
+ }
51
+
29
52
  const Promise = topology.s.promiseLibrary;
30
53
 
31
54
  // The driver sessions spec mandates that we implicitly create sessions for operations
@@ -65,7 +88,11 @@ function executeOperation(topology, operation, callback) {
65
88
  );
66
89
 
67
90
  try {
68
- return operation.execute(handler);
91
+ if (operation.hasAspect(Aspect.EXECUTE_WITH_SELECTION)) {
92
+ return executeWithServerSelection(topology, operation, handler);
93
+ } else {
94
+ return operation.execute(handler);
95
+ }
69
96
  } catch (e) {
70
97
  handler(e);
71
98
  throw e;
@@ -76,11 +103,63 @@ function executeOperation(topology, operation, callback) {
76
103
  const handler = makeExecuteCallback(resolve, reject);
77
104
 
78
105
  try {
79
- return operation.execute(handler);
106
+ if (operation.hasAspect(Aspect.EXECUTE_WITH_SELECTION)) {
107
+ return executeWithServerSelection(topology, operation, handler);
108
+ } else {
109
+ return operation.execute(handler);
110
+ }
80
111
  } catch (e) {
81
112
  handler(e);
82
113
  }
83
114
  });
84
115
  }
85
116
 
117
+ function supportsRetryableReads(server) {
118
+ return maxWireVersion(server) >= 6;
119
+ }
120
+
121
+ function executeWithServerSelection(topology, operation, callback) {
122
+ const readPreference = operation.readPreference || ReadPreference.primary;
123
+
124
+ function callbackWithRetry(err, result) {
125
+ if (err == null) {
126
+ return callback(null, result);
127
+ }
128
+
129
+ if (!isRetryableError(err)) {
130
+ return callback(err);
131
+ }
132
+
133
+ // select a new server, and attempt to retry the operation
134
+ topology.selectServer(readPreference, (err, server) => {
135
+ if (err || !supportsRetryableReads(server)) {
136
+ callback(err, null);
137
+ return;
138
+ }
139
+
140
+ operation.execute(server, callback);
141
+ });
142
+ }
143
+
144
+ // select a server, and execute the operation against it
145
+ topology.selectServer(readPreference, (err, server) => {
146
+ if (err) {
147
+ callback(err, null);
148
+ return;
149
+ }
150
+
151
+ const shouldRetryReads =
152
+ topology.s.options.retryReads !== false &&
153
+ (operation.session && !operation.session.inTransaction()) &&
154
+ supportsRetryableReads(server);
155
+
156
+ if (operation.hasAspect(Aspect.RETRYABLE) && shouldRetryReads) {
157
+ operation.execute(server, callbackWithRetry);
158
+ return;
159
+ }
160
+
161
+ operation.execute(server, callback);
162
+ });
163
+ }
164
+
86
165
  module.exports = executeOperation;
@@ -14,10 +14,6 @@ class ExplainOperation extends OperationBase {
14
14
 
15
15
  execute() {
16
16
  const cursor = this.cursor;
17
-
18
- if (cursor._initImplicitSession) {
19
- cursor._initImplicitSession();
20
- }
21
17
  return CoreCursor.prototype.next.apply(cursor, arguments);
22
18
  }
23
19
  }
@@ -3,7 +3,9 @@
3
3
  const Aspect = {
4
4
  READ_OPERATION: Symbol('READ_OPERATION'),
5
5
  SKIP_SESSION: Symbol('SKIP_SESSION'),
6
- WRITE_OPERATION: Symbol('WRITE_OPERATION')
6
+ WRITE_OPERATION: Symbol('WRITE_OPERATION'),
7
+ RETRYABLE: Symbol('RETRYABLE'),
8
+ EXECUTE_WITH_SELECTION: Symbol('EXECUTE_WITH_SELECTION')
7
9
  };
8
10
 
9
11
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb",
3
- "version": "3.3.0-beta1",
3
+ "version": "3.3.0-beta2",
4
4
  "description": "The official MongoDB driver for Node.js",
5
5
  "main": "index.js",
6
6
  "files": [