Skip to content

Commit 8cc28e2

Browse files
committed
WIP
1 parent f774e1c commit 8cc28e2

File tree

2 files changed

+349
-0
lines changed

2 files changed

+349
-0
lines changed

apps/workers/src/workers/worker-definitions/eventsWorker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const eventHandlersJobMappings = {
5454
enqueueShadowTestChallengerHandler: jobs.enqueueShadowTestChallengerHandler,
5555
notifyClientOfEvaluationV2AlignmentUpdated:
5656
jobs.notifyClientOfEvaluationV2AlignmentUpdated,
57+
unassignIssuesOnDocumentsDeleted: jobs.unassignIssuesOnDocumentsDeleted,
5758
}
5859

5960
export function startEventsWorker() {
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
import { and, eq, inArray } from 'drizzle-orm'
2+
import { describe, expect, it } from 'vitest'
3+
import { database } from '../../client'
4+
import { issueEvaluationResults } from '../../schema/models/issueEvaluationResults'
5+
import { issueHistograms } from '../../schema/models/issueHistograms'
6+
import { issues } from '../../schema/models/issues'
7+
import { createEvaluationResultV2 } from '../../tests/factories/evaluationResultsV2'
8+
import { createEvaluationV2 } from '../../tests/factories/evaluationsV2'
9+
import { createIssueEvaluationResult } from '../../tests/factories/issueEvaluationResults'
10+
import { createIssue } from '../../tests/factories/issues'
11+
import { createProject } from '../../tests/factories/projects'
12+
import { createSpan } from '../../tests/factories/spans'
13+
import { createWorkspace } from '../../tests/factories/workspaces'
14+
import { DocumentsDeletedEvent } from '../events'
15+
import { unassignIssuesOnDocumentsDeleted } from './unassignIssuesOnDocumentsDeleted'
16+
17+
describe('unassignIssuesOnDocumentsDeleted', () => {
18+
it('does nothing when documentUuids is empty', async () => {
19+
const { workspace } = await createWorkspace({ features: ['issues'] })
20+
const { project } = await createProject({ workspace })
21+
22+
const event: DocumentsDeletedEvent = {
23+
type: 'documentsDeleted',
24+
data: {
25+
workspaceId: workspace.id,
26+
projectId: project.id,
27+
commitUuid: 'some-uuid',
28+
documentUuids: [],
29+
softDeletedDocumentUuids: [],
30+
hardDeletedDocumentUuids: [],
31+
},
32+
}
33+
34+
await expect(
35+
unassignIssuesOnDocumentsDeleted({ data: event }),
36+
).resolves.not.toThrow()
37+
})
38+
39+
it('does nothing when commit is not found', async () => {
40+
const { workspace } = await createWorkspace({ features: ['issues'] })
41+
const { project, documents } = await createProject({
42+
workspace,
43+
documents: { 'test-doc': 'test content' },
44+
})
45+
const document = documents[0]!
46+
47+
const event: DocumentsDeletedEvent = {
48+
type: 'documentsDeleted',
49+
data: {
50+
workspaceId: workspace.id,
51+
projectId: project.id,
52+
commitUuid: 'non-existent-uuid',
53+
documentUuids: [document.documentUuid],
54+
softDeletedDocumentUuids: [],
55+
hardDeletedDocumentUuids: [],
56+
},
57+
}
58+
59+
await expect(
60+
unassignIssuesOnDocumentsDeleted({ data: event }),
61+
).resolves.not.toThrow()
62+
})
63+
64+
it('unassigns issueEvaluationResults for deleted documents in the commit', async () => {
65+
const { workspace } = await createWorkspace({ features: ['issues'] })
66+
const { project, documents, commit } = await createProject({
67+
workspace,
68+
documents: { 'test-doc': 'test content' },
69+
})
70+
const document = documents[0]!
71+
72+
const { issue } = await createIssue({
73+
workspace,
74+
project,
75+
document,
76+
})
77+
78+
const evaluation = await createEvaluationV2({
79+
workspace,
80+
document,
81+
commit,
82+
})
83+
84+
const span = await createSpan({
85+
workspaceId: workspace.id,
86+
documentUuid: document.documentUuid,
87+
commitUuid: commit.uuid,
88+
projectId: project.id,
89+
})
90+
91+
const evalResult = await createEvaluationResultV2({
92+
workspace,
93+
evaluation,
94+
span,
95+
commit,
96+
})
97+
98+
await createIssueEvaluationResult({
99+
workspace,
100+
issue,
101+
evaluationResult: evalResult,
102+
})
103+
104+
const beforeDelete = await database
105+
.select()
106+
.from(issueEvaluationResults)
107+
.where(eq(issueEvaluationResults.issueId, issue.id))
108+
expect(beforeDelete).toHaveLength(1)
109+
110+
const event: DocumentsDeletedEvent = {
111+
type: 'documentsDeleted',
112+
data: {
113+
workspaceId: workspace.id,
114+
projectId: project.id,
115+
commitUuid: commit.uuid,
116+
documentUuids: [document.documentUuid],
117+
softDeletedDocumentUuids: [],
118+
hardDeletedDocumentUuids: [document.documentUuid],
119+
},
120+
}
121+
122+
await unassignIssuesOnDocumentsDeleted({ data: event })
123+
124+
const afterDelete = await database
125+
.select()
126+
.from(issueEvaluationResults)
127+
.where(eq(issueEvaluationResults.issueId, issue.id))
128+
expect(afterDelete).toHaveLength(0)
129+
})
130+
131+
it('deletes histograms for issues in the commit where documents are deleted', async () => {
132+
const { workspace } = await createWorkspace({ features: ['issues'] })
133+
const { project, documents, commit } = await createProject({
134+
workspace,
135+
documents: { 'test-doc': 'test content' },
136+
})
137+
const document = documents[0]!
138+
139+
const histogramData = {
140+
commitId: commit.id,
141+
date: new Date(),
142+
count: 5,
143+
}
144+
145+
const { issue, histograms } = await createIssue({
146+
workspace,
147+
project,
148+
document,
149+
histograms: [histogramData],
150+
})
151+
152+
expect(histograms).toHaveLength(1)
153+
154+
const beforeDelete = await database
155+
.select()
156+
.from(issueHistograms)
157+
.where(
158+
and(
159+
eq(issueHistograms.issueId, issue.id),
160+
eq(issueHistograms.commitId, commit.id),
161+
),
162+
)
163+
expect(beforeDelete).toHaveLength(1)
164+
165+
const event: DocumentsDeletedEvent = {
166+
type: 'documentsDeleted',
167+
data: {
168+
workspaceId: workspace.id,
169+
projectId: project.id,
170+
commitUuid: commit.uuid,
171+
documentUuids: [document.documentUuid],
172+
softDeletedDocumentUuids: [],
173+
hardDeletedDocumentUuids: [document.documentUuid],
174+
},
175+
}
176+
177+
await unassignIssuesOnDocumentsDeleted({ data: event })
178+
179+
const afterDelete = await database
180+
.select()
181+
.from(issueHistograms)
182+
.where(
183+
and(
184+
eq(issueHistograms.issueId, issue.id),
185+
eq(issueHistograms.commitId, commit.id),
186+
),
187+
)
188+
expect(afterDelete).toHaveLength(0)
189+
})
190+
191+
it('updates escalating status for affected issues', async () => {
192+
const { workspace } = await createWorkspace({ features: ['issues'] })
193+
const { project, documents, commit } = await createProject({
194+
workspace,
195+
documents: { 'test-doc': 'test content' },
196+
})
197+
const document = documents[0]!
198+
199+
const histogramData = {
200+
commitId: commit.id,
201+
date: new Date(),
202+
count: 10,
203+
}
204+
205+
const { issue } = await createIssue({
206+
workspace,
207+
project,
208+
document,
209+
histograms: [histogramData],
210+
escalatingAt: new Date(),
211+
})
212+
213+
expect(issue.escalatingAt).not.toBeNull()
214+
215+
const event: DocumentsDeletedEvent = {
216+
type: 'documentsDeleted',
217+
data: {
218+
workspaceId: workspace.id,
219+
projectId: project.id,
220+
commitUuid: commit.uuid,
221+
documentUuids: [document.documentUuid],
222+
softDeletedDocumentUuids: [],
223+
hardDeletedDocumentUuids: [document.documentUuid],
224+
},
225+
}
226+
227+
await unassignIssuesOnDocumentsDeleted({ data: event })
228+
229+
const updatedIssue = await database
230+
.select()
231+
.from(issues)
232+
.where(eq(issues.id, issue.id))
233+
.then((r) => r[0])
234+
235+
expect(updatedIssue?.escalatingAt).toBeNull()
236+
})
237+
238+
it('handles multiple documents and issues', async () => {
239+
const { workspace } = await createWorkspace({ features: ['issues'] })
240+
const { project, documents, commit } = await createProject({
241+
workspace,
242+
documents: {
243+
'doc-1': 'content 1',
244+
'doc-2': 'content 2',
245+
},
246+
})
247+
const doc1 = documents[0]!
248+
const doc2 = documents[1]!
249+
250+
const { issue: issue1 } = await createIssue({
251+
workspace,
252+
project,
253+
document: doc1,
254+
histograms: [{ commitId: commit.id, date: new Date(), count: 3 }],
255+
})
256+
257+
const { issue: issue2 } = await createIssue({
258+
workspace,
259+
project,
260+
document: doc2,
261+
histograms: [{ commitId: commit.id, date: new Date(), count: 5 }],
262+
})
263+
264+
const beforeDelete = await database
265+
.select()
266+
.from(issueHistograms)
267+
.where(
268+
and(
269+
inArray(issueHistograms.issueId, [issue1.id, issue2.id]),
270+
eq(issueHistograms.commitId, commit.id),
271+
),
272+
)
273+
expect(beforeDelete).toHaveLength(2)
274+
275+
const event: DocumentsDeletedEvent = {
276+
type: 'documentsDeleted',
277+
data: {
278+
workspaceId: workspace.id,
279+
projectId: project.id,
280+
commitUuid: commit.uuid,
281+
documentUuids: [doc1.documentUuid, doc2.documentUuid],
282+
softDeletedDocumentUuids: [],
283+
hardDeletedDocumentUuids: [doc1.documentUuid, doc2.documentUuid],
284+
},
285+
}
286+
287+
await unassignIssuesOnDocumentsDeleted({ data: event })
288+
289+
const afterDelete = await database
290+
.select()
291+
.from(issueHistograms)
292+
.where(
293+
and(
294+
inArray(issueHistograms.issueId, [issue1.id, issue2.id]),
295+
eq(issueHistograms.commitId, commit.id),
296+
),
297+
)
298+
expect(afterDelete).toHaveLength(0)
299+
})
300+
301+
it('only deletes histograms for the specific commit', async () => {
302+
const { workspace } = await createWorkspace({ features: ['issues'] })
303+
const { project, documents, commit: commit1 } = await createProject({
304+
workspace,
305+
documents: { 'test-doc': 'test content' },
306+
})
307+
const document = documents[0]!
308+
309+
const { commit: commit2 } = await createProject({
310+
workspace,
311+
documents: { 'other-doc': 'other content' },
312+
})
313+
314+
const { issue, histograms } = await createIssue({
315+
workspace,
316+
project,
317+
document,
318+
histograms: [
319+
{ commitId: commit1.id, date: new Date(), count: 5 },
320+
{ commitId: commit2.id, date: new Date(), count: 3 },
321+
],
322+
})
323+
324+
expect(histograms).toHaveLength(2)
325+
326+
const event: DocumentsDeletedEvent = {
327+
type: 'documentsDeleted',
328+
data: {
329+
workspaceId: workspace.id,
330+
projectId: project.id,
331+
commitUuid: commit1.uuid,
332+
documentUuids: [document.documentUuid],
333+
softDeletedDocumentUuids: [],
334+
hardDeletedDocumentUuids: [document.documentUuid],
335+
},
336+
}
337+
338+
await unassignIssuesOnDocumentsDeleted({ data: event })
339+
340+
const remainingHistograms = await database
341+
.select()
342+
.from(issueHistograms)
343+
.where(eq(issueHistograms.issueId, issue.id))
344+
345+
expect(remainingHistograms).toHaveLength(1)
346+
expect(remainingHistograms[0]!.commitId).toBe(commit2.id)
347+
})
348+
})

0 commit comments

Comments
 (0)