Skip to content

Commit 85e123f

Browse files
committed
refactor(desktop): unify sidecar controller interface
1 parent 45cd8d7 commit 85e123f

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { describe, expect, test, vi } from "bun:test"
2+
import { BaseSidecarController } from "./types"
3+
4+
describe("SidecarController Interface", () => {
5+
test("manages sidecar lifecycle state transitions", async () => {
6+
const fetchUrl = vi.fn().mockResolvedValue("http://127.0.0.1:4096")
7+
const stopFn = vi.fn().mockResolvedValue(undefined)
8+
9+
const controller = new BaseSidecarController("local-1", "local", fetchUrl, stopFn)
10+
11+
expect(controller.status).toBe("idle")
12+
13+
const url = await controller.getUrl()
14+
expect(url).toBe("http://127.0.0.1:4096")
15+
expect(controller.status).toBe("ready")
16+
17+
await controller.stop()
18+
expect(stopFn).toHaveBeenCalled()
19+
expect(controller.status).toBe("stopped")
20+
})
21+
22+
test("handles startup failures gracefully", async () => {
23+
const fetchUrl = vi.fn().mockRejectedValue(new Error("Failed to start server"))
24+
const stopFn = vi.fn().mockResolvedValue(undefined)
25+
26+
const controller = new BaseSidecarController("wsl-ubuntu", "wsl", fetchUrl, stopFn)
27+
28+
expect(controller.getUrl()).rejects.toThrow("Failed to start server")
29+
expect(controller.status).toBe("failed")
30+
})
31+
})
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
export type SidecarKind = "local" | "wsl"
2+
export type SidecarStatus = "idle" | "starting" | "ready" | "failed" | "stopped"
3+
4+
export interface SidecarInstance {
5+
readonly id: string
6+
readonly kind: SidecarKind
7+
readonly status: SidecarStatus
8+
getUrl(): Promise<string | null>
9+
stop(): Promise<void>
10+
}
11+
12+
export class BaseSidecarController implements SidecarInstance {
13+
private _status: SidecarStatus = "idle"
14+
15+
constructor(
16+
public readonly id: string,
17+
public readonly kind: SidecarKind,
18+
private fetchUrl: () => Promise<string | null>,
19+
private stopFn: () => Promise<void>,
20+
) {}
21+
22+
get status(): SidecarStatus {
23+
return this._status
24+
}
25+
26+
async getUrl(): Promise<string | null> {
27+
this._status = "starting"
28+
try {
29+
const url = await this.fetchUrl()
30+
this._status = url ? "ready" : "failed"
31+
return url
32+
} catch (err) {
33+
this._status = "failed"
34+
throw err
35+
}
36+
}
37+
38+
async stop(): Promise<void> {
39+
try {
40+
await this.stopFn()
41+
} finally {
42+
this._status = "stopped"
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)