Fix throttle function, add retryAuth
This commit is contained in:
@@ -147,14 +147,14 @@ describe("Tools", () => {
|
|||||||
batchFn("b")
|
batchFn("b")
|
||||||
batchFn("c")
|
batchFn("c")
|
||||||
|
|
||||||
await vi.advanceTimersByTimeAsync(100)
|
await vi.advanceTimersByTimeAsync(300)
|
||||||
|
|
||||||
// Second batch
|
// Second batch
|
||||||
batchFn("d")
|
batchFn("d")
|
||||||
batchFn("e")
|
batchFn("e")
|
||||||
batchFn("f")
|
batchFn("f")
|
||||||
|
|
||||||
await vi.advanceTimersByTimeAsync(100)
|
await vi.advanceTimersByTimeAsync(110)
|
||||||
|
|
||||||
expect(processBatch).toHaveBeenCalledTimes(4)
|
expect(processBatch).toHaveBeenCalledTimes(4)
|
||||||
expect(processBatch).toHaveBeenCalledWith(["a"])
|
expect(processBatch).toHaveBeenCalledWith(["a"])
|
||||||
@@ -233,11 +233,10 @@ describe("Tools", () => {
|
|||||||
|
|
||||||
// Subsequent calls within throttle window should return cached value
|
// Subsequent calls within throttle window should return cached value
|
||||||
expect(throttledGet()).toBe(1)
|
expect(throttledGet()).toBe(1)
|
||||||
expect(throttledGet()).toBe(1)
|
|
||||||
expect(getValue).toHaveBeenCalledTimes(1)
|
expect(getValue).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
// After throttle window, should update value
|
// After throttle window, should update value
|
||||||
await vi.advanceTimersByTimeAsync(100)
|
await vi.advanceTimersByTimeAsync(300)
|
||||||
// the previous 2 called will have been batched, and the next throttledGet increase the counter to 3
|
// the previous 2 called will have been batched, and the next throttledGet increase the counter to 3
|
||||||
expect(throttledGet()).toBe(3)
|
expect(throttledGet()).toBe(3)
|
||||||
expect(getValue).toHaveBeenCalledTimes(3)
|
expect(getValue).toHaveBeenCalledTimes(3)
|
||||||
@@ -253,17 +252,15 @@ describe("Tools", () => {
|
|||||||
|
|
||||||
// Multiple calls within window
|
// Multiple calls within window
|
||||||
for (let i = 0; i < 4; i++) {
|
for (let i = 0; i < 4; i++) {
|
||||||
throttledGet()
|
expect(throttledGet()).toBe(1)
|
||||||
await vi.advanceTimersByTimeAsync(20) // 20ms each, still within 100ms window
|
await vi.advanceTimersByTimeAsync(20) // 20ms each, still within 100ms window
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(getValue).toHaveBeenCalledTimes(1)
|
expect(getValue).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
// After window
|
|
||||||
await vi.advanceTimersByTimeAsync(100)
|
await vi.advanceTimersByTimeAsync(100)
|
||||||
// the previous called will have been batched, and the next throttledGet increase the counter to 3
|
expect(throttledGet()).toBe(2)
|
||||||
expect(throttledGet()).toBe(3)
|
expect(getValue).toHaveBeenCalledTimes(2)
|
||||||
expect(getValue).toHaveBeenCalledTimes(3)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should handle zero throttle time", () => {
|
it("should handle zero throttle time", () => {
|
||||||
|
|||||||
@@ -1109,10 +1109,11 @@ export const throttle = <F extends (...args: any[]) => any>(ms: number, f: F) =>
|
|||||||
if (nextArgs) {
|
if (nextArgs) {
|
||||||
f(...nextArgs)
|
f(...nextArgs)
|
||||||
nextArgs = undefined
|
nextArgs = undefined
|
||||||
}
|
setTimeout(unpause, ms)
|
||||||
|
} else {
|
||||||
paused = false
|
paused = false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (...thisArgs: Parameters<F>) => {
|
return (...thisArgs: Parameters<F>) => {
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ export type AuthStateEvents = {
|
|||||||
[AuthStateEvent.Status]: (status: AuthStatus) => void
|
[AuthStateEvent.Status]: (status: AuthStatus) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Sign = (event: StampedEvent) => Promise<SignedEvent>
|
||||||
|
|
||||||
export class AuthState extends EventEmitter {
|
export class AuthState extends EventEmitter {
|
||||||
challenge: string | undefined
|
challenge: string | undefined
|
||||||
request: string | undefined
|
request: string | undefined
|
||||||
@@ -89,7 +91,7 @@ export class AuthState extends EventEmitter {
|
|||||||
this.emit(AuthStateEvent.Status, status)
|
this.emit(AuthStateEvent.Status, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
async doAuth(sign: (event: StampedEvent) => Promise<SignedEvent>) {
|
async doAuth(sign: Sign) {
|
||||||
if (!this.challenge) {
|
if (!this.challenge) {
|
||||||
throw new Error("Attempted to authenticate with no challenge")
|
throw new Error("Attempted to authenticate with no challenge")
|
||||||
}
|
}
|
||||||
@@ -111,7 +113,7 @@ export class AuthState extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async attemptAuth(sign: (event: StampedEvent) => Promise<SignedEvent>) {
|
async attemptAuth(sign: Sign) {
|
||||||
this.socket.attemptToOpen()
|
this.socket.attemptToOpen()
|
||||||
|
|
||||||
if (![AuthStatus.Forbidden, AuthStatus.Ok].includes(this.status)) {
|
if (![AuthStatus.Forbidden, AuthStatus.Ok].includes(this.status)) {
|
||||||
@@ -131,6 +133,16 @@ export class AuthState extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async retryAuth(sign: Sign) {
|
||||||
|
if (this.challenge) {
|
||||||
|
this.request = undefined
|
||||||
|
this.details = undefined
|
||||||
|
this.setStatus(AuthStatus.Requested)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.attemptAuth(sign)
|
||||||
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
this.removeAllListeners()
|
this.removeAllListeners()
|
||||||
this._unsubscribers.forEach(call)
|
this._unsubscribers.forEach(call)
|
||||||
|
|||||||
Reference in New Issue
Block a user