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 {
|
||||
if (row.ai_status !== "flagged" && row.ai_status !== "warn") return;
|
||||
const run = () => {
|
||||
attemptAutoDeleteFlaggedMessage(moderationClient, row).catch((error: unknown) => {
|
||||
logger.error(
|
||||
{
|
||||
messageId: row.id,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
},
|
||||
"Unexpected auto-delete error",
|
||||
);
|
||||
});
|
||||
attemptAutoDeleteFlaggedMessage(moderationClient, row).catch(
|
||||
(error: unknown) => {
|
||||
logger.error(
|
||||
{
|
||||
messageId: row.id,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
},
|
||||
"Unexpected auto-delete error",
|
||||
);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
if (config.AUTO_DELETE_FLAGGED_DELAY_MS > 0) {
|
||||
@@ -349,9 +351,9 @@ async function processIndividualFallback(
|
||||
}
|
||||
},
|
||||
{
|
||||
retries: 2,
|
||||
minTimeout: 2000,
|
||||
maxTimeout: 15000,
|
||||
retries: 0,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
logger,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -74,9 +74,9 @@ const BADWORD_CACHE_TTL_MS = 10 * 60 * 1000;
|
||||
*/
|
||||
const DB_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
||||
|
||||
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
||||
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 30_000;
|
||||
const GROQ_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
||||
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||
const GROQ_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||
|
||||
interface BadwordCacheEntry {
|
||||
value: string[];
|
||||
@@ -275,9 +275,9 @@ async function callPrimaryAiModeration(text: string): Promise<string[]> {
|
||||
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming);
|
||||
},
|
||||
{
|
||||
retries: 1,
|
||||
minTimeout: 500,
|
||||
maxTimeout: 2000,
|
||||
retries: 0,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
factor: 2,
|
||||
logger: log,
|
||||
},
|
||||
|
||||
@@ -748,9 +748,7 @@ async function callModerationLLM(
|
||||
}
|
||||
},
|
||||
{
|
||||
retries: 3,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 10000,
|
||||
retries: 0,
|
||||
logger: log,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -44,7 +44,7 @@ export async function uploadAttachmentToTele(
|
||||
contentType,
|
||||
uploadUrl: config.TELE_UPLOAD_URL,
|
||||
timeoutMs: config.ATTACHMENT_UPLOAD_TIMEOUT_MS,
|
||||
retries: config.ATTACHMENT_RETRY_ATTEMPTS,
|
||||
retries: 0,
|
||||
logger,
|
||||
});
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ export async function uploadToTele(input: {
|
||||
},
|
||||
{
|
||||
retries,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 5000,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
logger,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -92,9 +92,9 @@ export async function startRecording(
|
||||
config.VOICE_CONNECTION_TIMEOUT_MS,
|
||||
),
|
||||
{
|
||||
retries: 3,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 5000,
|
||||
retries: 0,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
logger,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -60,7 +60,7 @@ export async function uploadRecordingSegment(input: {
|
||||
filename: fileName,
|
||||
contentType: "audio/ogg",
|
||||
uploadUrl: config.TELE_UPLOAD_URL,
|
||||
retries: 3,
|
||||
retries: 0,
|
||||
logger,
|
||||
});
|
||||
const downloadUrl = uploadResult.url;
|
||||
|
||||
@@ -75,8 +75,8 @@ export async function uploadToTele(input: {
|
||||
},
|
||||
{
|
||||
retries,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 5000,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
logger,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ const configSchema = z
|
||||
RECORDINGS_DIR: z.string().default("./recordings"),
|
||||
RECORDING_SEGMENT_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),
|
||||
VOICE_CONNECTION_TIMEOUT_MS: z.coerce.number().positive().default(15000),
|
||||
RECONNECT_TIMEOUT_MS: z.coerce.number().positive().default(5000),
|
||||
@@ -96,7 +96,7 @@ const configSchema = z
|
||||
.number()
|
||||
.positive()
|
||||
.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). */
|
||||
AI_ANALYSIS_MAX_BATCH_SIZE: z.coerce.number().int().positive().default(200),
|
||||
AI_ANALYSIS_MAX_CONTEXT_TOKENS: z.coerce.number().positive().default(8000),
|
||||
|
||||
@@ -15,9 +15,9 @@ export async function retryWithBackoff<T>(
|
||||
): Promise<T> {
|
||||
const {
|
||||
retries = 3,
|
||||
minTimeout = 1000,
|
||||
maxTimeout = 30000,
|
||||
factor = 2,
|
||||
minTimeout = 0,
|
||||
maxTimeout = 0,
|
||||
factor = 1,
|
||||
logger,
|
||||
} = options;
|
||||
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ const configSchema = z
|
||||
RECORDINGS_DIR: z.string().default("./recordings"),
|
||||
RECORDING_SEGMENT_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),
|
||||
VOICE_CONNECTION_TIMEOUT_MS: z.coerce.number().positive().default(15000),
|
||||
RECONNECT_TIMEOUT_MS: z.coerce.number().positive().default(5000),
|
||||
@@ -96,7 +96,7 @@ const configSchema = z
|
||||
.number()
|
||||
.positive()
|
||||
.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). */
|
||||
AI_ANALYSIS_MAX_BATCH_SIZE: z.coerce.number().int().positive().default(200),
|
||||
AI_ANALYSIS_MAX_CONTEXT_TOKENS: z.coerce.number().positive().default(8000),
|
||||
|
||||
@@ -349,9 +349,9 @@ async function processIndividualFallback(
|
||||
}
|
||||
},
|
||||
{
|
||||
retries: 2,
|
||||
minTimeout: 2000,
|
||||
maxTimeout: 15000,
|
||||
retries: 0,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
logger,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -44,7 +44,7 @@ export async function uploadAttachmentToTele(
|
||||
contentType,
|
||||
uploadUrl: config.TELE_UPLOAD_URL,
|
||||
timeoutMs: config.ATTACHMENT_UPLOAD_TIMEOUT_MS,
|
||||
retries: config.ATTACHMENT_RETRY_ATTEMPTS,
|
||||
retries: 0,
|
||||
logger,
|
||||
});
|
||||
|
||||
|
||||
@@ -74,9 +74,9 @@ const BADWORD_CACHE_TTL_MS = 10 * 60 * 1000;
|
||||
*/
|
||||
const DB_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
||||
|
||||
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
||||
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 30_000;
|
||||
const GROQ_RATE_LIMIT_COOLDOWN_MS = 60 * 1000;
|
||||
const NEMOTRON_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||
const PRIMARY_AI_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||
const GROQ_RATE_LIMIT_COOLDOWN_MS = 0;
|
||||
|
||||
interface BadwordCacheEntry {
|
||||
value: string[];
|
||||
@@ -275,9 +275,9 @@ async function callPrimaryAiModeration(text: string): Promise<string[]> {
|
||||
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming);
|
||||
},
|
||||
{
|
||||
retries: 1,
|
||||
minTimeout: 500,
|
||||
maxTimeout: 2000,
|
||||
retries: 0,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
factor: 2,
|
||||
logger: log,
|
||||
},
|
||||
@@ -526,10 +526,7 @@ export async function detectIndonesianBadwords(
|
||||
if (status === 429) {
|
||||
groqUnavailableUntil = Date.now() + GROQ_RATE_LIMIT_COOLDOWN_MS;
|
||||
}
|
||||
log.warn(
|
||||
{ error },
|
||||
"Groq Llama Prompt Guard moderation failed",
|
||||
);
|
||||
log.warn({ error }, "Groq Llama Prompt Guard moderation failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,9 +748,7 @@ async function callModerationLLM(
|
||||
}
|
||||
},
|
||||
{
|
||||
retries: 3,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 10000,
|
||||
retries: 0,
|
||||
logger: log,
|
||||
},
|
||||
);
|
||||
|
||||
+3
-3
@@ -92,9 +92,9 @@ export async function startRecording(
|
||||
config.VOICE_CONNECTION_TIMEOUT_MS,
|
||||
),
|
||||
{
|
||||
retries: 3,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 5000,
|
||||
retries: 0,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
logger,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -60,7 +60,7 @@ export async function uploadRecordingSegment(input: {
|
||||
filename: fileName,
|
||||
contentType: "audio/ogg",
|
||||
uploadUrl: config.TELE_UPLOAD_URL,
|
||||
retries: 3,
|
||||
retries: 0,
|
||||
logger,
|
||||
});
|
||||
const downloadUrl = uploadResult.url;
|
||||
|
||||
+3
-3
@@ -15,9 +15,9 @@ export async function retryWithBackoff<T>(
|
||||
): Promise<T> {
|
||||
const {
|
||||
retries = 3,
|
||||
minTimeout = 1000,
|
||||
maxTimeout = 30000,
|
||||
factor = 2,
|
||||
minTimeout = 0,
|
||||
maxTimeout = 0,
|
||||
factor = 1,
|
||||
logger,
|
||||
} = options;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createChildLogger } from "../logger.js";
|
||||
import { syncSelectedChannelBacklog } from "../moderation/backlogSync.js";
|
||||
|
||||
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 recentBacklogSyncs = new Map<string, number>();
|
||||
|
||||
@@ -75,8 +75,8 @@ export async function uploadToTele(input: {
|
||||
},
|
||||
{
|
||||
retries,
|
||||
minTimeout: 1000,
|
||||
maxTimeout: 5000,
|
||||
minTimeout: 0,
|
||||
maxTimeout: 0,
|
||||
logger,
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user