Can polling get stuck if an event id is skipped?
When fixing IDLE_TIMELAPSE in https://github.com/oasislabs/oasis.js/pull/342/commits/1de0463e3115159a871c3a8143a7ed53b8e67fa8 I noticed that polling for event 1 and 3 would still never trigger IDLE_TIMELAPSE.
fit('IDLE_TIMELAPSE... only works if empty responses, but they wouldnt be empty if event skipped', async () => {
const originalIdleTimeout = PollingService['IDLE_TIMELAPSE'];
const POLLING_INTERVAL = 100;
PollingService['IDLE_TIMELAPSE'] = 200;
PollingService['SERVICES'] = new Map();
class LogSession implements Http {
public async request(method: string, api: string, body: any): Promise<any> {
if (body.offset === 1) {
const response = {
offset: 1,
events: [successEvent(1), successEvent(3)],
};
console.log('Polling', body, ' => responded', response.events.map(({id}) => id));
return response;
}
if (body.offset === 2) {
const response = {
offset: 2,
events: [successEvent(3)],
};
console.log('Polling', body, ' => responded', response.events.map(({id}) => id));
return response;
}
throw new Error('unhandled test case');
}
}
const session = new LogSession();
const service = PollingService.instance({
url: 'test',
session: session,
interval: 100,
});
const a = service.response(1);
console.log('Poll for id 1');
const b = service.response(3);
console.log('Poll for id 3');
await expect(a).resolves.toEqual(successEvent(1));
await expect(b).resolves.toEqual(successEvent(3));
await new Promise(resolve => setTimeout(resolve, POLLING_INTERVAL + PollingService['IDLE_TIMELAPSE'] + 1));
console.error(`Expected IDLE_TIMELAPSE=${PollingService['IDLE_TIMELAPSE']} to stop the polling by now?`);
await new Promise(resolve => setTimeout(resolve, PollingService['IDLE_TIMELAPSE'] * 5));
console.error('Forever');
service.stop();
PollingService['IDLE_TIMELAPSE'] = originalIdleTimeout;
});
Output
Poll for id 1
Poll for id 3
Polling { offset: 1, discardPrevious: true, id: undefined } => responded [ 1, 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Expected IDLE_TIMELAPSE=200 to stop the polling by now?
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Polling { offset: 2, discardPrevious: true, id: undefined } => responded [ 3 ]
Forever
Update after https://github.com/oasislabs/oasis.js/pull/350: IDLE_TIMELAPSE was removed, so if an event id is skipped (Poll for id 1 and 3), it will definitely poll forever.
Isn't it possible for the server to respond with [1, 3] first, and then [2] later? The events don't need to happen in the order we subscribed to them. In which case, it's fine to keep waiting for 2 forever.
But IIUC this was indeed a bug before, while we still had IDLE_TIMELAPSE. Nicely spotted, and I :heart: the unit test.