Skip to content

Commit 0e02414

Browse files
offirgolanjasonmit
authored andcommitted
fix(persister): Handle concurrent find requests (#88)
1 parent 8dfa464 commit 0e02414

File tree

2 files changed

+45
-18
lines changed

2 files changed

+45
-18
lines changed

packages/@pollyjs/persister/src/index.js

+23-14
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ const CREATOR_NAME = 'Polly.JS';
88
export default class Persister {
99
constructor(polly) {
1010
this.polly = polly;
11-
this.cache = new Map();
1211
this.pending = new Map();
12+
this._cache = new Map();
1313
}
1414

1515
static get type() {
@@ -116,31 +116,40 @@ export default class Persister {
116116
}
117117

118118
async find(recordingId) {
119-
if (this.cache.has(recordingId)) {
120-
return this.cache.get(recordingId);
121-
}
119+
const { _cache: cache } = this;
120+
121+
if (!cache.has(recordingId)) {
122+
const findRecording = async () => {
123+
const recording = await this.findRecording(recordingId);
124+
125+
if (recording) {
126+
this.assert(
127+
`Recording with id '${recordingId}' is invalid. Please delete the recording so a new one can be created.`,
128+
recording.log && recording.log.creator.name === CREATOR_NAME
129+
);
130+
131+
return recording;
132+
} else {
133+
cache.delete(recordingId);
122134

123-
const recording = await this.findRecording(recordingId);
135+
return null;
136+
}
137+
};
124138

125-
if (recording) {
126-
this.assert(
127-
`Recording with id '${recordingId}' is invalid. Please delete the recording so a new one can be created.`,
128-
recording.log && recording.log.creator.name === CREATOR_NAME
129-
);
130-
this.cache.set(recordingId, recording);
139+
cache.set(recordingId, findRecording());
131140
}
132141

133-
return recording;
142+
return cache.get(recordingId);
134143
}
135144

136145
async save(recordingId) {
137146
await this.saveRecording(...arguments);
138-
this.cache.delete(recordingId);
147+
this._cache.delete(recordingId);
139148
}
140149

141150
async delete(recordingId) {
142151
await this.deleteRecording(...arguments);
143-
this.cache.delete(recordingId);
152+
this._cache.delete(recordingId);
144153
}
145154

146155
async findEntry(pollyRequest) {

packages/@pollyjs/persister/tests/unit/persister-test.js

+22-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Persister from '../../src';
2+
import { timeout } from '@pollyjs/utils';
23

34
describe('Unit | Persister', function() {
45
it('should exist', function() {
@@ -19,24 +20,37 @@ describe('Unit | Persister', function() {
1920
};
2021

2122
class CustomPersister extends Persister {
22-
findRecording() {
23+
async findRecording() {
2324
callCounts.find++;
25+
await timeout(1);
2426

2527
return recording;
2628
}
2729

28-
saveRecording() {
30+
async saveRecording() {
2931
callCounts.save++;
32+
await timeout(1);
3033
}
3134

32-
deleteRecording() {
35+
async deleteRecording() {
3336
callCounts.delete++;
37+
await timeout(1);
3438
}
3539
}
3640

3741
this.persister = new CustomPersister({});
3842
});
3943

44+
it('should handle concurrent find requests', async function() {
45+
await Promise.all([
46+
this.persister.find('test'),
47+
this.persister.find('test'),
48+
this.persister.find('test')
49+
]);
50+
51+
expect(callCounts.find).to.equal(1);
52+
});
53+
4054
it('caches', async function() {
4155
await this.persister.find('test');
4256
await this.persister.find('test');
@@ -49,7 +63,11 @@ describe('Unit | Persister', function() {
4963
recording = null;
5064

5165
await this.persister.find('test');
52-
await this.persister.find('test');
66+
await Promise.all([
67+
this.persister.find('test'),
68+
this.persister.find('test'),
69+
this.persister.find('test')
70+
]);
5371
await this.persister.find('test');
5472

5573
expect(callCounts.find).to.equal(3);

0 commit comments

Comments
 (0)