Skip to content

Commit 9dc2a80

Browse files
committed
WIP fix tests on windows
1 parent a925f3c commit 9dc2a80

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

src/archivist/recorder/index.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ const MIME_TYPE = 'text/html';
1010
const FETCH_DATE = new Date('2000-01-01T12:00:00.000Z');
1111
const FETCH_DATE_LATER = new Date('2000-01-02T12:00:00.000Z');
1212

13-
describe('Recorder', () => {
13+
describe.only('Recorder', () => {
1414
const SERVICE_ID = 'test_service';
1515
const TYPE = 'Terms of Service';
1616

17-
for (const repositoryType of [ 'git', 'mongo' ]) {
17+
for (const repositoryType of ['mongo']) {
1818
describe(repositoryType, () => {
1919
let recorder;
2020

src/archivist/recorder/repositories/mongo/index.js

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,46 @@ import RepositoryInterface from '../interface.js';
1010
import * as DataMapper from './dataMapper.js';
1111

1212
export default class MongoRepository extends RepositoryInterface {
13+
/**
14+
* Shared MongoClient management with reference counting.
15+
*
16+
* Multiple repositories connecting to the same MongoDB server/database share a single MongoClient instance
17+
* to avoid race conditions during cleanup. Without sharing, each repository would create its own client,
18+
* and closing them sequentially could still cause "Operation interrupted because client was closed" errors.
19+
* This issue has been observed on Windows but not on Linux or macOS, suggesting platform-specific differences
20+
* in how connection pool cleanup is handled.
21+
*
22+
* The reference counting ensures that the shared client is only closed when the last repository using it
23+
* calls finalize(), preventing premature connection closure while operations are still in progress.
24+
*/
25+
static #clients = new Map(); // connectionURI -> MongoClient
26+
static #refCounts = new Map(); // connectionURI -> number of repositories using this client
27+
1328
constructor({ database: databaseName, collection: collectionName, connectionURI }) {
1429
super();
1530

16-
this.client = new MongoClient(connectionURI);
31+
this.connectionURI = connectionURI;
1732
this.databaseName = databaseName;
1833
this.collectionName = collectionName;
34+
this.client = null;
1935
}
2036

2137
async initialize() {
22-
await this.client.connect();
38+
console.log('MongoRepository.#clients', MongoRepository.#clients);
39+
if (MongoRepository.#clients.has(this.connectionURI)) {
40+
console.log('reuse client');
41+
// Reuse existing client
42+
this.client = MongoRepository.#clients.get(this.connectionURI);
43+
MongoRepository.#refCounts.set(this.connectionURI, MongoRepository.#refCounts.get(this.connectionURI) + 1);
44+
} else {
45+
// Create new client
46+
console.log('create new client');
47+
this.client = new MongoClient(this.connectionURI);
48+
await this.client.connect();
49+
MongoRepository.#clients.set(this.connectionURI, this.client);
50+
MongoRepository.#refCounts.set(this.connectionURI, 1);
51+
}
52+
2353
const db = this.client.db(this.databaseName);
2454

2555
this.collection = db.collection(this.collectionName);
@@ -29,8 +59,18 @@ export default class MongoRepository extends RepositoryInterface {
2959
return this;
3060
}
3161

32-
finalize() {
33-
return this.client.close();
62+
async finalize() {
63+
const refCount = MongoRepository.#refCounts.get(this.connectionURI);
64+
65+
if (refCount === 1) {
66+
// Last repository using this client - close it
67+
await this.client.close();
68+
MongoRepository.#clients.delete(this.connectionURI);
69+
MongoRepository.#refCounts.delete(this.connectionURI);
70+
} else {
71+
// Other repositories still using this client - just decrement
72+
MongoRepository.#refCounts.set(this.connectionURI, refCount - 1);
73+
}
3474
}
3575

3676
async save(record) {
@@ -108,7 +148,7 @@ export default class MongoRepository extends RepositoryInterface {
108148
}
109149

110150
removeAll() {
111-
return this.collection.deleteMany();
151+
return this.collection.deleteMany({});
112152
}
113153

114154
async loadRecordContent(record) {

0 commit comments

Comments
 (0)