Skip to content

Commit ea3b89d

Browse files
committed
refactor - remove proxy, use subclass
1 parent 6dfc73d commit ea3b89d

File tree

2 files changed

+27
-32
lines changed

2 files changed

+27
-32
lines changed

packages/client/lib/client/commands-queue.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList, makeEmptyAware } from './linked-list';
1+
import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList, EmptyAwareSinglyLinkedList } from './linked-list';
22
import encodeCommand from '../RESP/encoder';
33
import { Decoder, PUSH_TYPE_MAPPING, RESP_TYPES } from '../RESP/decoder';
44
import { TypeMapping, ReplyUnion, RespVersions, RedisArgument } from '../RESP/types';
@@ -55,7 +55,7 @@ export default class RedisCommandsQueue {
5555
readonly #respVersion;
5656
readonly #maxLength;
5757
readonly #toWrite = new DoublyLinkedList<CommandToWrite>();
58-
readonly #waitingForReply: SinglyLinkedList<CommandWaitingForReply>;
58+
readonly #waitingForReply: EmptyAwareSinglyLinkedList<CommandWaitingForReply>;
5959
readonly #onShardedChannelMoved;
6060
#chainInExecution: symbol | undefined;
6161
readonly decoder;
@@ -77,9 +77,8 @@ export default class RedisCommandsQueue {
7777
this.#maxLength = maxLength;
7878
this.#onShardedChannelMoved = onShardedChannelMoved;
7979
this.decoder = this.#initiateDecoder();
80-
const [waitingForReply, emptyEmitter] = makeEmptyAware(new SinglyLinkedList<CommandWaitingForReply>())
81-
this.#waitingForReply = waitingForReply;
82-
emptyEmitter.on('empty', this.events.emit.bind(this.events, 'waitingForReplyEmpty'))
80+
this.#waitingForReply = new EmptyAwareSinglyLinkedList<CommandWaitingForReply>()
81+
this.#waitingForReply.events.on('empty', this.events.emit.bind(this.events, 'waitingForReplyEmpty'))
8382
}
8483

8584
#onReply(reply: ReplyUnion) {

packages/client/lib/client/linked-list.ts

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -113,33 +113,6 @@ export class DoublyLinkedList<T> {
113113
}
114114
}
115115

116-
// This function takes an object that has a `length` property
117-
// and returns both a proxy and an event emitter.
118-
// The proxy will act the same as the original object.
119-
// And the event emitter will emit an `empty` event whenever the `length` becomes zero.
120-
export const makeEmptyAware = <T extends { length: number }>(obj: T): [T, EventEmitter] => {
121-
const eventEmitter = new EventEmitter();
122-
const proxy = new Proxy(obj, {
123-
get(target, prop, _receiver) {
124-
const original = Reflect.get(target, prop, target);
125-
if (typeof original === 'function') {
126-
return function (...args: any[]) {
127-
const oldLength = target.length;
128-
const ret = original.apply(target, args);
129-
const newLength = target.length;
130-
if(oldLength !== newLength && newLength === 0) {
131-
eventEmitter.emit('empty')
132-
}
133-
return ret
134-
};
135-
} else {
136-
return original;
137-
};
138-
},
139-
});
140-
return [ proxy, eventEmitter ];
141-
}
142-
143116
export interface SinglyLinkedNode<T> {
144117
value: T;
145118
next: SinglyLinkedNode<T> | undefined;
@@ -230,3 +203,26 @@ export class SinglyLinkedList<T> {
230203
}
231204
}
232205
}
206+
207+
export class EmptyAwareSinglyLinkedList<T> extends SinglyLinkedList<T> {
208+
readonly events = new EventEmitter();
209+
reset() {
210+
super.reset();
211+
this.events.emit('empty');
212+
}
213+
shift(): T | undefined {
214+
const old = this.length;
215+
const ret = super.shift();
216+
if(old !== this.length && this.length === 0) {
217+
this.events.emit('empty');
218+
}
219+
return ret;
220+
}
221+
remove(node: SinglyLinkedNode<T>, parent: SinglyLinkedNode<T> | undefined): T | undefined {
222+
const old = this.length;
223+
super.remove(node, parent);
224+
if(old !== this.length && this.length === 0) {
225+
this.events.emit('empty');
226+
}
227+
}
228+
}

0 commit comments

Comments
 (0)