[BE] Add a queue to Sunat API calls
This commit is contained in:
parent
5a8b93edc2
commit
459d5ceaff
56
src/controller/person/SunatQueue.ts
Normal file
56
src/controller/person/SunatQueue.ts
Normal 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);
|
||||
});
|
||||
}
|
||||
|
@ -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}`,
|
||||
|
Loading…
Reference in New Issue
Block a user