Skip to content

Commit 59476a1

Browse files
address comment
1 parent d70ae7a commit 59476a1

5 files changed

Lines changed: 31 additions & 21 deletions

File tree

packages/app/src/cli/services/app-logs/dev/poll-app-logs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ export const pollAppLogs = async ({
107107
},
108108
})
109109

110-
if (result.resubscribeFailed) {
110+
if (result.resubscribeResult === 'failed') {
111111
nextConsecutiveResubscribeFailures += 1
112112
if (nextConsecutiveResubscribeFailures >= MAX_CONSECUTIVE_RESUBSCRIBE_FAILURES) {
113113
outputWarn('App log streaming session has expired. Please restart your dev session.', stdout)
114114
return
115115
}
116-
} else {
116+
} else if (result.resubscribeResult === 'succeeded') {
117117
nextConsecutiveResubscribeFailures = 0
118118
}
119119

packages/app/src/cli/services/app-logs/logs-command/render-json-logs.test.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,19 @@ describe('renderJsonLogs', () => {
102102
})
103103

104104
test('should retry at throttle interval when handleFetchAppLogsError returns null token', async () => {
105+
const timeoutSpy = vi.spyOn(global, 'setTimeout')
105106
const mockErrorResponse = {
106107
errors: [{status: 401, message: 'Unauthorized'}],
107108
}
108109
const pollAppLogsMock = vi.fn().mockResolvedValue(mockErrorResponse)
109110
vi.mocked(pollAppLogs).mockImplementation(pollAppLogsMock)
110111
const throttleRetryInterval = 60000
111112
const handleFetchAppLogsErrorMock = vi.fn(() => {
112-
return Promise.resolve({nextJwtToken: null, retryIntervalMs: throttleRetryInterval, resubscribeFailed: false})
113+
return Promise.resolve({
114+
nextJwtToken: null,
115+
retryIntervalMs: throttleRetryInterval,
116+
resubscribeResult: 'not_attempted' as const,
117+
})
113118
})
114119
vi.mocked(handleFetchAppLogsError).mockImplementation(handleFetchAppLogsErrorMock)
115120

@@ -127,7 +132,7 @@ describe('renderJsonLogs', () => {
127132

128133
expect(handleFetchAppLogsError).toHaveBeenCalled()
129134
expect(pollAppLogs).toHaveBeenCalled()
130-
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), throttleRetryInterval)
135+
expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), throttleRetryInterval)
131136
expect(vi.getTimerCount()).toEqual(1)
132137
})
133138

