mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:43:06 +00:00
feat(C155): fallback de listagem desce ao mês quando o ano inteiro falha
This commit is contained in:
parent
2040c98654
commit
b86c108754
3 changed files with 49 additions and 19 deletions
|
|
@ -245,9 +245,10 @@ async function fetchSpeechesRange(deputyId, from, to) {
|
|||
|
||||
/**
|
||||
* Lista a faixa inteira; se a API recusar uma página funda (500/hang
|
||||
* persistente, visto na 55ª em 2026-09-13), cai para a listagem por ano — cada
|
||||
* chunk é raso e um ano quebrado não derruba os demais. Os chunks que falharem
|
||||
* são reportados via `onWarning` (o run os registra como falha de `list`).
|
||||
* persistente, visto na 55ª em 2026-09-13), cai para a listagem por ano e,
|
||||
* se um ano inteiro falhar, desce ao mês — cada chunk é raso e um mês
|
||||
* quebrado não derruba os demais. Os chunks que falharem são reportados via
|
||||
* `onWarning` (o run os registra como falha de `list`).
|
||||
*/
|
||||
async function fetchSpeeches(deputyId, from, to, onWarning = () => {}) {
|
||||
try {
|
||||
|
|
@ -256,12 +257,21 @@ async function fetchSpeeches(deputyId, from, to, onWarning = () => {}) {
|
|||
onWarning(`listagem ${from}..${to} falhou (${error?.message}); tentando por ano`)
|
||||
const speeches = []
|
||||
let listedChunks = 0
|
||||
for (const [chunkFrom, chunkTo] of dateRangeChunks(from, to)) {
|
||||
for (const [yearFrom, yearTo] of dateRangeChunks(from, to)) {
|
||||
try {
|
||||
speeches.push(...(await fetchSpeechesRange(deputyId, chunkFrom, chunkTo)))
|
||||
speeches.push(...(await fetchSpeechesRange(deputyId, yearFrom, yearTo)))
|
||||
listedChunks += 1
|
||||
} catch (chunkError) {
|
||||
onWarning(`listagem ${chunkFrom}..${chunkTo} falhou: ${chunkError?.message}`)
|
||||
continue
|
||||
} catch (yearError) {
|
||||
onWarning(`listagem ${yearFrom}..${yearTo} falhou: ${yearError?.message}; tentando por mês`)
|
||||
}
|
||||
for (const [monthFrom, monthTo] of dateRangeChunks(yearFrom, yearTo, 'month')) {
|
||||
try {
|
||||
speeches.push(...(await fetchSpeechesRange(deputyId, monthFrom, monthTo)))
|
||||
listedChunks += 1
|
||||
} catch (monthError) {
|
||||
onWarning(`listagem ${monthFrom}..${monthTo} falhou: ${monthError?.message}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (listedChunks === 0) throw error
|
||||
|
|
|
|||
|
|
@ -399,27 +399,36 @@ export const normalizeTranscription = (json) => {
|
|||
}
|
||||
}
|
||||
|
||||
const isIsoDate = (value) => /^\d{4}-\d{2}-\d{2}$/.test(String(value))
|
||||
|
||||
/**
|
||||
* Splits an inclusive `YYYY-MM-DD` range into calendar-year chunks (no
|
||||
* overlap; first/last partial). The backfill fallback uses it when the API
|
||||
* refuses a deep page: a shallow per-year listing still recovers the years
|
||||
* the broken offset does not cover.
|
||||
* Splits an inclusive `YYYY-MM-DD` range into calendar chunks (no overlap;
|
||||
* first/last partial) at `unit` granularity. The backfill fallback uses it
|
||||
* when the API refuses a deep page: a shallow per-year listing still recovers
|
||||
* the years the broken offset does not cover, and a broken year is isolated
|
||||
* down to the month.
|
||||
*
|
||||
* @param {string} from
|
||||
* @param {string} to
|
||||
* @param {'year' | 'month'} unit
|
||||
* @returns {Array<[string, string]>}
|
||||
*/
|
||||
export const dateRangeChunks = (from, to) => {
|
||||
export const dateRangeChunks = (from, to, unit = 'year') => {
|
||||
const chunks = []
|
||||
if (!/^\d{4}-\d{2}-\d{2}$/.test(String(from)) || !/^\d{4}-\d{2}-\d{2}$/.test(String(to))) {
|
||||
return chunks
|
||||
}
|
||||
if (!isIsoDate(from) || !isIsoDate(to)) return chunks
|
||||
let start = String(from)
|
||||
while (start <= String(to)) {
|
||||
const yearEnd = `${start.slice(0, 4)}-12-31`
|
||||
const end = yearEnd < String(to) ? yearEnd : String(to)
|
||||
chunks.push([start, end])
|
||||
const next = new Date(`${end}T00:00:00Z`)
|
||||
const end =
|
||||
unit === 'month'
|
||||
? `${start.slice(0, 7)}-${String(
|
||||
new Date(
|
||||
Date.UTC(Number(start.slice(0, 4)), Number(start.slice(5, 7)), 0),
|
||||
).getUTCDate(),
|
||||
).padStart(2, '0')}`
|
||||
: `${start.slice(0, 4)}-12-31`
|
||||
const boundedEnd = end < String(to) ? end : String(to)
|
||||
chunks.push([start, boundedEnd])
|
||||
const next = new Date(`${boundedEnd}T00:00:00Z`)
|
||||
next.setUTCDate(next.getUTCDate() + 1)
|
||||
start = next.toISOString().slice(0, 10)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -656,4 +656,15 @@ describe('dateRangeChunks', () => {
|
|||
expect(dateRangeChunks('2023-1-1', '2023-12-31')).toEqual([])
|
||||
expect(dateRangeChunks('', '2023-12-31')).toEqual([])
|
||||
})
|
||||
|
||||
it('splits by month when asked, with the right month length', () => {
|
||||
expect(dateRangeChunks('2018-01-01', '2018-03-15', 'month')).toEqual([
|
||||
['2018-01-01', '2018-01-31'],
|
||||
['2018-02-01', '2018-02-28'],
|
||||
['2018-03-01', '2018-03-15'],
|
||||
])
|
||||
expect(dateRangeChunks('2024-02-01', '2024-02-29', 'month')).toEqual([
|
||||
['2024-02-01', '2024-02-29'],
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue