@zodic/shared 0.0.186 → 0.0.188
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/durable/ConceptNameDO.ts +12 -10
- package/app/services/ConceptService.ts +37 -32
- package/package.json +1 -1
|
@@ -88,23 +88,25 @@ export class ConceptNameDO {
|
|
|
88
88
|
await this.loadCount();
|
|
89
89
|
await this.loadTimestamps();
|
|
90
90
|
await this.loadLastIndex(); // ✅ Ensure latest lastIndex is fetched
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
const now = Date.now();
|
|
93
93
|
const oneMinuteAgo = now - 60 * 1000;
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
const recentTimestamps = this.timestamps.filter((ts) => ts >= oneMinuteAgo);
|
|
96
96
|
const ratePerMinute = recentTimestamps.length;
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
|
|
98
|
+
// 🔥 Only count the `en-us` names to reflect progress properly
|
|
99
|
+
const enUsCount = this.names['en-us'].length;
|
|
100
|
+
|
|
101
|
+
const remainingNames = ConceptNameDO.TOTAL_NAMES - enUsCount;
|
|
99
102
|
const estimatedTimeMinutes =
|
|
100
103
|
ratePerMinute > 0 ? Math.round(remainingNames / ratePerMinute) : 'N/A';
|
|
101
|
-
|
|
104
|
+
|
|
102
105
|
return {
|
|
103
|
-
count: this.count,
|
|
104
|
-
total: ConceptNameDO.TOTAL_NAMES,
|
|
105
|
-
lastIndex: this.lastIndex,
|
|
106
|
-
progress:
|
|
107
|
-
((this.count / ConceptNameDO.TOTAL_NAMES) * 100).toFixed(2) + '%',
|
|
106
|
+
count: this.count, // ✅ Keep full count (en-us + pt-br)
|
|
107
|
+
total: ConceptNameDO.TOTAL_NAMES, // ✅ Base progress on 1728
|
|
108
|
+
lastIndex: this.lastIndex,
|
|
109
|
+
progress: ((enUsCount / ConceptNameDO.TOTAL_NAMES) * 100).toFixed(2) + '%', // ✅ Use only en-us count
|
|
108
110
|
ratePerMinute,
|
|
109
111
|
estimatedTimeMinutes,
|
|
110
112
|
};
|
|
@@ -39,9 +39,39 @@ export class ConceptService {
|
|
|
39
39
|
const id = this.context.env.CONCEPT_NAMES_DO.idFromName(conceptSlug);
|
|
40
40
|
const stub = this.context.env.CONCEPT_NAMES_DO.get(id);
|
|
41
41
|
|
|
42
|
+
console.log(`📡 Fetching existing KV data for ${conceptSlug}...`);
|
|
43
|
+
const existingEN = await this.getKVConcept(kvKeyEN);
|
|
44
|
+
const existingPT = await this.getKVConcept(kvKeyPT);
|
|
45
|
+
|
|
46
|
+
// ✅ IMMEDIATE SKIP if already exists and override is false
|
|
47
|
+
if (!override && existingEN.name && existingPT.name) {
|
|
48
|
+
console.log(`⚡ Basic info already exists for ${conceptSlug}, skipping.`);
|
|
49
|
+
|
|
50
|
+
// ✅ **Backfill Durable Object** to register the names
|
|
51
|
+
console.log(`📡 Backfilling Durable Object for ${conceptSlug}...`);
|
|
52
|
+
try {
|
|
53
|
+
await Promise.all([
|
|
54
|
+
stub.fetch(`https://internal/add-name`, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
body: JSON.stringify({ language: 'en-us', name: existingEN.name }),
|
|
57
|
+
headers: { 'Content-Type': 'application/json' },
|
|
58
|
+
}),
|
|
59
|
+
stub.fetch(`https://internal/add-name`, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
body: JSON.stringify({ language: 'pt-br', name: existingPT.name }),
|
|
62
|
+
headers: { 'Content-Type': 'application/json' },
|
|
63
|
+
}),
|
|
64
|
+
]);
|
|
65
|
+
console.log(`✅ Successfully backfilled Durable Object for ${conceptSlug}`);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error(`❌ Error backfilling Durable Object:`, error);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return; // ✅ Exit early
|
|
71
|
+
}
|
|
72
|
+
|
|
42
73
|
let attempts = 0;
|
|
43
74
|
const maxAttempts = 3;
|
|
44
|
-
|
|
45
75
|
while (attempts < maxAttempts) {
|
|
46
76
|
let phase = 'generation';
|
|
47
77
|
try {
|
|
@@ -63,37 +93,6 @@ export class ConceptService {
|
|
|
63
93
|
console.log(`❌ Error fetching names from DO for ${conceptSlug}: ${await response.text()}`);
|
|
64
94
|
}
|
|
65
95
|
|
|
66
|
-
// ✅ Fetch existing KV data to backfill Durable Object if necessary
|
|
67
|
-
console.log(`📡 Fetching existing KV data for ${conceptSlug}...`);
|
|
68
|
-
const existingEN = await this.getKVConcept(kvKeyEN);
|
|
69
|
-
const existingPT = await this.getKVConcept(kvKeyPT);
|
|
70
|
-
|
|
71
|
-
console.log(`📝 Existing EN name: ${existingEN.name || 'None'}, PT name: ${existingPT.name || 'None'}`);
|
|
72
|
-
|
|
73
|
-
// 🔥 If names exist in KV but not in DO, add them
|
|
74
|
-
if (existingEN.name && !allNamesEN.includes(existingEN.name)) {
|
|
75
|
-
console.log(`⚡ Backfilling existing EN name to DO: ${existingEN.name}`);
|
|
76
|
-
await stub.fetch(`https://internal/add-name`, {
|
|
77
|
-
method: 'POST',
|
|
78
|
-
body: JSON.stringify({ language: 'en-us', name: existingEN.name }),
|
|
79
|
-
headers: { 'Content-Type': 'application/json' },
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
if (existingPT.name && !allNamesPT.includes(existingPT.name)) {
|
|
83
|
-
console.log(`⚡ Backfilling existing PT name to DO: ${existingPT.name}`);
|
|
84
|
-
await stub.fetch(`https://internal/add-name`, {
|
|
85
|
-
method: 'POST',
|
|
86
|
-
body: JSON.stringify({ language: 'pt-br', name: existingPT.name }),
|
|
87
|
-
headers: { 'Content-Type': 'application/json' },
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ✅ Skip generation if basic info already exists and override is false
|
|
92
|
-
if (!override && existingEN.name && existingPT.name) {
|
|
93
|
-
console.log(`⚡ Basic info already exists for ${conceptSlug}, skipping.`);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
96
|
console.log(`✏️ Generating new name...`);
|
|
98
97
|
const recentNamesEN = allNamesEN.slice(-60);
|
|
99
98
|
const messages = this.context
|
|
@@ -159,6 +158,12 @@ export class ConceptService {
|
|
|
159
158
|
await kvStore.put(kvKeyPT, JSON.stringify(existingPT));
|
|
160
159
|
|
|
161
160
|
console.log(`✅ Stored basic info for ${conceptSlug}, combination: ${combinationString}.`);
|
|
161
|
+
|
|
162
|
+
// ✅ **Throttling for next request**
|
|
163
|
+
const delayMs = Math.floor(Math.random() * (500 - 200 + 1)) + 200; // 🔥 Random delay between 200-500ms
|
|
164
|
+
console.log(`⏳ Waiting ${delayMs}ms before processing next missing entry...`);
|
|
165
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
166
|
+
|
|
162
167
|
return;
|
|
163
168
|
} catch (error) {
|
|
164
169
|
console.error(`❌ Attempt ${attempts} failed at phase: ${phase}`, (error as Error).message);
|