Skip to content

Commit e771564

Browse files
committed
recurring timeout bugs fixed + tests adjestments
1 parent 224c1fd commit e771564

File tree

3 files changed

+54
-56
lines changed

3 files changed

+54
-56
lines changed

src/classes/recurringTimeout/recurringTimeout.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class RecurringTimeout implements IRecurringTimeout {
6767
}
6868

6969
stop() {
70+
this.startScheduled = false
7071
this.#reset()
7172
}
7273

@@ -76,8 +77,6 @@ export class RecurringTimeout implements IRecurringTimeout {
7677
}
7778

7879
async #loop() {
79-
if (this.promise) return // prevents multiple executions in one tick
80-
8180
try {
8281
this.promise = this.#fn()
8382
this.fnExecutionsCount += 1
@@ -117,6 +116,8 @@ export class RecurringTimeout implements IRecurringTimeout {
117116

118117
if (newTimeout) this.updateTimeout({ timeout: newTimeout })
119118

119+
if (this.promise) return // prevents multiple executions in one tick
120+
120121
if (runImmediately) {
121122
this.#loop()
122123
} else {
@@ -127,8 +128,6 @@ export class RecurringTimeout implements IRecurringTimeout {
127128

128129
#reset() {
129130
this.running = false
130-
this.promise = undefined
131-
this.startScheduled = false
132131
this.startedRunningAt = 0
133132

134133
if (this.#timeoutId) {

src/controllers/continuousUpdates/continuousUpdates.test.ts

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ACCOUNT_STATE_PENDING_INTERVAL } from '../../consts/intervals'
1010
import { RPCProviders } from '../../interfaces/provider'
1111
import { SubmittedAccountOp } from '../../libs/accountOp/submittedAccountOp'
1212
import { KeystoreSigner } from '../../libs/keystoreSigner/keystoreSigner'
13+
import wait from '../../utils/wait'
1314
import { MainController } from '../main/main'
1415

1516
// Public API key, shared by Socket, for testing purposes only
@@ -103,10 +104,16 @@ const prepareTest = async () => {
103104
velcroUrl
104105
})
105106
mainCtrl.portfolio.updateSelectedAccount = jest.fn().mockResolvedValue(undefined)
106-
mainCtrl.updateSelectedAccountPortfolio = jest.fn().mockResolvedValue(undefined)
107+
mainCtrl.updateSelectedAccountPortfolio = jest.fn().mockImplementation(async () => {
108+
await wait(500)
109+
})
107110
mainCtrl.domains.reverseLookup = jest.fn().mockResolvedValue(undefined)
108-
mainCtrl.accounts.updateAccountStates = jest.fn().mockResolvedValue(undefined)
109-
mainCtrl.accounts.updateAccountState = jest.fn().mockResolvedValue(undefined)
111+
mainCtrl.accounts.updateAccountStates = jest.fn().mockImplementation(async () => {
112+
await wait(500)
113+
})
114+
mainCtrl.accounts.updateAccountState = jest.fn().mockImplementation(async () => {
115+
await wait(500)
116+
})
110117
mainCtrl.updateAccountsOpsStatuses = jest.fn().mockResolvedValue({ newestOpTimestamp: 0 })
111118

112119
return { mainCtrl }
@@ -165,45 +172,30 @@ describe('ContinuousUpdatesController intervals', () => {
165172
const updateSelectedAccountPortfolioSpy = jest.spyOn(mainCtrl, 'updateSelectedAccountPortfolio')
166173
const initialFnExecutionsCount =
167174
mainCtrl.continuousUpdates.updatePortfolioInterval.fnExecutionsCount
168-
const { fnExecutionsCount: fnExecutionsCountFirstCall } = await waitForFnToBeCalledAndExecuted(
169-
mainCtrl.continuousUpdates.updatePortfolioInterval
170-
)
175+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.updatePortfolioInterval)
171176
expect(mainCtrl.continuousUpdates.updatePortfolioInterval.fnExecutionsCount).toBe(
172-
initialFnExecutionsCount + fnExecutionsCountFirstCall
177+
initialFnExecutionsCount + 1
173178
)
174179
const updateSelectedAccountCalledTimes = updateSelectedAccountPortfolioSpy.mock.calls.length
175180
await mainCtrl.activity.addAccountOp(submittedAccountOp)
176181
await jest.advanceTimersByTimeAsync(0)
177-
const { fnExecutionsCount: fnExecutionsCountSecondCall } = await waitForFnToBeCalledAndExecuted(
178-
mainCtrl.continuousUpdates.updatePortfolioInterval
179-
)
182+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.updatePortfolioInterval)
180183
expect(mainCtrl.continuousUpdates.updatePortfolioInterval.fnExecutionsCount).toBe(
181-
initialFnExecutionsCount + fnExecutionsCountFirstCall + fnExecutionsCountSecondCall
184+
initialFnExecutionsCount + 2
182185
)
183186
expect(updateSelectedAccountPortfolioSpy).toHaveBeenCalledTimes(
184187
updateSelectedAccountCalledTimes
185188
) // tests the branching in the updatePortfolio func
186189
mainCtrl.ui.removeView('1')
187190
await jest.advanceTimersByTimeAsync(0)
188191
expect(mainCtrl.continuousUpdates.updatePortfolioInterval.restart).toHaveBeenCalledTimes(2)
189-
const { fnExecutionsCount: fnExecutionsCountThirdCall } = await waitForFnToBeCalledAndExecuted(
190-
mainCtrl.continuousUpdates.updatePortfolioInterval
191-
)
192+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.updatePortfolioInterval)
192193
expect(mainCtrl.continuousUpdates.updatePortfolioInterval.fnExecutionsCount).toBe(
193-
initialFnExecutionsCount +
194-
fnExecutionsCountFirstCall +
195-
fnExecutionsCountSecondCall +
196-
fnExecutionsCountThirdCall
197-
)
198-
const { fnExecutionsCount: fnExecutionsCountFourthCall } = await waitForFnToBeCalledAndExecuted(
199-
mainCtrl.continuousUpdates.updatePortfolioInterval
194+
initialFnExecutionsCount + 3
200195
)
196+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.updatePortfolioInterval)
201197
expect(mainCtrl.continuousUpdates.updatePortfolioInterval.fnExecutionsCount).toBe(
202-
initialFnExecutionsCount +
203-
fnExecutionsCountFirstCall +
204-
fnExecutionsCountSecondCall +
205-
fnExecutionsCountThirdCall +
206-
fnExecutionsCountFourthCall
198+
initialFnExecutionsCount + 4
207199
)
208200
})
209201