@@ -138,7 +143,7 @@ describe('renderJsonLogs', () => {
138143
const pollAppLogsMock = vi.fn().mockResolvedValue(mockErrorResponse)
139144
vi.mocked(pollAppLogs).mockImplementation(pollAppLogsMock)
140145
const handleFetchAppLogsErrorMock = vi.fn(() => {
141-
return Promise.resolve({nextJwtToken: null, retryIntervalMs: 60000, resubscribeFailed: true})
146+
return Promise.resolve({nextJwtToken: null, retryIntervalMs: 60000, resubscribeResult: 'failed' as const})
142147
})
143148
vi.mocked(handleFetchAppLogsError).mockImplementation(handleFetchAppLogsErrorMock)
144149

@@ -171,11 +176,13 @@ describe('renderJsonLogs', () => {
171176
const mockRetryInterval = 1000
172177
const handleFetchAppLogsErrorMock = vi.fn((input) => {
173178
input.onUnknownError(mockRetryInterval)
174-
return new Promise<{retryIntervalMs: number; nextJwtToken: string | null; resubscribeFailed: boolean}>(
175-
(resolve, _reject) => {
176-
resolve({nextJwtToken: 'new-jwt-token', retryIntervalMs: mockRetryInterval, resubscribeFailed: false})
177-
},
178-
)
179+
return new Promise<{
180+
retryIntervalMs: number
181+
nextJwtToken: string | null
182+
resubscribeResult: 'succeeded' | 'failed' | 'not_attempted'
183+
}>((resolve, _reject) => {
184+
resolve({nextJwtToken: 'new-jwt-token', retryIntervalMs: mockRetryInterval, resubscribeResult: 'not_attempted'})
185+
})
179186
})
180187
vi.mocked(handleFetchAppLogsError).mockImplementation(handleFetchAppLogsErrorMock)
181188

packages/app/src/cli/services/app-logs/logs-command/render-json-logs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ export async function renderJsonLogs({
4444
},
4545
})
4646

47-
if (result.resubscribeFailed) {
47+
if (result.resubscribeResult === 'failed') {
4848
nextConsecutiveResubscribeFailures += 1
4949
if (nextConsecutiveResubscribeFailures >= MAX_CONSECUTIVE_RESUBSCRIBE_FAILURES) {
5050
outputInfo(JSON.stringify({message: 'App log streaming session has expired. Please restart your dev session.'}))
5151
return
5252
}
53-
} else {
53+
} else if (result.resubscribeResult === 'succeeded') {
5454
nextConsecutiveResubscribeFailures = 0
5555
}
5656

packages/app/src/cli/services/app-logs/logs-command/ui/components/hooks/usePollAppLogs.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ async function performPoll({
5858
organizationId,
5959
})
6060

61-
let resubscribeFailed = false
61+
let resubscribeResult: 'succeeded' | 'failed' | 'not_attempted' = 'not_attempted'
6262
const errorResponse = response as ErrorResponse
6363

6464
if (errorResponse.errors) {
@@ -75,7 +75,7 @@ async function performPoll({
7575
},
7676
})
7777

78-
resubscribeFailed = result.resubscribeFailed
78+
resubscribeResult = result.resubscribeResult
7979

8080
if (result.nextJwtToken) {
8181
nextJwtToken = result.nextJwtToken
@@ -138,7 +138,7 @@ async function performPoll({
138138
}
139139
}
140140

141-
return {nextJwtToken, retryIntervalMs, cursor: nextCursor ?? cursor, resubscribeFailed}
141+
return {nextJwtToken, retryIntervalMs, cursor: nextCursor ?? cursor, resubscribeResult}
142142
}
143143

144144
export function usePollAppLogs({
@@ -169,13 +169,13 @@ export function usePollAppLogs({
169169
organizationId,
170170
})
171171

172-
if (res.resubscribeFailed) {
172+
if (res.resubscribeResult === 'failed') {
173173
consecutiveResubscribeFailures.current += 1
174174
if (consecutiveResubscribeFailures.current >= MAX_CONSECUTIVE_RESUBSCRIBE_FAILURES) {
175175
setErrors(['App log streaming session has expired. Please restart your dev session.'])
176176
return {retryIntervalMs: 0}
177177
}
178-
} else {
178+
} else if (res.resubscribeResult === 'succeeded') {
179179
consecutiveResubscribeFailures.current = 0
180180
}
181181

packages/app/src/cli/services/app-logs/utils.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,26 +108,29 @@ export interface AppLogsOptions {
108108
}
109109
}
110110

111+
type ResubscribeResult = 'succeeded' | 'failed' | 'not_attempted'
112+
111113
export const handleFetchAppLogsError = async (
112114
input: FetchAppLogsErrorOptions,
113-
): Promise<{retryIntervalMs: number; nextJwtToken: string | null; resubscribeFailed: boolean}> => {
115+
): Promise<{retryIntervalMs: number; nextJwtToken: string | null; resubscribeResult: ResubscribeResult}> => {
114116
const {errors} = input.response
115117

116118
let retryIntervalMs = POLLING_INTERVAL_MS
117119
let nextJwtToken = null
118-
let resubscribeFailed = false
120+
let resubscribeResult: ResubscribeResult = 'not_attempted'
119121

120122
if (errors.length > 0) {
121123
outputDebug(`Errors: ${errors.map((error) => error.message).join(', ')}`)
122124

123125
if (errors.some((error) => error.status === 401)) {
124126
try {
125127
nextJwtToken = await input.onResubscribe()
128+
resubscribeResult = 'succeeded'
126129
// eslint-disable-next-line no-catch-all/no-catch-all
127130
} catch (resubscribeError) {
128131
outputDebug(`Failed to resubscribe to app logs: ${resubscribeError}`)
129132
retryIntervalMs = POLLING_THROTTLE_RETRY_INTERVAL_MS
130-
resubscribeFailed = true
133+
resubscribeResult = 'failed'
131134
input.onThrottle(retryIntervalMs)
132135
}
133136
} else if (errors.some((error) => error.status === 429)) {
@@ -139,7 +142,7 @@ export const handleFetchAppLogsError = async (
139142
}
140143
}
141144

142-
return {retryIntervalMs, nextJwtToken, resubscribeFailed}
145+
return {retryIntervalMs, nextJwtToken, resubscribeResult}
143146
}
144147

145148
export function sourcesForApp(app: AppInterface): string[] {

0 commit comments

Comments
 (0)