-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathmongo.ts
79 lines (71 loc) · 2.25 KB
/
mongo.ts
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
import * as mongo from 'mongodb';
import * as timers from 'timers/promises';
import { BaseMongoConfigDecoded, normalizeMongoConfig } from '../types/types.js';
/**
* Time for new connection to timeout.
*/
export const MONGO_CONNECT_TIMEOUT_MS = 10_000;
/**
* Time for individual requests to timeout the socket.
*/
export const MONGO_SOCKET_TIMEOUT_MS = 60_000;
/**
* Time for individual requests to timeout the operation.
*
* This is time spent on the cursor, not total time.
*
* Must be less than MONGO_SOCKET_TIMEOUT_MS to ensure proper error handling.
*/
export const MONGO_OPERATION_TIMEOUT_MS = 30_000;
/**
* Same as above, but specifically for clear operations.
*
* These are retried when reaching the timeout.
*/
export const MONGO_CLEAR_OPERATION_TIMEOUT_MS = 5_000;
export function createMongoClient(config: BaseMongoConfigDecoded) {
const normalized = normalizeMongoConfig(config);
return new mongo.MongoClient(normalized.uri, {
auth: {
username: normalized.username,
password: normalized.password
},
// Time for connection to timeout
connectTimeoutMS: MONGO_CONNECT_TIMEOUT_MS,
// Time for individual requests to timeout
socketTimeoutMS: MONGO_SOCKET_TIMEOUT_MS,
// How long to wait for new primary selection
serverSelectionTimeoutMS: 30_000,
// Avoid too many connections:
// 1. It can overwhelm the source database.
// 2. Processing too many queries in parallel can cause the process to run out of memory.
maxPoolSize: 8,
maxConnecting: 3,
maxIdleTimeMS: 60_000
});
}
/**
* Wait up to a minute for authentication errors to resolve.
*
* There can be a delay between an Atlas user being created, and that user being
* available on the database cluster. This works around it.
*
* This is specifically relevant for migrations and teardown - other parts of the stack
* can generate handle these failures and just retry or restart.
*/
export async function waitForAuth(db: mongo.Db) {
const start = Date.now();
while (Date.now() - start < 60_000) {
try {
await db.command({ ping: 1 });
// Success
break;
} catch (e) {
if (e.codeName == 'AuthenticationFailed') {
await timers.setTimeout(1_000);
continue;
}
throw e;
}
}
}