feat: integrate DeltaIns, Tufts SCO, United SCO, and CCA eligibility checks
This commit is contained in:
24
apps/Backend/src/services/seleniumCCAEligibilityClient.ts
Normal file
24
apps/Backend/src/services/seleniumCCAEligibilityClient.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import axios from "axios";
|
||||
|
||||
const SELENIUM_BASE = process.env.SELENIUM_SERVICE_URL ?? "http://localhost:5002";
|
||||
|
||||
/**
|
||||
* POST /cca-eligibility
|
||||
* Returns { status: "started", session_id: "<uuid>" }
|
||||
*/
|
||||
export async function forwardToSeleniumCCAEligibilityAgent(
|
||||
data: Record<string, any>
|
||||
): Promise<{ status: string; session_id: string }> {
|
||||
const resp = await axios.post(`${SELENIUM_BASE}/cca-eligibility`, { data });
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /session/{sid}/status
|
||||
*/
|
||||
export async function getSeleniumCCASessionStatus(
|
||||
sessionId: string
|
||||
): Promise<Record<string, any>> {
|
||||
const resp = await axios.get(`${SELENIUM_BASE}/session/${sessionId}/status`);
|
||||
return resp.data;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import axios from "axios";
|
||||
import http from "http";
|
||||
import https from "https";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
const SELENIUM_AGENT_BASE = process.env.SELENIUM_AGENT_BASE_URL;
|
||||
|
||||
const httpAgent = new http.Agent({ keepAlive: true, keepAliveMsecs: 60_000 });
|
||||
const httpsAgent = new https.Agent({ keepAlive: true, keepAliveMsecs: 60_000 });
|
||||
|
||||
const client = axios.create({
|
||||
baseURL: SELENIUM_AGENT_BASE,
|
||||
timeout: 5 * 60 * 1000,
|
||||
httpAgent,
|
||||
httpsAgent,
|
||||
validateStatus: (s) => s >= 200 && s < 600,
|
||||
});
|
||||
|
||||
async function requestWithRetries(config: any, retries = 4, baseBackoffMs = 300) {
|
||||
for (let attempt = 1; attempt <= retries; attempt++) {
|
||||
try {
|
||||
const r = await client.request(config);
|
||||
if (![502, 503, 504].includes(r.status)) return r;
|
||||
console.warn(`[deltains-client] retryable HTTP status ${r.status} (attempt ${attempt})`);
|
||||
} catch (err: any) {
|
||||
const code = err?.code;
|
||||
const isTransient =
|
||||
code === "ECONNRESET" || code === "ECONNREFUSED" || code === "EPIPE" || code === "ETIMEDOUT";
|
||||
if (!isTransient) throw err;
|
||||
console.warn(`[deltains-client] transient network error ${code} (attempt ${attempt})`);
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, baseBackoffMs * attempt));
|
||||
}
|
||||
return client.request(config);
|
||||
}
|
||||
|
||||
function log(tag: string, msg: string, ctx?: any) {
|
||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||
}
|
||||
|
||||
export async function forwardToSeleniumDeltaInsEligibilityAgent(data: any): Promise<any> {
|
||||
const payload = { data };
|
||||
const url = `/deltains-eligibility`;
|
||||
log("deltains-client", "POST deltains-eligibility", { url: SELENIUM_AGENT_BASE + url });
|
||||
const r = await requestWithRetries({ url, method: "POST", data: payload }, 4);
|
||||
log("deltains-client", "agent response", { status: r.status, dataKeys: r.data ? Object.keys(r.data) : null });
|
||||
if (r.status >= 500) throw new Error(`Selenium agent server error: ${r.status}`);
|
||||
return r.data;
|
||||
}
|
||||
|
||||
export async function forwardOtpToSeleniumDeltaInsAgent(sessionId: string, otp: string): Promise<any> {
|
||||
const url = `/submit-otp`;
|
||||
log("deltains-client", "POST submit-otp", { url: SELENIUM_AGENT_BASE + url, sessionId });
|
||||
const r = await requestWithRetries({ url, method: "POST", data: { session_id: sessionId, otp } }, 4);
|
||||
log("deltains-client", "submit-otp response", { status: r.status, data: r.data });
|
||||
if (r.status >= 500) throw new Error(`Selenium agent server error on submit-otp: ${r.status}`);
|
||||
return r.data;
|
||||
}
|
||||
|
||||
export async function getSeleniumDeltaInsSessionStatus(sessionId: string): Promise<any> {
|
||||
const url = `/session/${sessionId}/status`;
|
||||
log("deltains-client", "GET session status", { url: SELENIUM_AGENT_BASE + url, sessionId });
|
||||
const r = await requestWithRetries({ url, method: "GET" }, 4);
|
||||
log("deltains-client", "session status response", { status: r.status, dataKeys: r.data ? Object.keys(r.data) : null });
|
||||
if (r.status === 404) {
|
||||
const e: any = new Error("not_found");
|
||||
e.response = { status: 404, data: r.data };
|
||||
throw e;
|
||||
}
|
||||
return r.data;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import axios from "axios";
|
||||
import http from "http";
|
||||
import https from "https";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
const SELENIUM_AGENT_BASE = process.env.SELENIUM_AGENT_BASE_URL;
|
||||
|
||||
const httpAgent = new http.Agent({ keepAlive: true, keepAliveMsecs: 60_000 });
|
||||
const httpsAgent = new https.Agent({ keepAlive: true, keepAliveMsecs: 60_000 });
|
||||
|
||||
const client = axios.create({
|
||||
baseURL: SELENIUM_AGENT_BASE,
|
||||
timeout: 5 * 60 * 1000,
|
||||
httpAgent,
|
||||
httpsAgent,
|
||||
validateStatus: (s) => s >= 200 && s < 600,
|
||||
});
|
||||
|
||||
async function requestWithRetries(config: any, retries = 4, baseBackoffMs = 300) {
|
||||
for (let attempt = 1; attempt <= retries; attempt++) {
|
||||
try {
|
||||
const r = await client.request(config);
|
||||
if (![502, 503, 504].includes(r.status)) return r;
|
||||
console.warn(`[unitedsco-client] retryable HTTP status ${r.status} (attempt ${attempt})`);
|
||||
} catch (err: any) {
|
||||
const code = err?.code;
|
||||
const isTransient =
|
||||
code === "ECONNRESET" || code === "ECONNREFUSED" || code === "EPIPE" || code === "ETIMEDOUT";
|
||||
if (!isTransient) throw err;
|
||||
console.warn(`[unitedsco-client] transient network error ${code} (attempt ${attempt})`);
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, baseBackoffMs * attempt));
|
||||
}
|
||||
return client.request(config);
|
||||
}
|
||||
|
||||
function log(tag: string, msg: string, ctx?: any) {
|
||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||
}
|
||||
|
||||
export async function forwardToSeleniumUnitedSCOEligibilityAgent(data: any): Promise<any> {
|
||||
const payload = { data };
|
||||
const url = `/unitedsco-eligibility`;
|
||||
log("unitedsco-client", "POST unitedsco-eligibility", { url: SELENIUM_AGENT_BASE + url });
|
||||
const r = await requestWithRetries({ url, method: "POST", data: payload }, 4);
|
||||
log("unitedsco-client", "agent response", { status: r.status, dataKeys: r.data ? Object.keys(r.data) : null });
|
||||
if (r.status >= 500) throw new Error(`Selenium agent server error: ${r.status}`);
|
||||
return r.data;
|
||||
}
|
||||
|
||||
export async function forwardOtpToSeleniumUnitedSCOAgent(sessionId: string, otp: string): Promise<any> {
|
||||
const url = `/submit-otp`;
|
||||
log("unitedsco-client", "POST submit-otp", { url: SELENIUM_AGENT_BASE + url, sessionId });
|
||||
const r = await requestWithRetries({ url, method: "POST", data: { session_id: sessionId, otp } }, 4);
|
||||
log("unitedsco-client", "submit-otp response", { status: r.status, data: r.data });
|
||||
if (r.status >= 500) throw new Error(`Selenium agent server error on submit-otp: ${r.status}`);
|
||||
return r.data;
|
||||
}
|
||||
|
||||
export async function getSeleniumUnitedSCOSessionStatus(sessionId: string): Promise<any> {
|
||||
const url = `/session/${sessionId}/status`;
|
||||
log("unitedsco-client", "GET session status", { url: SELENIUM_AGENT_BASE + url, sessionId });
|
||||
const r = await requestWithRetries({ url, method: "GET" }, 4);
|
||||
log("unitedsco-client", "session status response", { status: r.status, dataKeys: r.data ? Object.keys(r.data) : null });
|
||||
if (r.status === 404) {
|
||||
const e: any = new Error("not_found");
|
||||
e.response = { status: 404, data: r.data };
|
||||
throw e;
|
||||
}
|
||||
return r.data;
|
||||
}
|
||||
Reference in New Issue
Block a user