Skip to content

Commit 6e835de

Browse files
jrroomote[bot]
andauthored
Cloud service cleanup callbacks / move to events (#6519)
* Cloud: use events in SettingsService * Cloud: simplify AuthService events * Cloud: convert CloudService to an EventEmitter * Apply suggestions from code review Co-authored-by: roomote[bot] <219738659+roomote[bot]@users.noreply.github.com> --------- Co-authored-by: roomote[bot] <219738659+roomote[bot]@users.noreply.github.com>
1 parent 079fc22 commit 6e835de

File tree

11 files changed

+764
-143
lines changed

11 files changed

+764
-143
lines changed

packages/cloud/src/CloudService.ts

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as vscode from "vscode"
2+
import EventEmitter from "events"
23

34
import type {
45
CloudUserInfo,
@@ -10,7 +11,7 @@ import type {
1011
} from "@roo-code/types"
1112
import { TelemetryService } from "@roo-code/telemetry"
1213

13-
import { CloudServiceCallbacks } from "./types"
14+
import { CloudServiceEvents } from "./types"
1415
import type { AuthService } from "./auth"
1516
import { WebAuthService, StaticTokenAuthService } from "./auth"
1617
import type { SettingsService } from "./SettingsService"
@@ -19,25 +20,37 @@ import { StaticSettingsService } from "./StaticSettingsService"
1920
import { TelemetryClient } from "./TelemetryClient"
2021
import { ShareService, TaskNotFoundError } from "./ShareService"
2122

22-
export class CloudService {
23+
type AuthStateChangedPayload = CloudServiceEvents["auth-state-changed"][0]
24+
type AuthUserInfoPayload = CloudServiceEvents["user-info"][0]
25+
type SettingsPayload = CloudServiceEvents["settings-updated"][0]
26+
27+
export class CloudService extends EventEmitter<CloudServiceEvents> implements vscode.Disposable {
2328
private static _instance: CloudService | null = null
2429

2530
private context: vscode.ExtensionContext
26-
private callbacks: CloudServiceCallbacks
27-
private authListener: () => void
31+
private authStateListener: (data: AuthStateChangedPayload) => void
32+
private authUserInfoListener: (data: AuthUserInfoPayload) => void
2833
private authService: AuthService | null = null
34+
private settingsListener: (data: SettingsPayload) => void
2935
private settingsService: SettingsService | null = null
3036
private telemetryClient: TelemetryClient | null = null
3137
private shareService: ShareService | null = null
3238
private isInitialized = false
3339
private log: (...args: unknown[]) => void
3440

35-
private constructor(context: vscode.ExtensionContext, callbacks: CloudServiceCallbacks) {
41+
private constructor(context: vscode.ExtensionContext, log?: (...args: unknown[]) => void) {
42+
super()
43+
3644
this.context = context
37-
this.callbacks = callbacks
38-
this.log = callbacks.log || console.log
39-
this.authListener = () => {
40-
this.callbacks.stateChanged?.()
45+
this.log = log || console.log
46+
this.authStateListener = (data: AuthStateChangedPayload) => {
47+
this.emit("auth-state-changed", data)
48+
}
49+
this.authUserInfoListener = (data: AuthUserInfoPayload) => {
50+
this.emit("user-info", data)
51+
}
52+
this.settingsListener = (data: SettingsPayload) => {
53+
this.emit("settings-updated", data)
4154
}
4255
}
4356

@@ -57,26 +70,20 @@ export class CloudService {
5770

5871
await this.authService.initialize()
5972

60-
this.authService.on("attempting-session", this.authListener)
61-
this.authService.on("inactive-session", this.authListener)
62-
this.authService.on("active-session", this.authListener)
63-
this.authService.on("logged-out", this.authListener)
64-
this.authService.on("user-info", this.authListener)
73+
this.authService.on("auth-state-changed", this.authStateListener)
74+
this.authService.on("user-info", this.authUserInfoListener)
6575

6676
// Check for static settings environment variable.
6777
const staticOrgSettings = process.env.ROO_CODE_CLOUD_ORG_SETTINGS
6878

6979
if (staticOrgSettings && staticOrgSettings.length > 0) {
7080
this.settingsService = new StaticSettingsService(staticOrgSettings, this.log)
7181
} else {
72-
const cloudSettingsService = new CloudSettingsService(
73-
this.context,
74-
this.authService,
75-
() => this.callbacks.stateChanged?.(),
76-
this.log,
77-
)
78-
82+
const cloudSettingsService = new CloudSettingsService(this.context, this.authService, this.log)
7983
cloudSettingsService.initialize()
84+
85+
cloudSettingsService.on("settings-updated", this.settingsListener)
86+
8087
this.settingsService = cloudSettingsService
8188
}
8289

@@ -219,13 +226,13 @@ export class CloudService {
219226

220227
public dispose(): void {
221228
if (this.authService) {
222-
this.authService.off("attempting-session", this.authListener)
223-
this.authService.off("inactive-session", this.authListener)
224-
this.authService.off("active-session", this.authListener)
225-
this.authService.off("logged-out", this.authListener)
226-
this.authService.off("user-info", this.authListener)
229+
this.authService.off("auth-state-changed", this.authStateListener)
230+
this.authService.off("user-info", this.authUserInfoListener)
227231
}
228232
if (this.settingsService) {
233+
if (this.settingsService instanceof CloudSettingsService) {
234+
this.settingsService.off("settings-updated", this.settingsListener)
235+
}
229236
this.settingsService.dispose()
230237
}
231238

@@ -248,13 +255,13 @@ export class CloudService {
248255

249256
static async createInstance(
250257
context: vscode.ExtensionContext,
251-
callbacks: CloudServiceCallbacks = {},
258+
log?: (...args: unknown[]) => void,
252259
): Promise<CloudService> {
253260
if (this._instance) {
254261
throw new Error("CloudService instance already created")
255262
}
256263

257-
this._instance = new CloudService(context, callbacks)
264+
this._instance = new CloudService(context, log)
258265
await this._instance.initialize()
259266
return this._instance
260267
}

packages/cloud/src/CloudSettingsService.ts

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as vscode from "vscode"
2+
import EventEmitter from "events"
23

34
import {
45
ORGANIZATION_ALLOW_ALL,
@@ -8,32 +9,38 @@ import {
89
} from "@roo-code/types"
910

1011
import { getRooCodeApiUrl } from "./Config"
11-
import type { AuthService } from "./auth"
12+
import type { AuthService, AuthState } from "./auth"
1213
import { RefreshTimer } from "./RefreshTimer"
1314
import type { SettingsService } from "./SettingsService"
1415

1516
const ORGANIZATION_SETTINGS_CACHE_KEY = "organization-settings"
1617

17-
export class CloudSettingsService implements SettingsService {
18+
export interface SettingsServiceEvents {
19+
"settings-updated": [
20+
data: {
21+
settings: OrganizationSettings
22+
previousSettings: OrganizationSettings | undefined
23+
},
24+
]
25+
}
26+
27+
export class CloudSettingsService extends EventEmitter<SettingsServiceEvents> implements SettingsService {
1828
private context: vscode.ExtensionContext
1929
private authService: AuthService
2030
private settings: OrganizationSettings | undefined = undefined
2131
private timer: RefreshTimer
2232
private log: (...args: unknown[]) => void
2333

24-
constructor(
25-
context: vscode.ExtensionContext,
26-
authService: AuthService,
27-
callback: () => void,
28-
log?: (...args: unknown[]) => void,
29-
) {
34+
constructor(context: vscode.ExtensionContext, authService: AuthService, log?: (...args: unknown[]) => void) {
35+
super()
36+
3037
this.context = context
3138
this.authService = authService
3239
this.log = log || console.log
3340

3441
this.timer = new RefreshTimer({
3542
callback: async () => {
36-
return await this.fetchSettings(callback)
43+
return await this.fetchSettings()
3744
},
3845
successInterval: 30000,
3946
initialBackoffMs: 1000,
@@ -49,21 +56,24 @@ export class CloudSettingsService implements SettingsService {
4956
this.removeSettings()
5057
}
5158

52-
this.authService.on("active-session", () => {
53-
this.timer.start()
54-
})
59+
this.authService.on("auth-state-changed", (data: { state: AuthState; previousState: AuthState }) => {
60+
if (data.state === "active-session") {
61+
this.timer.start()
62+
} else if (data.previousState === "active-session") {
63+
this.timer.stop()
5564

56-
this.authService.on("logged-out", () => {
57-
this.timer.stop()
58-
this.removeSettings()
65+
if (data.state === "logged-out") {
66+
this.removeSettings()
67+
}
68+
}
5969
})
6070

6171
if (this.authService.hasActiveSession()) {
6272
this.timer.start()
6373
}
6474
}
6575

66-
private async fetchSettings(callback: () => void): Promise<boolean> {
76+
private async fetchSettings(): Promise<boolean> {
6777
const token = this.authService.getSessionToken()
6878

6979
if (!token) {
@@ -97,9 +107,14 @@ export class CloudSettingsService implements SettingsService {
97107
const newSettings = result.data
98108

99109
if (!this.settings || this.settings.version !== newSettings.version) {
110+
const previousSettings = this.settings
100111
this.settings = newSettings
101112
await this.cacheSettings()
102-
callback()
113+
114+
this.emit("settings-updated", {
115+
settings: this.settings,
116+
previousSettings,
117+
})
103118
}
104119

105120
return true
@@ -131,6 +146,7 @@ export class CloudSettingsService implements SettingsService {
131146
}
132147

133148
public dispose(): void {
149+
this.removeAllListeners()
134150
this.timer.stop()
135151
}
136152
}

0 commit comments

Comments
 (0)