perf: hapus semua cooldown/backoff delay — retry tanpa bottleneck
Semua retry sekarang instant (retries=0, minTimeout=0, maxTimeout=0): - retry.ts (kedua) — default minTimeout/maxTimeout 0, factor 1 - config.ts (kedua) — DECODER_COOLDOWN_MS=0, AI_ANALYSIS_ERROR_COOLDOWN_MS=0 - llmModerationClient.ts (kedua) — retries 0 tanpa delay - aiAnalyzer.ts (kedua) — retries 0, AI_ANALYSIS_ERROR_COOLDOWN jadi 0 - indonesianTextNormalizer.ts (kedua) — semua rate limit cooldown 0 - recorder.ts (kedua), teleUpload (3 files), uploader (2 files) — retry instant - attachmentUploader (kedua) — retries 0 - syncRoutes.ts — BACKLOG_SYNC_COOLDOWN 0 20 files changed. Semua cooldown bottleneck dihapus. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
62d7d19b53
commit
64643bb066
@@ -41,15 +41,17 @@ function getModerationBroadcaster(): ModerationBroadcaster | undefined {
|
|||||||
function scheduleAutoDelete(row: MessageRecord): void {
|
function scheduleAutoDelete(row: MessageRecord): void {
|
||||||
if (row.ai_status !== "flagged" && row.ai_status !== "warn") return;
|
if (row.ai_status !== "flagged" && row.ai_status !== "warn") return;
|
||||||
const run = () => {
|
const run = () => {
|
||||||
attemptAutoDeleteFlaggedMessage(moderationClient, row).catch((error: unknown) => {
|
attemptAutoDeleteFlaggedMessage(moderationClient, row).catch(
|
||||||
logger.error(
|
(error: unknown) => {
|
||||||
{
|
logger.error(
|
||||||
messageId: row.id,
|
{
|
||||||
error: error instanceof Error ? error.message : String(error),
|
messageId: row.id,
|
||||||
},
|
error: error instanceof Error ? error.message : String(error),
|
||||||
"Unexpected auto-delete error",
|
},
|
||||||
);
|
"Unexpected auto-delete error",
|
||||||
});
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (config.AUTO_DELETE_FLAGGED_DELAY_MS > 0) {
|
if (config.AUTO_DELETE_FLAGGED_DELAY_MS > 0) {
|
||||||
@@ -349,9 +351,9 @@ async function processIndividualFallback(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries: 2,
|
retries: 0,
|
||||||
minTimeout: 2000,
|
minTimeout: 0,
|
||||||
maxTimeout: 15000,
|
maxTimeout: 0,
|
||||||
logger,
|
logger,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ const BADWORD_CACHE_TTL_MS = 10 * 60 * 1000;
|
|||||||
*/
|
*/
|
||||||
const DB_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
const DB_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||||
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 30_000;
|
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||||
const GROQ_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
const GROQ_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||||
|
|
||||||
interface BadwordCacheEntry {
|
interface BadwordCacheEntry {
|
||||||
value: string[];
|
value: string[];
|
||||||
@@ -275,9 +275,9 @@ async function callPrimaryAiModeration(text: string): Promise<string[]> {
|
|||||||
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming);
|
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries: 1,
|
retries: 0,
|
||||||
minTimeout: 500,
|
minTimeout: 0,
|
||||||
maxTimeout: 2000,
|
maxTimeout: 0,
|
||||||
factor: 2,
|
factor: 2,
|
||||||
logger: log,
|
logger: log,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -748,9 +748,7 @@ async function callModerationLLM(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries: 3,
|
retries: 0,
|
||||||
minTimeout: 1000,
|
|
||||||
maxTimeout: 10000,
|
|
||||||
logger: log,
|
logger: log,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export async function uploadAttachmentToTele(
|
|||||||
contentType,
|
contentType,
|
||||||
uploadUrl: config.TELE_UPLOAD_URL,
|
uploadUrl: config.TELE_UPLOAD_URL,
|
||||||
timeoutMs: config.ATTACHMENT_UPLOAD_TIMEOUT_MS,
|
timeoutMs: config.ATTACHMENT_UPLOAD_TIMEOUT_MS,
|
||||||
retries: config.ATTACHMENT_RETRY_ATTEMPTS,
|
retries: 0,
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ export async function uploadToTele(input: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries,
|
retries,
|
||||||
minTimeout: 1000,
|
minTimeout: 0,
|
||||||
maxTimeout: 5000,
|
maxTimeout: 0,
|
||||||
logger,
|
logger,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -92,9 +92,9 @@ export async function startRecording(
|
|||||||
config.VOICE_CONNECTION_TIMEOUT_MS,
|
config.VOICE_CONNECTION_TIMEOUT_MS,
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
retries: 3,
|
retries: 0,
|
||||||
minTimeout: 1000,
|
minTimeout: 0,
|
||||||
maxTimeout: 5000,
|
maxTimeout: 0,
|
||||||
logger,
|
logger,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export async function uploadRecordingSegment(input: {
|
|||||||
filename: fileName,
|
filename: fileName,
|
||||||
contentType: "audio/ogg",
|
contentType: "audio/ogg",
|
||||||
uploadUrl: config.TELE_UPLOAD_URL,
|
uploadUrl: config.TELE_UPLOAD_URL,
|
||||||
retries: 3,
|
retries: 0,
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
const downloadUrl = uploadResult.url;
|
const downloadUrl = uploadResult.url;
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ export async function uploadToTele(input: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries,
|
retries,
|
||||||
minTimeout: 1000,
|
minTimeout: 0,
|
||||||
maxTimeout: 5000,
|
maxTimeout: 0,
|
||||||
logger,
|
logger,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const configSchema = z
|
|||||||
RECORDINGS_DIR: z.string().default("./recordings"),
|
RECORDINGS_DIR: z.string().default("./recordings"),
|
||||||
RECORDING_SEGMENT_MS: z.coerce.number().positive().default(5000),
|
RECORDING_SEGMENT_MS: z.coerce.number().positive().default(5000),
|
||||||
DECODER_ROTATE_MS: z.coerce.number().positive().default(5000),
|
DECODER_ROTATE_MS: z.coerce.number().positive().default(5000),
|
||||||
DECODER_COOLDOWN_MS: z.coerce.number().positive().default(30000),
|
DECODER_COOLDOWN_MS: z.coerce.number().positive().default(0),
|
||||||
WEBSERVER_PORT: z.coerce.number().positive().default(3000),
|
WEBSERVER_PORT: z.coerce.number().positive().default(3000),
|
||||||
VOICE_CONNECTION_TIMEOUT_MS: z.coerce.number().positive().default(15000),
|
VOICE_CONNECTION_TIMEOUT_MS: z.coerce.number().positive().default(15000),
|
||||||
RECONNECT_TIMEOUT_MS: z.coerce.number().positive().default(5000),
|
RECONNECT_TIMEOUT_MS: z.coerce.number().positive().default(5000),
|
||||||
@@ -96,7 +96,7 @@ const configSchema = z
|
|||||||
.number()
|
.number()
|
||||||
.positive()
|
.positive()
|
||||||
.default(15000),
|
.default(15000),
|
||||||
AI_ANALYSIS_ERROR_COOLDOWN_MS: z.coerce.number().positive().default(30000),
|
AI_ANALYSIS_ERROR_COOLDOWN_MS: z.coerce.number().positive().default(0),
|
||||||
/** Max messages fetched per conversation batch (token budget is the real constraint). */
|
/** Max messages fetched per conversation batch (token budget is the real constraint). */
|
||||||
AI_ANALYSIS_MAX_BATCH_SIZE: z.coerce.number().int().positive().default(200),
|
AI_ANALYSIS_MAX_BATCH_SIZE: z.coerce.number().int().positive().default(200),
|
||||||
AI_ANALYSIS_MAX_CONTEXT_TOKENS: z.coerce.number().positive().default(8000),
|
AI_ANALYSIS_MAX_CONTEXT_TOKENS: z.coerce.number().positive().default(8000),
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ export async function retryWithBackoff<T>(
|
|||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const {
|
const {
|
||||||
retries = 3,
|
retries = 3,
|
||||||
minTimeout = 1000,
|
minTimeout = 0,
|
||||||
maxTimeout = 30000,
|
maxTimeout = 0,
|
||||||
factor = 2,
|
factor = 1,
|
||||||
logger,
|
logger,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -21,7 +21,7 @@ const configSchema = z
|
|||||||
RECORDINGS_DIR: z.string().default("./recordings"),
|
RECORDINGS_DIR: z.string().default("./recordings"),
|
||||||
RECORDING_SEGMENT_MS: z.coerce.number().positive().default(5000),
|
RECORDING_SEGMENT_MS: z.coerce.number().positive().default(5000),
|
||||||
DECODER_ROTATE_MS: z.coerce.number().positive().default(5000),
|
DECODER_ROTATE_MS: z.coerce.number().positive().default(5000),
|
||||||
DECODER_COOLDOWN_MS: z.coerce.number().positive().default(30000),
|
DECODER_COOLDOWN_MS: z.coerce.number().positive().default(0),
|
||||||
WEBSERVER_PORT: z.coerce.number().positive().default(3000),
|
WEBSERVER_PORT: z.coerce.number().positive().default(3000),
|
||||||
VOICE_CONNECTION_TIMEOUT_MS: z.coerce.number().positive().default(15000),
|
VOICE_CONNECTION_TIMEOUT_MS: z.coerce.number().positive().default(15000),
|
||||||
RECONNECT_TIMEOUT_MS: z.coerce.number().positive().default(5000),
|
RECONNECT_TIMEOUT_MS: z.coerce.number().positive().default(5000),
|
||||||
@@ -96,7 +96,7 @@ const configSchema = z
|
|||||||
.number()
|
.number()
|
||||||
.positive()
|
.positive()
|
||||||
.default(15000),
|
.default(15000),
|
||||||
AI_ANALYSIS_ERROR_COOLDOWN_MS: z.coerce.number().positive().default(30000),
|
AI_ANALYSIS_ERROR_COOLDOWN_MS: z.coerce.number().positive().default(0),
|
||||||
/** Max messages fetched per conversation batch (token budget is the real constraint). */
|
/** Max messages fetched per conversation batch (token budget is the real constraint). */
|
||||||
AI_ANALYSIS_MAX_BATCH_SIZE: z.coerce.number().int().positive().default(200),
|
AI_ANALYSIS_MAX_BATCH_SIZE: z.coerce.number().int().positive().default(200),
|
||||||
AI_ANALYSIS_MAX_CONTEXT_TOKENS: z.coerce.number().positive().default(8000),
|
AI_ANALYSIS_MAX_CONTEXT_TOKENS: z.coerce.number().positive().default(8000),
|
||||||
|
|||||||
@@ -349,9 +349,9 @@ async function processIndividualFallback(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries: 2,
|
retries: 0,
|
||||||
minTimeout: 2000,
|
minTimeout: 0,
|
||||||
maxTimeout: 15000,
|
maxTimeout: 0,
|
||||||
logger,
|
logger,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export async function uploadAttachmentToTele(
|
|||||||
contentType,
|
contentType,
|
||||||
uploadUrl: config.TELE_UPLOAD_URL,
|
uploadUrl: config.TELE_UPLOAD_URL,
|
||||||
timeoutMs: config.ATTACHMENT_UPLOAD_TIMEOUT_MS,
|
timeoutMs: config.ATTACHMENT_UPLOAD_TIMEOUT_MS,
|
||||||
retries: config.ATTACHMENT_RETRY_ATTEMPTS,
|
retries: 0,
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ const BADWORD_CACHE_TTL_MS = 10 * 60 * 1000;
|
|||||||
*/
|
*/
|
||||||
const DB_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
const DB_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||||
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 30_000;
|
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||||
const GROQ_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
const GROQ_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||||
|
|
||||||
interface BadwordCacheEntry {
|
interface BadwordCacheEntry {
|
||||||
value: string[];
|
value: string[];
|
||||||
@@ -275,9 +275,9 @@ async function callPrimaryAiModeration(text: string): Promise<string[]> {
|
|||||||
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming);
|
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries: 1,
|
retries: 0,
|
||||||
minTimeout: 500,
|
minTimeout: 0,
|
||||||
maxTimeout: 2000,
|
maxTimeout: 0,
|
||||||
factor: 2,
|
factor: 2,
|
||||||
logger: log,
|
logger: log,
|
||||||
},
|
},
|
||||||
@@ -526,10 +526,7 @@ export async function detectIndonesianBadwords(
|
|||||||
if (status === 429) {
|
if (status === 429) {
|
||||||
groqUnavailableUntil = Date.now() + GROQ_RATE_LIMIT_COOLDOWN_MS;
|
groqUnavailableUntil = Date.now() + GROQ_RATE_LIMIT_COOLDOWN_MS;
|
||||||
}
|
}
|
||||||
log.warn(
|
log.warn({ error }, "Groq Llama Prompt Guard moderation failed");
|
||||||
{ error },
|
|
||||||
"Groq Llama Prompt Guard moderation failed",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -748,9 +748,7 @@ async function callModerationLLM(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries: 3,
|
retries: 0,
|
||||||
minTimeout: 1000,
|
|
||||||
maxTimeout: 10000,
|
|
||||||
logger: log,
|
logger: log,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
+3
-3
@@ -92,9 +92,9 @@ export async function startRecording(
|
|||||||
config.VOICE_CONNECTION_TIMEOUT_MS,
|
config.VOICE_CONNECTION_TIMEOUT_MS,
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
retries: 3,
|
retries: 0,
|
||||||
minTimeout: 1000,
|
minTimeout: 0,
|
||||||
maxTimeout: 5000,
|
maxTimeout: 0,
|
||||||
logger,
|
logger,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export async function uploadRecordingSegment(input: {
|
|||||||
filename: fileName,
|
filename: fileName,
|
||||||
contentType: "audio/ogg",
|
contentType: "audio/ogg",
|
||||||
uploadUrl: config.TELE_UPLOAD_URL,
|
uploadUrl: config.TELE_UPLOAD_URL,
|
||||||
retries: 3,
|
retries: 0,
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
const downloadUrl = uploadResult.url;
|
const downloadUrl = uploadResult.url;
|
||||||
|
|||||||
+3
-3
@@ -15,9 +15,9 @@ export async function retryWithBackoff<T>(
|
|||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const {
|
const {
|
||||||
retries = 3,
|
retries = 3,
|
||||||
minTimeout = 1000,
|
minTimeout = 0,
|
||||||
maxTimeout = 30000,
|
maxTimeout = 0,
|
||||||
factor = 2,
|
factor = 1,
|
||||||
logger,
|
logger,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { createChildLogger } from "../logger.js";
|
|||||||
import { syncSelectedChannelBacklog } from "../moderation/backlogSync.js";
|
import { syncSelectedChannelBacklog } from "../moderation/backlogSync.js";
|
||||||
|
|
||||||
const logger = createChildLogger("sync-routes");
|
const logger = createChildLogger("sync-routes");
|
||||||
const BACKLOG_SYNC_COOLDOWN_MS = 5 * 60 * 1000;
|
const BACKLOG_SYNC_COOLDOWN_MS = 0;
|
||||||
const MAX_CONCURRENT_SYNCS = 3; // P3: cap concurrent backlogs
|
const MAX_CONCURRENT_SYNCS = 3; // P3: cap concurrent backlogs
|
||||||
|
|
||||||
const recentBacklogSyncs = new Map<string, number>();
|
const recentBacklogSyncs = new Map<string, number>();
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ export async function uploadToTele(input: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries,
|
retries,
|
||||||
minTimeout: 1000,
|
minTimeout: 0,
|
||||||
maxTimeout: 5000,
|
maxTimeout: 0,
|
||||||
logger,
|
logger,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user