GeminiBot
commited on
Commit
·
5a97b06
1
Parent(s):
5ceef9b
Implement concurrency queue (max 5) to protect IP from DDG burst bans
Browse files- src/duckai.ts +33 -4
src/duckai.ts
CHANGED
|
@@ -4,9 +4,36 @@ import { Buffer } from "node:buffer";
|
|
| 4 |
import UserAgent from "user-agents";
|
| 5 |
|
| 6 |
let activeRequests = 0;
|
|
|
|
|
|
|
| 7 |
|
| 8 |
export class DuckAI {
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
private async solveChallenge(vqdHash: string, reqId: string): Promise<string> {
|
| 11 |
const start = Date.now();
|
| 12 |
const memBefore = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
@@ -79,10 +106,12 @@ export class DuckAI {
|
|
| 79 |
|
| 80 |
async chat(request: any): Promise<string> {
|
| 81 |
const reqId = Math.random().toString(36).substring(7).toUpperCase();
|
| 82 |
-
activeRequests++;
|
| 83 |
-
const startTime = Date.now();
|
| 84 |
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
// Добавляем Jitter (случайную задержку 0-500мс), чтобы не долбить DDG пачкой
|
| 88 |
await new Promise(r => setTimeout(resolve => r(resolve), Math.random() * 500));
|
|
@@ -156,7 +185,7 @@ export class DuckAI {
|
|
| 156 |
console.error(`[${reqId}] [Chat] FAILED: ${error.message}`);
|
| 157 |
throw error;
|
| 158 |
} finally {
|
| 159 |
-
|
| 160 |
}
|
| 161 |
}
|
| 162 |
|
|
|
|
| 4 |
import UserAgent from "user-agents";
|
| 5 |
|
| 6 |
let activeRequests = 0;
|
| 7 |
+
const MAX_CONCURRENT_CHATS = 5; // Максимум 5 одновременных запросов к DDG
|
| 8 |
+
const requestQueue: (() => void)[] = [];
|
| 9 |
|
| 10 |
export class DuckAI {
|
| 11 |
|
| 12 |
+
// Метод для ожидания своей очереди
|
| 13 |
+
private async acquireSlot(reqId: string): Promise<void> {
|
| 14 |
+
if (activeRequests < MAX_CONCURRENT_CHATS) {
|
| 15 |
+
activeRequests++;
|
| 16 |
+
return;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
console.log(`[${reqId}] [Queue] Space busy (${activeRequests} active). Waiting for slot...`);
|
| 20 |
+
return new Promise((resolve) => {
|
| 21 |
+
requestQueue.push(() => {
|
| 22 |
+
activeRequests++;
|
| 23 |
+
resolve();
|
| 24 |
+
});
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
// Освобождение слота
|
| 29 |
+
private releaseSlot() {
|
| 30 |
+
activeRequests--;
|
| 31 |
+
if (requestQueue.length > 0) {
|
| 32 |
+
const next = requestQueue.shift();
|
| 33 |
+
if (next) next();
|
| 34 |
+
}
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
private async solveChallenge(vqdHash: string, reqId: string): Promise<string> {
|
| 38 |
const start = Date.now();
|
| 39 |
const memBefore = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
|
|
| 106 |
|
| 107 |
async chat(request: any): Promise<string> {
|
| 108 |
const reqId = Math.random().toString(36).substring(7).toUpperCase();
|
|
|
|
|
|
|
| 109 |
|
| 110 |
+
// Ждем свободный слот (максимум 5 параллельно)
|
| 111 |
+
await this.acquireSlot(reqId);
|
| 112 |
+
|
| 113 |
+
const startTime = Date.now();
|
| 114 |
+
console.log(`[${reqId}] [Chat] STARTING (Active: ${activeRequests}, Queued: ${requestQueue.length})`);
|
| 115 |
|
| 116 |
// Добавляем Jitter (случайную задержку 0-500мс), чтобы не долбить DDG пачкой
|
| 117 |
await new Promise(r => setTimeout(resolve => r(resolve), Math.random() * 500));
|
|
|
|
| 185 |
console.error(`[${reqId}] [Chat] FAILED: ${error.message}`);
|
| 186 |
throw error;
|
| 187 |
} finally {
|
| 188 |
+
this.releaseSlot();
|
| 189 |
}
|
| 190 |
}
|
| 191 |
|