[BE] Add a queue to Sunat API calls

master
Araozu 2023-06-12 22:07:46 -05:00
parent 5a8b93edc2
commit 459d5ceaff
2 changed files with 70 additions and 0 deletions

View File

@ -0,0 +1,56 @@
type ResolveFn = (v: null) => void;
const waitTime = 500;
const queue: Array<Promise<null>> = [];
function schedule(resolve: ResolveFn) {
if (queue.length === 0) {
// Call resolve after 500ms
const newPromise = new Promise<null>((newResolve) => {
setTimeout(() => {
// Remove this promise from the queue
queue.shift();
// Resolve the original promise
resolve(null);
// Resolve this promise,
// to allow chaining
newResolve(null);
}, waitTime);
});
queue.push(newPromise);
} else {
// Create a new promise, and make it wait
// for the last promise in the queue
const lastPromise = queue[queue.length - 1];
const newPromise = new Promise<null>((newResolve) => {
// Chain to last promise
lastPromise.then(() => {
setTimeout(() => {
// Remove this promise from the queue
queue.shift();
// Resolve the original promise
resolve(null);
// Resolve this promise,
// to allow chaining
newResolve(null);
}, waitTime);
});
});
queue.push(newPromise);
}
}
export function waitForSunatApi(): Promise<null> {
return new Promise((resolve) => {
schedule(resolve);
});
}

View File

@ -4,6 +4,7 @@ import { DataSource, Repository } from "typeorm";
import { Persona } from "../../model/Persona/persona.entity";
import { Person } from "../../types/Person";
import axios from "axios";
import { waitForSunatApi } from "./SunatQueue";
interface SunatPerson {
apellidoPaterno: string,
@ -34,6 +35,15 @@ export class PersonService {
}
}
/**
* ALL CALLS TO THIS METHOD ARE INSERTED TO A QUEUE,
* EACH REQUEST TO SUNAT WAITS AT LEAST 500ms,
* to avoid hitting rate limits.
*
* @param dni Dni of the person
* @returns A person, if found, or throws if not found
* @throws A 404 exception if not found
*/
async getByDni(dni: string): Promise<Person> {
// Search person in new tables
const person = await this.personaRepository.findOneBy({
@ -57,6 +67,10 @@ export class PersonService {
// Search person in SUNAT API
let personSunat: SunatPerson | null = null;
try {
// Enter Sunat API queue
await waitForSunatApi();
// Then perform the actual request
const personSunatR = await axios.get<SunatPerson>(`https://api.apis.net.pe/v1/dni?numero=${dni}`, {
headers: {
"Authorization": `Bearer ${token}`,