Skip to content

Commit

Permalink
reduce background network access
Browse files Browse the repository at this point in the history
Skip the UpstreamHealthProviderCheck if the window is not focused, and try again when the window becomes focused again. Some users have OS firewalls that make periodic background network access annoying for users. See https://linear.app/sourcegraph/issue/CODY-3745/codys-background-periodic-network-access-causes-2fa.

This check is used to gather latency information to properly measure actual latency for autocomplete. As long as the user has VS Code focused for slightly more than 10 seconds, it will still gather the necessary latency information for these calculations.

Fixes https://linear.app/sourcegraph/issue/CODY-3745/codys-background-periodic-network-access-causes-2fa
  • Loading branch information
sqs committed Sep 13, 2024
1 parent ccab0ed commit fc4524b
Showing 1 changed file with 34 additions and 6 deletions.
40 changes: 34 additions & 6 deletions vscode/src/services/UpstreamHealthProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
wrapInActiveSpan,
} from '@sourcegraph/cody-shared'
import { fetch } from '@sourcegraph/cody-shared'
import type * as vscode from 'vscode'
import * as vscode from 'vscode'

// We choose an interval that gives us a reasonable aggregate without causing
// too many requests
Expand All @@ -27,12 +27,25 @@ class UpstreamHealthProvider implements vscode.Disposable {
private lastUpstreamLatency?: number
private lastGatewayLatency?: number

private disposables: vscode.Disposable[] = []

private config: Pick<
ClientConfigurationWithAccessToken,
'serverEndpoint' | 'customHeaders' | 'accessToken'
> | null = null
private nextTimeoutId: NodeJS.Timeout | null = null

constructor() {
this.disposables.push(
vscode.window.onDidChangeWindowState(state => {

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/create-inline-completion-item-provider.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/get-current-doc-context.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/inline-completion-item-provider-e2e.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/inline-completion-item-provider.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/logger.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/request-manager.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/smart-throttle.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/text-processing.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/context/openctx.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 20)

src/completions/context/context-mixer.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/create-inline-completion-item-provider.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/get-current-doc-context.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/inline-completion-item-provider-e2e.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/inline-completion-item-provider.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/logger.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/request-manager.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/smart-throttle.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/text-processing.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/context/openctx.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (ubuntu, 18)

src/completions/context/context-mixer.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/create-inline-completion-item-provider.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/get-current-doc-context.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/inline-completion-item-provider-e2e.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/inline-completion-item-provider.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/logger.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/request-manager.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/smart-throttle.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/text-processing.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/context/openctx.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31

Check failure on line 40 in vscode/src/services/UpstreamHealthProvider.ts

View workflow job for this annotation

GitHub Actions / test-unit (windows, 20)

src/completions/context/context-mixer.test.ts

TypeError: window.onDidChangeWindowState is not a function ❯ new UpstreamHealthProvider src/services/UpstreamHealthProvider.ts:40:27 ❯ src/services/UpstreamHealthProvider.ts:186:38 ❯ src/completions/logger.ts:10:31
if (state.focused && this.lastMeasurementSkippedBecauseNotFocused) {
this.lastMeasurementSkippedBecauseNotFocused = false
this.enqueue(INITIAL_PING_DELAY_MS)
}
})
)
}

public getUpstreamLatency(): number | undefined {
if (!this.config) {
return undefined
Expand Down Expand Up @@ -60,12 +73,18 @@ class UpstreamHealthProvider implements vscode.Disposable {
// Enqueue the initial ping after a config change in 10 seconds. This
// avoids running the test while the extension is still initializing and
// competing with many other network requests.
this.enqueue(INITIAL_PING_DELAY_MS)
}

private enqueue(delay: number): void {
if (this.nextTimeoutId) {
clearTimeout(this.nextTimeoutId)
}
this.nextTimeoutId = setTimeout(this.measure.bind(this), INITIAL_PING_DELAY_MS)
this.nextTimeoutId = setTimeout(this.measure.bind(this), delay)
}

private lastMeasurementSkippedBecauseNotFocused = false

private async measure() {
if (this.nextTimeoutId) {
clearTimeout(this.nextTimeoutId)
Expand All @@ -76,6 +95,15 @@ class UpstreamHealthProvider implements vscode.Disposable {
return
}

if (!vscode.window.state.focused) {
// Skip if the window is not focused, and try again when the window becomes focused
// again. Some users have OS firewalls that make periodic background network access
// annoying for users, and this eliminates that annoyance. See
// https://linear.app/sourcegraph/issue/CODY-3745/codys-background-periodic-network-access-causes-2fa.
this.lastMeasurementSkippedBecauseNotFocused = true
return
}

if (!this.config) {
throw new Error('UpstreamHealthProvider not initialized')
}
Expand Down Expand Up @@ -140,17 +168,17 @@ class UpstreamHealthProvider implements vscode.Disposable {
// We don't care about errors here, we just want to measure the latency
} finally {
// Enqueue a new ping
if (this.nextTimeoutId) {
clearTimeout(this.nextTimeoutId)
}
this.nextTimeoutId = setTimeout(this.measure.bind(this), PING_INTERVAL_MS)
this.enqueue(PING_INTERVAL_MS)
}
}

public dispose(): void {
if (this.nextTimeoutId) {
clearTimeout(this.nextTimeoutId)
}
for (const disposable of this.disposables) {
disposable.dispose()
}
}
}

Expand Down

0 comments on commit fc4524b

Please sign in to comment.