diff --git a/relay.ts b/relay.ts index 3b91bd7..cd7b39e 100644 --- a/relay.ts +++ b/relay.ts @@ -3,6 +3,7 @@ import {verifySignature, validateEvent, type Event} from './event.ts' import {matchFilters, type Filter} from './filter.ts' import {getHex64, getSubscriptionId} from './fakejson.ts' +import { MessageQueue } from './utils.ts' type RelayEvent = { connect: () => void | Promise @@ -122,24 +123,24 @@ export function relayInit( listeners.disconnect.forEach(cb => cb()) } - let incomingMessageQueue: string[] = [] + let incomingMessageQueue: MessageQueue = new MessageQueue() let handleNextInterval: any ws.onmessage = e => { - incomingMessageQueue.push(e.data) + incomingMessageQueue.enqueue(e.data) if (!handleNextInterval) { handleNextInterval = setInterval(handleNext, 0) } } function handleNext() { - if (incomingMessageQueue.length === 0) { + if (incomingMessageQueue.size === 0) { clearInterval(handleNextInterval) handleNextInterval = null return } - var json = incomingMessageQueue.shift() + var json = incomingMessageQueue.dequeue() if (!json) return let subid = getSubscriptionId(json) diff --git a/utils.test.ts b/utils.test.ts index e1ff199..7ad3d3b 100644 --- a/utils.test.ts +++ b/utils.test.ts @@ -1,5 +1,6 @@ import {buildEvent} from './test-helpers.ts' import { + MessageQueue, insertEventIntoAscendingList, insertEventIntoDescendingList, } from './utils.ts' @@ -191,3 +192,48 @@ describe('inserting into a asc sorted list of events', () => { expect(list1).toHaveLength(3) }) }) + +describe('enque a message into MessageQueue', () => { + test('enque into an empty queue', () => { + const queue = new MessageQueue() + queue.enqueue('node1') + expect(queue.first!.value).toBe('node1') + }) + test('enque into a non-empty queue', () => { + const queue = new MessageQueue() + queue.enqueue('node1') + queue.enqueue('node3') + queue.enqueue('node2') + expect(queue.first!.value).toBe('node1') + expect(queue.last!.value).toBe('node2') + expect(queue.size).toBe(3) + }) + test('dequeue from an empty queue', () => { + const queue = new MessageQueue() + const item1 = queue.dequeue() + expect(item1).toBe(null) + expect(queue.size).toBe(0) + }) + test('dequeue from a non-empty queue', () => { + const queue = new MessageQueue() + queue.enqueue('node1') + queue.enqueue('node3') + queue.enqueue('node2') + const item1 = queue.dequeue() + expect(item1).toBe('node1') + const item2 = queue.dequeue() + expect(item2).toBe('node3') + }) + test('dequeue more than in queue', () => { + const queue = new MessageQueue() + queue.enqueue('node1') + queue.enqueue('node3') + const item1 = queue.dequeue() + expect(item1).toBe('node1') + const item2 = queue.dequeue() + expect(item2).toBe('node3') + expect(queue.size).toBe(0) + const item3 = queue.dequeue() + expect(item3).toBe(null) + }) +}) diff --git a/utils.ts b/utils.ts index c50c7e1..86e9eb2 100644 --- a/utils.ts +++ b/utils.ts @@ -109,3 +109,79 @@ export function insertEventIntoAscendingList( return sortedArray } + +export class MessageNode { + private _value: string + private _next: MessageNode | null + + public get value(): string { + return this._value + } + public set value(message: string) { + this._value = message + } + public get next(): MessageNode | null { + return this._next + } + public set next(node: MessageNode | null) { + this._next = node + } + + constructor(message: string) { + this._value = message + this._next = null + } +} + +export class MessageQueue { + private _first: MessageNode | null + private _last: MessageNode | null + + public get first(): MessageNode | null { + return this._first + } + public set first(messageNode: MessageNode | null) { + this._first = messageNode + } + public get last(): MessageNode | null { + return this._last + } + public set last(messageNode: MessageNode | null) { + this._last = messageNode + } + private _size: number + public get size(): number { + return this._size + } + public set size(v: number) { + this._size = v + } + + constructor() { + this._first = null + this._last = null + this._size = 0 + } + enqueue(message: string): boolean { + const newNode = new MessageNode(message) + if (this._size === 0 || !this._last) { + this._first = newNode + this._last = newNode + } else { + this._last.next = newNode + this._last = newNode + } + this._size++ + return true + } + dequeue(): string | null { + if (this._size === 0 || !this._first) return null + + let prev = this._first + this._first = prev.next + prev.next = null + + this._size-- + return prev.value + } +}