|
| 1 | +import { DryRun, DryRunResult, MessageInput } from "@permaweb/aoconnect/dist/lib/dryrun"; |
| 2 | +import { connect } from "@permaweb/aoconnect"; |
| 3 | + |
| 4 | +interface DryRunQueueItem { |
| 5 | + msg: MessageInput; |
| 6 | + resolve: (result: DryRunResult) => void; |
| 7 | + reject: (reason?: any) => void; |
| 8 | +} |
| 9 | + |
| 10 | +export class DryRunFIFO { |
| 11 | + #queue: DryRunQueueItem[]; |
| 12 | + #running: boolean; |
| 13 | + #availableDryRuns: DryRunList; |
| 14 | + |
| 15 | + constructor(CUs: string[], delay = 500) { |
| 16 | + this.#queue = []; |
| 17 | + this.#running = false; |
| 18 | + this.#availableDryRuns = new DryRunList(CUs.map( |
| 19 | + (CU_URL) => connect({ MODE: "legacy", CU_URL }).dryrun |
| 20 | + ), delay); |
| 21 | + } |
| 22 | + |
| 23 | + put(msg: MessageInput) { |
| 24 | + return new Promise<DryRunResult>((resolve, reject) => { |
| 25 | + this.#queue.push({ msg, resolve, reject }); |
| 26 | + this.#run(); |
| 27 | + }); |
| 28 | + } |
| 29 | + |
| 30 | + async #run() { |
| 31 | + if (this.#running) return; |
| 32 | + this.#running = true; |
| 33 | + |
| 34 | + while (this.#queue.length > 0) { |
| 35 | + const dryrun = await this.#availableDryRuns.waitForOne(); |
| 36 | + const { msg, resolve, reject } = this.#queue.shift()!; |
| 37 | + |
| 38 | + dryrun(msg) |
| 39 | + .then(resolve) |
| 40 | + .catch(reject) |
| 41 | + .finally(() => this.#availableDryRuns.push(dryrun)); |
| 42 | + } |
| 43 | + |
| 44 | + this.#running = false; |
| 45 | + } |
| 46 | +} |
| 47 | + |
| 48 | +class DryRunList { |
| 49 | + #list: DryRun[]; |
| 50 | + #delay: number; |
| 51 | + #resolves: Array<(val: DryRun) => void>; |
| 52 | + |
| 53 | + constructor(list: DryRun[] = [], delay: number) { |
| 54 | + this.#list = list; |
| 55 | + this.#delay = delay; |
| 56 | + this.#resolves = []; |
| 57 | + } |
| 58 | + |
| 59 | + push(item: DryRun) { |
| 60 | + setTimeout(() => { |
| 61 | + const nextRequest = this.#resolves.shift(); |
| 62 | + if (nextRequest) nextRequest(item); |
| 63 | + else this.#list.push(item); |
| 64 | + }, this.#delay); |
| 65 | + } |
| 66 | + |
| 67 | + async waitForOne() { |
| 68 | + const next = this.#list.shift(); |
| 69 | + if (next) return next; |
| 70 | + |
| 71 | + return new Promise<DryRun>((resolve) => { |
| 72 | + this.#resolves.push(resolve); |
| 73 | + }); |
| 74 | + } |
| 75 | +} |
0 commit comments