Skip to content

Commit 5470baa

Browse files
committed
Merge branch 'bugfix/BB-161-add-timestamp-to-object-delete-notification' into q/8.4
2 parents b1de371 + b651db4 commit 5470baa

File tree

2 files changed

+114
-6
lines changed

2 files changed

+114
-6
lines changed

lib/queuePopulator/LogReader.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,15 +378,21 @@ class LogReader {
378378
}
379379

380380
async _processLogEntry(batchState, record, entry) {
381-
// some extension's filter functions are async (notification)
382381
return Promise.all(this._extensions.map(ext => {
383382
/**
384-
* object delete entries don't have a value field,
385-
* those should not be skipped for the notification
386-
* extension
383+
* Delete entries don't have a value field.
384+
* Value field normally contains the timestamp
385+
* of the event, which is needed for the notification
386+
* extension.
387+
* That gets added here, we use the oplog event timestamp
387388
*/
388-
if (entry.value === undefined &&
389-
ext.constructor.name !== 'NotificationQueuePopulator') {
389+
if (entry.type === 'delete' &&
390+
ext.constructor.name === 'NotificationQueuePopulator') {
391+
entry.value = JSON.stringify({
392+
'last-modified': record.timestamp
393+
});
394+
// skipping entry for other extensions
395+
} else if (entry.value === undefined) {
390396
return null;
391397
}
392398
return ext.filter({

tests/unit/lib/queuePopulator/LogReader.spec.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,106 @@ describe('LogReader', () => {
148148
assert(mockExtension.filter.secondCall.calledWith(expectedArgs));
149149
done();
150150
});
151+
152+
it('Should add timestamp if got delete event and extension is notification', done => {
153+
const mockExtension = {
154+
constructor: {
155+
name: 'NotificationQueuePopulator'
156+
},
157+
filter: sinon.spy(),
158+
};
159+
const logReaderWithExtension = new LogReader({
160+
logId: 'test-log-reader',
161+
zkClient: zkMock.createClient('localhost:2181'),
162+
logConsumer: new MockLogConsumer(),
163+
logger: new Logger('test:logReaderWithExtension'),
164+
extensions: [mockExtension]
165+
});
166+
const record = {
167+
db: 'example-bucket',
168+
timestamp: 'YYYY-MM-DD:HH-MM-SS',
169+
entry: {
170+
type: 'delete',
171+
key: 'fMexample-key',
172+
}
173+
};
174+
logReaderWithExtension._processLogEntry({}, record, record.entry);
175+
const expectedArgs = {
176+
type: 'delete',
177+
bucket: 'example-bucket',
178+
key: 'fMexample-key',
179+
value: JSON.stringify({
180+
'last-modified': 'YYYY-MM-DD:HH-MM-SS',
181+
}),
182+
logReader: logReaderWithExtension,
183+
};
184+
assert(mockExtension.filter.calledWith(expectedArgs));
185+
done();
186+
});
187+
188+
it('Should not modify entry value if already defined', done => {
189+
const mockExtension = {
190+
constructor: {
191+
name: 'NotificationQueuePopulator'
192+
},
193+
filter: sinon.spy(),
194+
};
195+
const logReaderWithExtension = new LogReader({
196+
logId: 'test-log-reader',
197+
zkClient: zkMock.createClient('localhost:2181'),
198+
logConsumer: new MockLogConsumer(),
199+
logger: new Logger('test:logReaderWithExtension'),
200+
extensions: [mockExtension]
201+
});
202+
const record = {
203+
db: 'example-bucket',
204+
timestamp: 'timestamp-value',
205+
entry: {
206+
type: 'example-type',
207+
key: 'fMexample-key',
208+
value: {
209+
'last-modified': 'YYYY-MM-DD:HH-MM-SS',
210+
}
211+
}
212+
};
213+
logReaderWithExtension._processLogEntry({}, record, record.entry);
214+
const expectedArgs = {
215+
type: 'example-type',
216+
bucket: 'example-bucket',
217+
key: 'fMexample-key',
218+
value: {
219+
'last-modified': 'YYYY-MM-DD:HH-MM-SS',
220+
},
221+
logReader: logReaderWithExtension,
222+
};
223+
assert(mockExtension.filter.calledWith(expectedArgs));
224+
done();
225+
});
226+
227+
it('Should skip filtering if value is undefined and extension not notification', done => {
228+
const mockExtension = {
229+
constructor: {
230+
name: 'ReplicationQueuePopulator'
231+
},
232+
filter: sinon.spy(),
233+
};
234+
const logReaderWithExtension = new LogReader({
235+
logId: 'test-log-reader',
236+
zkClient: zkMock.createClient('localhost:2181'),
237+
logConsumer: new MockLogConsumer(),
238+
logger: new Logger('test:logReaderWithExtension'),
239+
extensions: [mockExtension]
240+
});
241+
const record = {
242+
db: 'example-bucket',
243+
timestamp: 'YYYY-MM-DD:HH-MM-SS',
244+
entry: {
245+
type: 'example-type',
246+
key: 'fMexample-key',
247+
}
248+
};
249+
logReaderWithExtension._processLogEntry({}, record, record.entry);
250+
assert(mockExtension.filter.notCalled);
251+
done();
252+
});
151253
});

0 commit comments

Comments
 (0)