Skip to content

Commit 254ca38

Browse files
authored
fix(vscode): passing any lineage error through (#4786)
1 parent 118e7e9 commit 254ca38

5 files changed

Lines changed: 95 additions & 14 deletions

File tree

vscode/extension/src/lsp/custom.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface RenderModelRequest {
1414
textDocumentUri: string
1515
}
1616

17-
interface RenderModelResponse {
17+
interface RenderModelResponse extends BaseResponse {
1818
models: RenderModelEntry[]
1919
}
2020

@@ -25,7 +25,6 @@ export interface RenderModelEntry {
2525
rendered_query: string
2626
}
2727

28-
// @eslint-disable-next-line @typescript-eslint/consistent-type-definition
2928
export type CustomLSPMethods =
3029
| AllModelsMethod
3130
| AbstractAPICall
@@ -40,7 +39,7 @@ interface AllModelsRequest {
4039
}
4140
}
4241

43-
interface AllModelsResponse {
42+
interface AllModelsResponse extends BaseResponse {
4443
models: string[]
4544
keywords: string[]
4645
}
@@ -55,9 +54,11 @@ export interface AbstractAPICallRequest {
5554
export interface AbstractAPICall {
5655
method: 'sqlmesh/api'
5756
request: AbstractAPICallRequest
58-
response: object
57+
response: AbstractAPICallResponse
5958
}
6059

60+
type AbstractAPICallResponse = object & BaseResponse
61+
6162
export interface AllModelsForRenderMethod {
6263
method: 'sqlmesh/all_models_for_render'
6364
request: AllModelsForRenderRequest
@@ -67,7 +68,7 @@ export interface AllModelsForRenderMethod {
6768
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
6869
interface AllModelsForRenderRequest {}
6970

70-
interface AllModelsForRenderResponse {
71+
interface AllModelsForRenderResponse extends BaseResponse {
7172
models: ModelForRendering[]
7273
}
7374

@@ -87,7 +88,7 @@ export interface SupportedMethodsMethod {
8788
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
8889
interface SupportedMethodsRequest {}
8990

90-
interface SupportedMethodsResponse {
91+
interface SupportedMethodsResponse extends BaseResponse {
9192
methods: CustomMethod[]
9293
}
9394

@@ -105,4 +106,8 @@ export interface FormatProjectMethod {
105106
interface FormatProjectRequest {}
106107

107108
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
108-
interface FormatProjectResponse {}
109+
interface FormatProjectResponse extends BaseResponse {}
110+
111+
interface BaseResponse {
112+
response_error?: string
113+
}

vscode/extension/src/lsp/lsp.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ export class LSPClient implements Disposable {
256256

257257
try {
258258
const result = await this.client.sendRequest<Response>(method, request)
259+
if (result.response_error) {
260+
return err(result.response_error)
261+
}
259262
return ok(result)
260263
} catch (error) {
261264
traceError(

vscode/extension/src/webviews/lineagePanel.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from 'vscode'
1111
import { getWorkspaceFolders } from '../utilities/common/vscodeapi'
1212
import { LSPClient } from '../lsp/lsp'
13+
import { isErr } from '@bus/result'
1314

1415
export class LineagePanel implements WebviewViewProvider, Disposable {
1516
public static readonly viewType = 'sqlmesh.lineage'
@@ -97,12 +98,40 @@ export class LineagePanel implements WebviewViewProvider, Disposable {
9798
'sqlmesh/api',
9899
payload.params,
99100
)
100-
const responseCallback: CallbackEvent = {
101-
key: 'rpcResponse',
102-
payload: {
103-
requestId,
104-
result: response,
105-
},
101+
let responseCallback: CallbackEvent
102+
if (isErr(response)) {
103+
let errorMessage: string
104+
switch (response.error.type) {
105+
case 'generic':
106+
errorMessage = response.error.message
107+
break
108+
case 'invalid_state':
109+
errorMessage = `Invalid state: ${response.error.message}`
110+
break
111+
case 'sqlmesh_outdated':
112+
errorMessage = `SQLMesh version issue: ${response.error.message}`
113+
break
114+
default:
115+
errorMessage = 'Unknown error'
116+
}
117+
responseCallback = {
118+
key: 'rpcResponse',
119+
payload: {
120+
requestId,
121+
result: {
122+
ok: false,
123+
error: errorMessage,
124+
},
125+
},
126+
}
127+
} else {
128+
responseCallback = {
129+
key: 'rpcResponse',
130+
payload: {
131+
requestId,
132+
result: response,
133+
},
134+
}
106135
}
107136
await webviewView.webview.postMessage(responseCallback)
108137
break

vscode/extension/tests/broken_project.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,39 @@ test('bad project, double model, then fixed', async ({}) => {
9292
await fs.remove(tempDir)
9393
}
9494
})
95+
96+
test('bad project, double model, check lineage', async ({}) => {
97+
const tempDir = await fs.mkdtemp(
98+
path.join(os.tmpdir(), 'vscode-test-tcloud-'),
99+
)
100+
await fs.copy(SUSHI_SOURCE_PATH, tempDir)
101+
102+
// Read the customers.sql file
103+
const customersSql = await fs.readFile(
104+
path.join(tempDir, 'models', 'customers.sql'),
105+
'utf8',
106+
)
107+
108+
// Write the customers.sql file with a double model
109+
await fs.writeFile(
110+
path.join(tempDir, 'models', 'customers_duplicated.sql'),
111+
customersSql,
112+
)
113+
114+
const { window, close } = await startVSCode(tempDir)
115+
try {
116+
await window.waitForSelector('text=models')
117+
118+
// Open the lineage view
119+
await openLineageView(window)
120+
121+
await window.waitForSelector('text=Error creating context')
122+
123+
await window.waitForSelector('text=Error:')
124+
125+
await window.waitForTimeout(1000)
126+
} finally {
127+
await close()
128+
await fs.remove(tempDir)
129+
}
130+
})

vscode/react/src/pages/lineage.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ function Lineage() {
7373
const { on } = useEventBus()
7474
const queryClient = useQueryClient()
7575

76-
const { data: models, isLoading: isLoadingModels } = useApiModels()
76+
const {
77+
data: models,
78+
isLoading: isLoadingModels,
79+
error: modelsError,
80+
} = useApiModels()
7781
const rpc = useRpc()
7882
React.useEffect(() => {
7983
const fetchFirstTimeModelIfNotSet = async (
@@ -143,6 +147,10 @@ function Lineage() {
143147
}
144148
}, [on, queryClient, modelsRecord])
145149

150+
if (modelsError) {
151+
return <div>Error: {modelsError.message}</div>
152+
}
153+
146154
if (
147155
isLoadingModels ||
148156
models === undefined ||

0 commit comments

Comments
 (0)