Repository navigation
Expand file tree
/
Copy pathvectorize-lanes.js
More file actions
92 lines (83 loc) · 2.85 KB
/
Copy pathvectorize-lanes.js
File metadata and controls
92 lines (83 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
'use strict';
/**
* Pure helpers for stage-4 tip/cold drain order and partial-complete flags.
*/
/**
* Order pending shows: tip-queue IDs (enqueued order) → incremental
* (ep=0 ∧ show=1) → cold (both=0) oldest last_ep_sync first.
*
* @param {Array<{id: string, last_ep_sync?: number|null, qdrant_podcast_vectorized?: number|boolean}>} pending
* @param {string[]} tipQueueIdsOrdered oldest enqueued first
* @returns {{ ordered: typeof pending, tipSet: Set<string>, orphanTipIds: string[], tipCount: number, incrementalCount: number, coldCount: number }}
*/
function orderPendingForVectorize(pending, tipQueueIdsOrdered) {
const byId = new Map((pending || []).map((p) => [String(p.id), p]));
const tipSet = new Set();
const tipOrdered = [];
const orphanTipIds = [];
for (const rawId of tipQueueIdsOrdered || []) {
const id = String(rawId);
const pod = byId.get(id);
if (pod) {
tipOrdered.push(pod);
tipSet.add(id);
} else {
orphanTipIds.push(id);
}
}
const incremental = [];
const cold = [];
for (const pod of pending || []) {
const id = String(pod.id);
if (tipSet.has(id)) continue;
if (Number(pod.qdrant_podcast_vectorized) === 1) incremental.push(pod);
else cold.push(pod);
}
cold.sort((a, b) => {
if (a.last_ep_sync == null && b.last_ep_sync != null) return -1;
if (a.last_ep_sync != null && b.last_ep_sync == null) return 1;
return (a.last_ep_sync || 0) - (b.last_ep_sync || 0);
});
return {
ordered: [...tipOrdered, ...incremental, ...cold],
tipSet,
orphanTipIds,
tipCount: tipOrdered.length,
incrementalCount: incremental.length,
coldCount: cold.length,
};
}
/**
* Whether a show may flip qdrant_vectorized=1 and leave the tip queue.
* Budget mid-show or embed failure → incomplete (partial upsert OK, flag stays 0).
*
* @param {{ showFailed: boolean, budgetBroke: boolean, toEmbedCount: number, embeddedCount: number, corruptSkipped: number }}
*/
function showVectorizeComplete({
showFailed,
budgetBroke,
toEmbedCount,
embeddedCount,
corruptSkipped = 0,
}) {
if (showFailed || budgetBroke) return false;
const accounted = embeddedCount + corruptSkipped;
return accounted >= toEmbedCount;
}
/**
* Lane label for metrics: tip queue membership wins, else show-vec done → tip lane.
* @param {{ id: string, qdrant_podcast_vectorized?: number|boolean }} pod
* @param {Set<string>} tipSet
* @returns {'tip'|'cold'}
*/
function laneForShow(pod, tipSet) {
const id = String(pod.id);
if (tipSet && tipSet.has(id)) return 'tip';
if (Number(pod.qdrant_podcast_vectorized) === 1) return 'tip';
return 'cold';
}
module.exports = {
orderPendingForVectorize,
showVectorizeComplete,
laneForShow,
};