Skip to content

Commit 45eea48

Browse files
refine sliding window sender in #532
1 parent 732ebc5 commit 45eea48

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

webiojs/src/utils.ts

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -188,67 +188,76 @@ export function is_mobile() {
188188
// put send task to a queue and run it one by one
189189
export class ReliableSender {
190190
private seq = 0;
191-
private queue: { enable_batch: boolean, param: any }[] = [];
192-
private send_running = false
191+
private queue: { enable_batch: boolean, task: any }[] = [];
193192
private _stop = false;
193+
private ignore_interval_send = false;
194+
private last_send_time = 0;
195+
private interval_send_id = 0;
194196

195197
constructor(
196-
private readonly sender: (params: any[], seq: number) => Promise<void>,
198+
private readonly sender: (tasks: any[], seq: number) => Promise<void>,
197199
private window_size: number = 8,
198-
init_seq = 0, private timeout = 2000
200+
init_seq = 0,
201+
send_interval = 2000,
202+
private min_send_interval = 1000,
199203
) {
200204
this.sender = sender;
201205
this.window_size = window_size;
202-
this.timeout = timeout;
203206
this.seq = init_seq;
204207
this.queue = [];
208+
this.ignore_interval_send = false;
209+
this.interval_send_id = setInterval(this.interval_send.bind(this), send_interval);
205210
}
206211

207212
/*
208-
* for continuous batch_send tasks in queue, they will be sent in one sender, the sending will retry when it finished or timeout.
209-
* for non-batch task, each will be sent in a single sender, the sending will retry when it finished.
213+
* for continuous batch_send tasks in queue, they will be sent in one sender,
214+
* for non-batch task, each will be sent in a single sender,
215+
* the sending will retry when there are unfinished task in queue.
210216
* */
211-
add_send_task(param: any, allow_batch_send = true) {
217+
add_send_task(task: any, allow_batch_send = true) {
212218
if (this._stop) return;
213219
this.queue.push({
214220
enable_batch: allow_batch_send,
215-
param: param
221+
task: task
216222
});
217-
if (!this.send_running)
218-
this.start_send();
223+
this.do_send();
219224
}
220225

221-
private start_send() {
222-
if (this._stop || this.queue.length === 0) {
223-
this.send_running = false;
224-
return;
225-
}
226-
this.send_running = true;
227-
let params: any[] = [];
226+
private get_tasks() {
227+
let tasks: any[] = [];
228228
for (let item of this.queue) {
229229
if (!item.enable_batch)
230230
break;
231-
params.push(item.param);
231+
tasks.push(item.task);
232232
}
233233
let batch_send = true;
234-
if (params.length === 0 && !this.queue[0].enable_batch) {
234+
if (tasks.length === 0 && this.queue.length > 0 && !this.queue[0].enable_batch) {
235235
batch_send = false;
236-
params.push(this.queue[0].param);
236+
tasks.push(this.queue[0].task);
237237
}
238-
if (params.length === 0) {
239-
this.send_running = false;
238+
return {tasks, batch_send};
239+
}
240+
241+
private do_send() {
242+
const info = this.get_tasks();
243+
const tasks = info.tasks, batch_send = info.batch_send;
244+
if (tasks.length === 0) {
240245
return;
241246
}
242-
243-
let promises = [this.sender(params, this.seq)];
244-
if (batch_send)
245-
promises.push(new Promise((resolve) => setTimeout(resolve, this.timeout)));
246-
247-
Promise.race(promises).then(() => {
248-
this.start_send();
247+
this.last_send_time = Date.now();
248+
if (!batch_send) // for non-batch task, only retry after current request finished
249+
this.ignore_interval_send = true;
250+
this.sender(tasks, this.seq).then(() => {
251+
this.ignore_interval_send = false;
249252
});
250253
}
251254

255+
private interval_send() {
256+
if (this._stop || this.ignore_interval_send) return;
257+
if (Date.now() - this.last_send_time < this.min_send_interval) return;
258+
this.do_send();
259+
}
260+
252261
// seq for each ack call must be larger than the previous one, otherwise the ack will be ignored
253262
ack(seq: number) {
254263
if (seq < this.seq)
@@ -260,5 +269,6 @@ export class ReliableSender {
260269

261270
stop() {
262271
this._stop = true;
272+
clearInterval(this.interval_send_id);
263273
}
264274
}

0 commit comments

Comments
 (0)