@@ -221,17 +213,13 @@ describe('ContinuousUpdatesController intervals', () => {
221213
mainCtrl.continuousUpdates.accountsOpsStatusesInterval.fnExecutionsCount
222214

223215
expect(mainCtrl.continuousUpdates.accountsOpsStatusesInterval.start).toHaveBeenCalled()
224-
const { fnExecutionsCount: fnExecutionsCountFirstCall } = await waitForFnToBeCalledAndExecuted(
225-
mainCtrl.continuousUpdates.accountsOpsStatusesInterval
226-
)
216+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.accountsOpsStatusesInterval)
227217
expect(mainCtrl.continuousUpdates.accountsOpsStatusesInterval.fnExecutionsCount).toBe(
228-
initialFnExecutionsCount + fnExecutionsCountFirstCall
229-
)
230-
const { fnExecutionsCount: fnExecutionsCountSecondCall } = await waitForFnToBeCalledAndExecuted(
231-
mainCtrl.continuousUpdates.accountsOpsStatusesInterval
218+
initialFnExecutionsCount + 1
232219
)
220+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.accountsOpsStatusesInterval)
233221
expect(mainCtrl.continuousUpdates.accountsOpsStatusesInterval.fnExecutionsCount).toBe(
234-
initialFnExecutionsCount + fnExecutionsCountFirstCall + fnExecutionsCountSecondCall
222+
initialFnExecutionsCount + 2
235223
)
236224
jest.spyOn(mainCtrl.activity, 'broadcastedButNotConfirmed', 'get').mockReturnValue([])
237225
// @ts-ignore
@@ -257,10 +245,9 @@ describe('ContinuousUpdatesController intervals', () => {
257245

258246
expect(mainCtrl.continuousUpdates.accountStateLatestInterval.running).toBe(true)
259247
expect(mainCtrl.continuousUpdates.accountStatePendingInterval.running).toBe(false)
260-
const { fnExecutionsCount: accountStateLatestFnExecutionsCountFirstCall } =
261-
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.accountStateLatestInterval)
248+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.accountStateLatestInterval)
262249
expect(mainCtrl.continuousUpdates.accountStateLatestInterval.fnExecutionsCount).toBe(
263-
initialAccountStateLatestFnExecutionsCount + accountStateLatestFnExecutionsCountFirstCall
250+
initialAccountStateLatestFnExecutionsCount + 1
264251
)
265252
mainCtrl.statuses.signAndBroadcastAccountOp = 'SUCCESS'
266253
// @ts-ignore
@@ -273,10 +260,10 @@ describe('ContinuousUpdatesController intervals', () => {
273260
expect(mainCtrl.continuousUpdates.accountStatePendingInterval.currentTimeout).toBe(
274261
ACCOUNT_STATE_PENDING_INTERVAL / 2
275262
)
276-
const { fnExecutionsCount: accountStatePendingFnExecutionsCountFirstCall } =
277-
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.accountStatePendingInterval)
263+
264+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.accountStatePendingInterval)
278265
expect(mainCtrl.continuousUpdates.accountStatePendingInterval.fnExecutionsCount).toBe(
279-
initialAccountStatePendingFnExecutionsCount + accountStatePendingFnExecutionsCountFirstCall
266+
initialAccountStatePendingFnExecutionsCount + 1
280267
)
281268
expect(mainCtrl.continuousUpdates.accountStateLatestInterval.restart).toHaveBeenCalledTimes(2)
282269
expect(mainCtrl.continuousUpdates.accountStatePendingInterval.stop).toHaveBeenCalledTimes(1)
@@ -317,17 +304,32 @@ describe('ContinuousUpdatesController intervals', () => {
317304
expect(mainCtrl.continuousUpdates.fastAccountStateReFetchTimeout.fnExecutionsCount).toBe(
318305
initialFnExecutionsCount
319306
)
320-
const { fnExecutionsCount: fnExecutionsCountFirstCall } = await waitForFnToBeCalledAndExecuted(
321-
mainCtrl.continuousUpdates.fastAccountStateReFetchTimeout
322-
)
307+
// @ts-ignore
308+
mainCtrl.providers.emitUpdate()
309+
// @ts-ignore
310+
mainCtrl.providers.emitUpdate()
311+
// @ts-ignore
312+
mainCtrl.providers.emitUpdate()
313+
314+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.fastAccountStateReFetchTimeout)
315+
// @ts-ignore
316+
mainCtrl.providers.emitUpdate()
317+
// @ts-ignore
318+
mainCtrl.providers.emitUpdate()
319+
323320
expect(mainCtrl.continuousUpdates.fastAccountStateReFetchTimeout.fnExecutionsCount).toBe(
324-
initialFnExecutionsCount + fnExecutionsCountFirstCall
325-
)
326-
const { fnExecutionsCount: fnExecutionsCountSecondCall } = await waitForFnToBeCalledAndExecuted(
327-
mainCtrl.continuousUpdates.fastAccountStateReFetchTimeout
321+
initialFnExecutionsCount + 1
328322
)
323+
// @ts-ignore
324+
mainCtrl.providers.emitUpdate()
325+
// @ts-ignore
326+
mainCtrl.providers.emitUpdate()
327+
// @ts-ignore
328+
mainCtrl.providers.emitUpdate()
329+
330+
await waitForFnToBeCalledAndExecuted(mainCtrl.continuousUpdates.fastAccountStateReFetchTimeout)
329331
expect(mainCtrl.continuousUpdates.fastAccountStateReFetchTimeout.fnExecutionsCount).toBe(
330-
initialFnExecutionsCount + fnExecutionsCountFirstCall + fnExecutionsCountSecondCall
332+
initialFnExecutionsCount + 2
331333
)
332334
})
333335
})

test/recurringTimeout.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ export const waitForFnToBeCalledAndExecuted = async (
55
recurringTimeout: IRecurringTimeout,
66
// eslint-disable-next-line @typescript-eslint/no-unused-vars
77
id: string = '' // for testing
8-
): Promise<{ fnExecutionsCount: number }> => {
9-
const initialFnExecutionsCount = recurringTimeout.fnExecutionsCount
8+
): Promise<void> => {
109
while (recurringTimeout.startScheduled) {
1110
await jest.advanceTimersByTimeAsync(1)
1211
}
@@ -28,6 +27,4 @@ export const waitForFnToBeCalledAndExecuted = async (
2827
}
2928
expect(recurringTimeout.promise).toBe(undefined)
3029
await Promise.resolve()
31-
32-
return { fnExecutionsCount: recurringTimeout.fnExecutionsCount - initialFnExecutionsCount }
3330
}

0 commit comments

Comments
 (0)