Skip to content

Commit cf35989

Browse files
committed
fix: fix batching mechanism
1 parent c92268a commit cf35989

File tree

4 files changed

+29
-13
lines changed

4 files changed

+29
-13
lines changed

app/app.vue

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ const { data: clusters, refresh, status } = useFetch('/api/clusters/nuxt/nuxt',
99
1010
onMounted(async () => {
1111
if ('startViewTransition' in document) {
12-
document.startViewTransition(() => refresh())
12+
let finishTransition: () => void
13+
const promise = new Promise<void>((resolve) => {
14+
finishTransition = resolve
15+
})
16+
watch(clusters, () => document.startViewTransition(() => promise), { flush: 'pre', once: true })
17+
watch(clusters, () => nextTick(finishTransition), { flush: 'post', once: true })
18+
refresh()
1319
}
1420
})
1521
@@ -152,6 +158,8 @@ async function updateSearch() {}
152158
:datetime="issue.updated_at"
153159
relative
154160
/>
161+
&middot;
162+
{{ Math.floor(issue.avgSimilarity * 100) }}% similar
155163
</span>
156164
<div class="flex flex-row gap-1 items-baseline flex-wrap md:flex-nowrap">
157165
<span

server/api/clusters/[...repo].ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { clusterEmbeddings } from '../../utils/cluster'
22
import { getEmbeddingsForIssue } from '../../utils/embeddings'
3-
import type { Issue } from '../../utils/github'
43

54
const linkedRepos: Record<string, string[]> = {
65
'danielroe/beasties': ['GoogleChromeLabs/critters'],
6+
'nitrojs/nitro': ['unjs/h3', 'unjs/c12', 'unjs/unenv', 'unjs/ofetch'],
77
'nuxt/nuxt': ['vuejs/core', 'vitejs/vite', 'nitrojs/nitro'],
88
}
99

10-
const allowedRepos = ['nuxt/nuxt', 'vuejs/vue', 'vitejs/vite', 'nitrojs/nitro', 'danielroe/beasties']
10+
const allowedRepos = ['nuxt/nuxt', 'vuejs/core', 'vitejs/vite', 'nitrojs/nitro', 'danielroe/beasties', 'unjs/h3', 'unjs/c12', 'unjs/unenv', 'unjs/ofetch']
1111

1212
export default defineCachedEventHandler(async (event) => {
1313
const [owner, repo] = getRouterParam(event, 'repo')?.split('/') || []
@@ -28,27 +28,30 @@ export default defineCachedEventHandler(async (event) => {
2828
}
2929

3030
const repos = [source, ...linkedRepos[source] || []]
31-
const issues = await Promise.all(repos.map(async repo => event.$fetch<Issue[]>(`/api/issues/${repo}`)))
31+
const issues = await Promise.all(repos.map(async repo => $fetch(`/api/issues/${repo}`)))
3232
.then(r => r.flat())
3333

3434
console.log('fetched', issues.length, 'issues')
3535

36+
const backlog = [...issues]
3637
const embeddings: number[][] = []
3738

3839
do {
39-
const batch = issues.splice(0, 100)
40+
const batch = backlog.splice(0, 100)
4041
embeddings.push(...await Promise.all(batch.map(async issue => getEmbeddingsForIssue(event, issue))))
41-
} while (issues.length)
42+
} while (backlog.length)
4243

44+
console.log('generated', embeddings.length, 'embeddings')
4345
const clusters = clusterEmbeddings(issues, embeddings)
46+
console.log('generated', clusters.length, 'clusters')
4447
return clusters.filter((cluster) => {
4548
return cluster.some(issue => issue.repository?.owner?.name === owner && issue.repository?.name === repo)
4649
})
4750
}, {
4851
swr: true,
4952
getKey(event) {
5053
const [owner, repo] = getRouterParam(event, 'repo')?.split('/') || []
51-
return `clusters:${owner}:${repo}`
54+
return `clusters:${owner}:${repo}`.toLowerCase()
5255
},
5356
maxAge: 60 * 60 * 1000,
5457
staleMaxAge: 60 * 60 * 1000,

server/api/issues/[...repo].ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getLabels, type Issue } from '../../utils/github'
55
const labelsToExclude = ['documentation', 'invalid', 'enhancement']
66
const knownBots = new Set(['renovate', 'renovate[bot]'])
77

8-
const allowedRepos = ['nuxt/nuxt', 'vuejs/vue', 'vitejs/vite', 'nitrojs/nitro', 'danielroe/beasties']
8+
const allowedRepos = ['nuxt/nuxt', 'vuejs/core', 'vitejs/vite', 'nitrojs/nitro', 'danielroe/beasties', 'unjs/h3', 'unjs/c12', 'unjs/unenv', 'unjs/ofetch']
99

1010
export default defineCachedEventHandler(async (event) => {
1111
const [owner, repo] = getRouterParam(event, 'repo')?.split('/') || []
@@ -23,7 +23,8 @@ export default defineCachedEventHandler(async (event) => {
2323
})
2424
}
2525

26-
const octokit = new Octokit({ auth: useRuntimeConfig(event).github.token })
26+
const options = owner !== 'unjs' ? { auth: useRuntimeConfig(event).github.token } : {}
27+
const octokit = new Octokit(options)
2728

2829
// TODO: date/state filters?
2930
const issues = await octokit.paginate(octokit.issues.listForRepo, {
@@ -42,7 +43,7 @@ export default defineCachedEventHandler(async (event) => {
4243
swr: true,
4344
getKey(event) {
4445
const [owner, repo] = getRouterParam(event, 'repo')?.split('/') || []
45-
return `issues:${owner}:${repo}`
46+
return `issues:${owner}:${repo}`.toLowerCase()
4647
},
4748
maxAge: 60 * 60 * 1000,
4849
staleMaxAge: 60 * 60 * 1000,

server/utils/cluster.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,20 @@ export function clusterEmbeddings(issues: Issue[], embeddings: number[][]) {
2626

2727
for (const cluster in clusteredIssues) {
2828
const chunk = clusteredIssues[cluster]!
29-
const sortedChunk = chunk.map((issue) => {
29+
let sortedChunk = chunk.map((issue) => {
3030
let totalSimilarity = 0
3131
for (const other of chunk) {
3232
if (issue === other) {
3333
continue
3434
}
3535
totalSimilarity += similarity.cosine(embeddings[issues.indexOf(issue)], embeddings[issues.indexOf(other)])
3636
}
37-
return { ...issue, avgSimilarity: totalSimilarity / (chunk.length - 1) }
38-
}).filter(i => i.avgSimilarity > 0.75).sort((a, b) => b.avgSimilarity - a.avgSimilarity)
37+
return { ...issue, avgSimilarity: Math.floor(100 * totalSimilarity / (chunk.length - 1)) / 100 }
38+
})
39+
40+
const similarityThreshold = 0.75
41+
42+
sortedChunk = sortedChunk.filter(i => i.avgSimilarity >= similarityThreshold).sort((a, b) => b.avgSimilarity - a.avgSimilarity)
3943

4044
if (sortedChunk.length > 1) {
4145
sortedClusters.push(sortedChunk)

0 commit comments

Comments
 (0)