[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 { Persona } from "../../model/Persona/persona.entity";
|
||||||
import { Person } from "../../types/Person";
|
import { Person } from "../../types/Person";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { waitForSunatApi } from "./SunatQueue";
|
||||||
|
|
||||||
interface SunatPerson {
|
interface SunatPerson {
|
||||||
apellidoPaterno: string,
|
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> {
|
async getByDni(dni: string): Promise<Person> {
|
||||||
// Search person in new tables
|
// Search person in new tables
|
||||||
const person = await this.personaRepository.findOneBy({
|
const person = await this.personaRepository.findOneBy({
|
||||||
@ -57,6 +67,10 @@ export class PersonService {
|
|||||||
// Search person in SUNAT API
|
// Search person in SUNAT API
|
||||||
let personSunat: SunatPerson | null = null;
|
let personSunat: SunatPerson | null = null;
|
||||||
try {
|
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}`, {
|
const personSunatR = await axios.get<SunatPerson>(`https://api.apis.net.pe/v1/dni?numero=${dni}`, {
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Bearer ${token}`,
|
"Authorization": `Bearer ${token}`,
|
||||||
|
Loading…
Reference in New Issue
Block a user