






















@@ -32,7 +32,9 @@ import {
3232buildTextEmbeddingInputs,
3333filterNonEmptyMemoryChunks,
3434isRetryableMemoryEmbeddingError,
35+isSplittableMemoryEmbeddingTransportError,
3536resolveMemoryEmbeddingRetryDelay,
37+runMemoryEmbeddingBatchRetryWithSplit,
3638runMemoryEmbeddingRetryLoop,
3739} from "./manager-embedding-policy.js";
3840import { deleteMemoryFtsRows } from "./manager-fts-state.js";
@@ -344,26 +346,33 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
344346throw new Error("Cannot embed batch in FTS-only mode (no embedding provider)");
345347}
346348try {
347-return await runMemoryEmbeddingRetryLoop({
348-run: async () => {
349+return await runMemoryEmbeddingBatchRetryWithSplit({
350+items: texts,
351+run: async (batchTexts) => {
349352const timeoutMs = this.resolveEmbeddingTimeout("batch");
350353log.debug("memory embeddings: batch start", {
351354provider: provider.id,
352-items: texts.length,
355+items: batchTexts.length,
353356 timeoutMs,
354357});
355358return await runEmbeddingOperationWithTimeout({
356359 timeoutMs,
357360message: `memory embeddings batch timed out after ${Math.round(timeoutMs / 1000)}s`,
358-run: async (signal) => await provider.embedBatch(texts, { signal }),
361+run: async (signal) => await provider.embedBatch(batchTexts, { signal }),
359362});
360363},
361364isRetryable: isRetryableMemoryEmbeddingError,
365+isSplittable: isSplittableMemoryEmbeddingTransportError,
362366waitForRetry: async (delayMs) => {
363367await this.waitForEmbeddingRetry(delayMs, "retrying");
364368},
365369maxAttempts: EMBEDDING_RETRY_MAX_ATTEMPTS,
366370baseDelayMs: EMBEDDING_RETRY_BASE_DELAY_MS,
371+onSplit: ({ itemCount, splitAt }) => {
372+log.warn(
373+`memory embeddings transport failed after retries; splitting batch of ${itemCount} into ${splitAt} + ${itemCount - splitAt}`,
374+);
375+},
367376});
368377} catch (err) {
369378this.markLocalEmbeddingProviderDegraded(err);
@@ -385,26 +394,33 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
385394return await this.embedBatchWithRetry(inputs.map((input) => input.text));
386395}
387396try {
388-return await runMemoryEmbeddingRetryLoop({
389-run: async () => {
397+return await runMemoryEmbeddingBatchRetryWithSplit({
398+items: inputs,
399+run: async (batchInputs) => {
390400const timeoutMs = this.resolveEmbeddingTimeout("batch");
391401log.debug("memory embeddings: structured batch start", {
392402provider: provider.id,
393-items: inputs.length,
403+items: batchInputs.length,
394404 timeoutMs,
395405});
396406return await runEmbeddingOperationWithTimeout({
397407 timeoutMs,
398408message: `memory embeddings batch timed out after ${Math.round(timeoutMs / 1000)}s`,
399-run: async (signal) => await embedBatchInputs(inputs, { signal }),
409+run: async (signal) => await embedBatchInputs(batchInputs, { signal }),
400410});
401411},
402412isRetryable: isRetryableMemoryEmbeddingError,
413+isSplittable: isSplittableMemoryEmbeddingTransportError,
403414waitForRetry: async (delayMs) => {
404415await this.waitForEmbeddingRetry(delayMs, "retrying structured batch");
405416},
406417maxAttempts: EMBEDDING_RETRY_MAX_ATTEMPTS,
407418baseDelayMs: EMBEDDING_RETRY_BASE_DELAY_MS,
419+onSplit: ({ itemCount, splitAt }) => {
420+log.warn(
421+`memory embeddings transport failed after retries; splitting structured batch of ${itemCount} into ${splitAt} + ${itemCount - splitAt}`,
422+);
423+},
408424});
409425} catch (err) {
410426this.markLocalEmbeddingProviderDegraded(err);
@@ -422,7 +438,7 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
422438Math.random(),
423439EMBEDDING_RETRY_MAX_DELAY_MS,
424440);
425-log.warn(`memory embeddings rate limited; ${action} in ${waitMs}ms`);
441+log.warn(`memory embeddings retryable error; ${action} in ${waitMs}ms`);
426442await new Promise((resolve) => setTimeout(resolve, waitMs));
427443}
428444@@ -435,18 +451,28 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
435451});
436452}
437453438-protected async embedQueryWithTimeout(text: string): Promise<number[]> {
454+protected async embedQueryWithRetry(text: string): Promise<number[]> {
439455const provider = this.provider;
440456if (!provider) {
441457throw new Error("Cannot embed query in FTS-only mode (no embedding provider)");
442458}
443-const timeoutMs = this.resolveEmbeddingTimeout("query");
444-log.debug("memory embeddings: query start", { provider: provider.id, timeoutMs });
445459try {
446-return await runEmbeddingOperationWithTimeout({
447- timeoutMs,
448-message: `memory embeddings query timed out after ${Math.round(timeoutMs / 1000)}s`,
449-run: async (signal) => await provider.embedQuery(text, { signal }),
460+return await runMemoryEmbeddingRetryLoop({
461+run: async () => {
462+const timeoutMs = this.resolveEmbeddingTimeout("query");
463+log.debug("memory embeddings: query start", { provider: provider.id, timeoutMs });
464+return await runEmbeddingOperationWithTimeout({
465+ timeoutMs,
466+message: `memory embeddings query timed out after ${Math.round(timeoutMs / 1000)}s`,
467+run: async (signal) => await provider.embedQuery(text, { signal }),
468+});
469+},
470+isRetryable: isRetryableMemoryEmbeddingError,
471+waitForRetry: async (delayMs) => {
472+await this.waitForEmbeddingRetry(delayMs, "retrying query");
473+},
474+maxAttempts: EMBEDDING_RETRY_MAX_ATTEMPTS,
475+baseDelayMs: EMBEDDING_RETRY_BASE_DELAY_MS,
450476});
451477} catch (err) {
452478this.markLocalEmbeddingProviderDegraded(err);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。