This commit is contained in:
2026-04-19 13:23:00 +03:00
parent e4c74025e5
commit 1346924387
25 changed files with 1639 additions and 1076 deletions
@@ -1,6 +1,9 @@
import { HttpException, HttpStatus, Injectable, Logger } from "@nestjs/common";
import axios from "axios";
import { GeminiService } from "../../gemini/gemini.service";
import {
AiEngineClient,
AiEngineRequestError,
} from "../../../common/utils/ai-engine-client";
export type PredictionRiskLevel = "LOW" | "MEDIUM" | "HIGH" | "EXTREME";
export type PredictionDataQuality = "HIGH" | "MEDIUM" | "LOW";
@@ -126,24 +129,34 @@ export interface SmartCouponResult {
export class SmartCouponService {
private readonly logger = new Logger(SmartCouponService.name);
private readonly aiEngineUrl: string;
private readonly aiEngineClient: AiEngineClient;
constructor(private readonly geminiService: GeminiService) {
this.aiEngineUrl = process.env.AI_ENGINE_URL || "http://ai-engine:8000";
this.aiEngineClient = new AiEngineClient({
baseUrl: this.aiEngineUrl,
logger: this.logger,
serviceName: SmartCouponService.name,
timeoutMs: 60000,
maxRetries: 2,
retryDelayMs: 750,
});
}
async analyzeMatch(matchId: string): Promise<SingleMatchPredictionPackage> {
let prediction: SingleMatchPredictionPackage;
try {
const response = await axios.post<SingleMatchPredictionPackage>(
`${this.aiEngineUrl}/v20plus/analyze/${matchId}`,
const response = await this.aiEngineClient.post<SingleMatchPredictionPackage>(
`/v20plus/analyze/${matchId}`,
);
prediction = response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
const detail = error.response?.data?.detail || error.message;
} catch (error: unknown) {
if (error instanceof AiEngineRequestError) {
const detail =
typeof error.detail === "string" ? error.detail : error.message;
throw new HttpException(
`AI analyze failed: ${detail}`,
error.response?.status || HttpStatus.SERVICE_UNAVAILABLE,
error.status || HttpStatus.SERVICE_UNAVAILABLE,
);
}
throw new HttpException(
@@ -205,8 +218,8 @@ export class SmartCouponService {
options: { maxMatches?: number; minConfidence?: number } = {},
): Promise<SmartCouponResult> {
try {
const response = await axios.post<SmartCouponResult>(
`${this.aiEngineUrl}/v20plus/coupon`,
const response = await this.aiEngineClient.post<SmartCouponResult>(
"/v20plus/coupon",
{
match_ids: matchIds,
strategy,
@@ -215,13 +228,14 @@ export class SmartCouponService {
},
);
return response.data;
} catch (error) {
} catch (error: unknown) {
this.logger.error("Failed to generate smart coupon", error);
if (axios.isAxiosError(error)) {
const detail = error.response?.data?.detail || error.message;
if (error instanceof AiEngineRequestError) {
const detail =
typeof error.detail === "string" ? error.detail : error.message;
throw new HttpException(
`Coupon generation failed: ${detail}`,
error.response?.status || HttpStatus.SERVICE_UNAVAILABLE,
error.status || HttpStatus.SERVICE_UNAVAILABLE,
);
}
throw new HttpException(