-
Notifications
You must be signed in to change notification settings - Fork 150
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add range query param type * correctly parse a range or throw an error * create new endpoint to query a range of blocks using an async generator * lint, add `/blocks` route * fix grumbles * fix blunder * sort collection of responses, add comments for range algorithm * add return types * cleanup QueueNext type * port runTasks to AbstractController, and make it generic * add PromiseQueue * fix memory allocation, and remove async generator * add PromiseQueue * use PromiseQueue * lint * remove console * fix verifyInt * add /blocks to docs * change BlockRange to Blocks * set a max range, extra error handling * add verifyUInt within util * remove this.verifyInt and replace it with verifyUInt and verifyNonZeroUInt * correct error message * fix small async await grumble * refactor calling each promise * allow parseNumberOrThrow to accept zeroes * fix comment grumble
- Loading branch information
Showing
9 changed files
with
321 additions
and
3 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/** | ||
* A PromiseQueue, enforcing that no more than `maxTasks` number of tasks | ||
* are running at a given time. | ||
*/ | ||
export class PromiseQueue<T> { | ||
// How many tasks are allowed to run concurrently? | ||
#maxTasks: number; | ||
// How many tasks are currently running concurrently? | ||
#runningTasks = 0; | ||
// The queued tasks waiting to run | ||
#tasks: LinkedList<() => void>; | ||
|
||
constructor(maxTasks: number) { | ||
this.#maxTasks = maxTasks; | ||
this.#tasks = new LinkedList(); | ||
} | ||
|
||
// Try to run the next task in the queue. | ||
private tryRunNextTask(): void { | ||
if (this.#runningTasks >= this.#maxTasks) { | ||
return; | ||
} | ||
const nextTask = this.#tasks.popFront(); | ||
if (nextTask) { | ||
nextTask(); | ||
this.#runningTasks += 1; | ||
} | ||
} | ||
|
||
// Take a task and package it up to run, triggering | ||
// the next task when it completes (or errors), and returning the | ||
// result in the returned promise. | ||
private submitTaskToRun(task: () => Promise<T>): Promise<T> { | ||
return new Promise((resolve, reject) => { | ||
const onFinish = () => { | ||
this.#runningTasks -= 1; | ||
this.tryRunNextTask(); | ||
}; | ||
|
||
const taskToRun = () => { | ||
task() | ||
.then((item) => { | ||
resolve(item); | ||
onFinish(); | ||
}) | ||
.catch((err) => { | ||
reject(err); | ||
onFinish(); | ||
}); | ||
}; | ||
|
||
this.#tasks.pushBack(taskToRun); | ||
this.tryRunNextTask(); | ||
}); | ||
} | ||
|
||
/** | ||
* Push a new task onto the queue. It will run when there are fewer | ||
* than `maxTasks` running. | ||
*/ | ||
run(task: () => Promise<T>): Promise<T> { | ||
return this.submitTaskToRun(task); | ||
} | ||
} | ||
|
||
type LinkedListItem<T> = { item: T; next: null | LinkedListItem<T> }; | ||
|
||
/** | ||
* A quick LinkedList queue implementation; we can add items to the back | ||
* or remove them from the front. | ||
*/ | ||
class LinkedList<T> { | ||
#first: LinkedListItem<T> | null = null; | ||
#last: LinkedListItem<T> | null = null; | ||
|
||
private init(item: T): void { | ||
this.#first = this.#last = { item, next: null }; | ||
} | ||
|
||
pushBack(item: T) { | ||
if (!this.#first) return this.init(item); | ||
const entry = { item, next: null }; | ||
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */ | ||
this.#last!.next = entry; | ||
this.#last = entry; | ||
} | ||
|
||
popFront(): T | null { | ||
if (!this.#first) return null; | ||
const entry = this.#first; | ||
this.#first = this.#first.next; | ||
return entry.item; | ||
} | ||
|
||
clear(): void { | ||
this.#first = this.#last = null; | ||
} | ||
|
||
empty(): boolean { | ||
return this.#first === null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { verifyNonZeroUInt, verifyUInt } from './verifyInt'; | ||
|
||
describe('Verify integers', () => { | ||
describe('verifyUInt', () => { | ||
it('Should correctly handle unsigned integers correctly', () => { | ||
expect(verifyUInt(0)).toBe(true); | ||
expect(verifyUInt(1)).toBe(true); | ||
expect(verifyUInt(-1)).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('verifyNonZeroUInt', () => { | ||
it('Should correctly handle unsigned integers correctly', () => { | ||
expect(verifyNonZeroUInt(1)).toBe(true); | ||
expect(verifyNonZeroUInt(0)).toBe(false); | ||
expect(verifyNonZeroUInt(-1)).toBe(false); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* Verify all integers including zeroes. | ||
* @param num | ||
*/ | ||
export const verifyUInt = (num: Number): boolean => { | ||
return Number.isInteger(num) && num >= 0; | ||
}; | ||
|
||
/** | ||
* Verify all integers except for zero. Will return false when zero is inputted. | ||
* @param num | ||
*/ | ||
export const verifyNonZeroUInt = (num: Number): boolean => { | ||
return Number.isInteger(num) && num > 0; | ||
}; |