refactor(timeout): reuse shared api request timeout
This commit is contained in:
@@ -6,6 +6,7 @@ import * as http from 'node:http';
|
|||||||
import type { IApiError, IChatCompletionRequest } from '../../interfaces/api.ts';
|
import type { IApiError, IChatCompletionRequest } from '../../interfaces/api.ts';
|
||||||
import { ClusterCoordinator } from '../../cluster/coordinator.ts';
|
import { ClusterCoordinator } from '../../cluster/coordinator.ts';
|
||||||
import { ContainerManager } from '../../containers/container-manager.ts';
|
import { ContainerManager } from '../../containers/container-manager.ts';
|
||||||
|
import { API_SERVER } from '../../constants.ts';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.ts';
|
||||||
import { ModelRegistry } from '../../models/registry.ts';
|
import { ModelRegistry } from '../../models/registry.ts';
|
||||||
import { ModelLoader } from '../../models/loader.ts';
|
import { ModelLoader } from '../../models/loader.ts';
|
||||||
@@ -158,11 +159,14 @@ export class ChatHandler {
|
|||||||
targetEndpoint: string,
|
targetEndpoint: string,
|
||||||
body: IChatCompletionRequest,
|
body: IChatCompletionRequest,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), API_SERVER.REQUEST_TIMEOUT_MS);
|
||||||
const response = await fetch(`${targetEndpoint}/v1/chat/completions`, {
|
const response = await fetch(`${targetEndpoint}/v1/chat/completions`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: this.buildForwardHeaders(req),
|
headers: this.buildForwardHeaders(req),
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
});
|
signal: controller.signal,
|
||||||
|
}).finally(() => clearTimeout(timeout));
|
||||||
|
|
||||||
if (body.stream) {
|
if (body.stream) {
|
||||||
res.writeHead(response.status, {
|
res.writeHead(response.status, {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import type {
|
|||||||
} from '../../interfaces/api.ts';
|
} from '../../interfaces/api.ts';
|
||||||
import { ClusterCoordinator } from '../../cluster/coordinator.ts';
|
import { ClusterCoordinator } from '../../cluster/coordinator.ts';
|
||||||
import { ContainerManager } from '../../containers/container-manager.ts';
|
import { ContainerManager } from '../../containers/container-manager.ts';
|
||||||
|
import { API_SERVER } from '../../constants.ts';
|
||||||
import { logger } from '../../logger.ts';
|
import { logger } from '../../logger.ts';
|
||||||
import { ModelRegistry } from '../../models/registry.ts';
|
import { ModelRegistry } from '../../models/registry.ts';
|
||||||
|
|
||||||
@@ -80,7 +81,7 @@ export class EmbeddingsHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(`${ensured.location.endpoint}/v1/embeddings`, {
|
const response = await this.fetchWithTimeout(`${ensured.location.endpoint}/v1/embeddings`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: this.buildForwardHeaders(req),
|
headers: this.buildForwardHeaders(req),
|
||||||
body: JSON.stringify(requestBody),
|
body: JSON.stringify(requestBody),
|
||||||
@@ -159,7 +160,7 @@ export class EmbeddingsHandler {
|
|||||||
model: string,
|
model: string,
|
||||||
input: string,
|
input: string,
|
||||||
): Promise<{ vector: number[]; tokenCount: number }> {
|
): Promise<{ vector: number[]; tokenCount: number }> {
|
||||||
const response = await fetch(`${endpoint}/v1/embeddings`, {
|
const response = await this.fetchWithTimeout(`${endpoint}/v1/embeddings`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ model, input }),
|
body: JSON.stringify({ model, input }),
|
||||||
@@ -181,7 +182,7 @@ export class EmbeddingsHandler {
|
|||||||
_model: string,
|
_model: string,
|
||||||
input: string,
|
input: string,
|
||||||
): Promise<{ vector: number[]; tokenCount: number }> {
|
): Promise<{ vector: number[]; tokenCount: number }> {
|
||||||
const response = await fetch(`${endpoint}/embed`, {
|
const response = await this.fetchWithTimeout(`${endpoint}/embed`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ inputs: input }),
|
body: JSON.stringify({ inputs: input }),
|
||||||
@@ -214,6 +215,20 @@ export class EmbeddingsHandler {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), API_SERVER.REQUEST_TIMEOUT_MS);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await fetch(url, {
|
||||||
|
...init,
|
||||||
|
signal: controller.signal,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private sendError(
|
private sendError(
|
||||||
res: http.ServerResponse,
|
res: http.ServerResponse,
|
||||||
statusCode: number,
|
statusCode: number,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import type {
|
|||||||
TContainerType,
|
TContainerType,
|
||||||
} from '../interfaces/container.ts';
|
} from '../interfaces/container.ts';
|
||||||
import type { IChatCompletionRequest, IChatCompletionResponse } from '../interfaces/api.ts';
|
import type { IChatCompletionRequest, IChatCompletionResponse } from '../interfaces/api.ts';
|
||||||
|
import { API_SERVER } from '../constants.ts';
|
||||||
import { ContainerRuntime } from '../docker/container-runtime.ts';
|
import { ContainerRuntime } from '../docker/container-runtime.ts';
|
||||||
import { logger } from '../logger.ts';
|
import { logger } from '../logger.ts';
|
||||||
|
|
||||||
@@ -165,7 +166,7 @@ export abstract class BaseContainer {
|
|||||||
const url = `${endpoint}${path}`;
|
const url = `${endpoint}${path}`;
|
||||||
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeout = options.timeout || 30000;
|
const timeout = options.timeout || API_SERVER.REQUEST_TIMEOUT_MS;
|
||||||
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import * as fs from 'node:fs/promises';
|
import * as fs from 'node:fs/promises';
|
||||||
import type { IModelCatalog, IModelCatalogEntry } from '../interfaces/catalog.ts';
|
import type { IModelCatalog, IModelCatalogEntry } from '../interfaces/catalog.ts';
|
||||||
import { MODEL_REGISTRY, TIMING } from '../constants.ts';
|
import { API_SERVER, MODEL_REGISTRY, TIMING } from '../constants.ts';
|
||||||
import { logger } from '../logger.ts';
|
import { logger } from '../logger.ts';
|
||||||
|
|
||||||
export class ModelRegistry {
|
export class ModelRegistry {
|
||||||
@@ -167,7 +167,7 @@ export class ModelRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeout = setTimeout(() => controller.abort(), 30000);
|
const timeout = setTimeout(() => controller.abort(), API_SERVER.REQUEST_TIMEOUT_MS);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(source, {
|
const response = await fetch(source, {
|
||||||
|
|||||||
Reference in New Issue
Block a user