@cyanheads/congressgov-mcp-server 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +25 -10
- package/CLAUDE.md +25 -10
- package/README.md +10 -5
- package/changelog/0.9.x/0.9.1.md +31 -0
- package/dist/config/server-config.d.ts +0 -7
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +1 -9
- package/dist/config/server-config.js.map +1 -1
- package/dist/mcp-server/tools/definitions/bill-lookup.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/bill-lookup.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/bill-summaries.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/bill-summaries.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/committee-lookup.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/committee-lookup.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/committee-reports.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/committee-reports.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/crs-reports.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/crs-reports.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/daily-record.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/daily-record.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/enacted-laws.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/enacted-laws.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/member-lookup.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/member-lookup.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/roll-votes.tool.d.ts +9 -2
- package/dist/mcp-server/tools/definitions/roll-votes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/roll-votes.tool.js +3 -2
- package/dist/mcp-server/tools/definitions/roll-votes.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/senate-nominations.tool.d.ts +49 -4
- package/dist/mcp-server/tools/definitions/senate-nominations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/senate-nominations.tool.js +102 -5
- package/dist/mcp-server/tools/definitions/senate-nominations.tool.js.map +1 -1
- package/dist/mcp-server/tools/format-helpers.d.ts.map +1 -1
- package/dist/mcp-server/tools/format-helpers.js +37 -8
- package/dist/mcp-server/tools/format-helpers.js.map +1 -1
- package/dist/mcp-server/tools/tool-helpers.d.ts +11 -4
- package/dist/mcp-server/tools/tool-helpers.d.ts.map +1 -1
- package/dist/mcp-server/tools/tool-helpers.js +12 -4
- package/dist/mcp-server/tools/tool-helpers.js.map +1 -1
- package/dist/services/call-budget.d.ts +77 -0
- package/dist/services/call-budget.d.ts.map +1 -0
- package/dist/services/call-budget.js +118 -0
- package/dist/services/call-budget.js.map +1 -0
- package/dist/services/congress-api/congress-api-service.d.ts +4 -0
- package/dist/services/congress-api/congress-api-service.d.ts.map +1 -1
- package/dist/services/congress-api/congress-api-service.js +60 -32
- package/dist/services/congress-api/congress-api-service.js.map +1 -1
- package/dist/services/congress-documents/congress-documents-service.d.ts +46 -15
- package/dist/services/congress-documents/congress-documents-service.d.ts.map +1 -1
- package/dist/services/congress-documents/congress-documents-service.js +95 -24
- package/dist/services/congress-documents/congress-documents-service.js.map +1 -1
- package/dist/services/congress-documents/document-body-cache.d.ts +66 -0
- package/dist/services/congress-documents/document-body-cache.d.ts.map +1 -0
- package/dist/services/congress-documents/document-body-cache.js +122 -0
- package/dist/services/congress-documents/document-body-cache.js.map +1 -0
- package/dist/services/congress-mirror/ingest.d.ts +13 -7
- package/dist/services/congress-mirror/ingest.d.ts.map +1 -1
- package/dist/services/congress-mirror/ingest.js +33 -10
- package/dist/services/congress-mirror/ingest.js.map +1 -1
- package/dist/services/congress-mirror/schema.d.ts.map +1 -1
- package/dist/services/congress-mirror/schema.js +15 -1
- package/dist/services/congress-mirror/schema.js.map +1 -1
- package/dist/services/senate-lis/parse.d.ts +23 -0
- package/dist/services/senate-lis/parse.d.ts.map +1 -1
- package/dist/services/senate-lis/parse.js +49 -5
- package/dist/services/senate-lis/parse.js.map +1 -1
- package/dist/services/senate-lis/senate-vote-service.d.ts.map +1 -1
- package/dist/services/senate-lis/senate-vote-service.js +32 -25
- package/dist/services/senate-lis/senate-vote-service.js.map +1 -1
- package/dist/utils/congress-calendar.d.ts +15 -0
- package/dist/utils/congress-calendar.d.ts.map +1 -0
- package/dist/utils/congress-calendar.js +33 -0
- package/dist/utils/congress-calendar.js.map +1 -0
- package/package.json +3 -3
- package/scripts/_mirror-context.ts +15 -9
- package/scripts/congress-mirror-init.ts +1 -1
- package/scripts/congress-mirror-refresh.ts +1 -1
- package/scripts/congress-mirror-verify.ts +5 -4
- package/server.json +3 -3
- package/skills/congressgov-guide/SKILL.md +1 -1
|
@@ -8,20 +8,30 @@
|
|
|
8
8
|
* its own service the way `SenateVoteService` does for the Senate LIS feed.
|
|
9
9
|
*
|
|
10
10
|
* Two bounds, deliberately separate:
|
|
11
|
-
* - **The fetch** is bounded by {@link MAX_DOCUMENT_BYTES}, a
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* - **The fetch** is bounded by {@link MAX_DOCUMENT_BYTES}, a per-attempt timeout,
|
|
12
|
+
* the tool call's one time budget (`call-budget.ts`), which the format lookup
|
|
13
|
+
* before it spends from too, and a content-type allowlist. The body is
|
|
14
|
+
* extracted as it streams and only the requested window is extracted into
|
|
15
|
+
* memory, so the ceiling bounds how long a response may run rather than how
|
|
16
|
+
* much of one fits in a buffer.
|
|
16
17
|
* - **The response** is bounded by an exact character offset/limit window. Offsets
|
|
17
18
|
* index into the extracted plain text and are never snapped to section or
|
|
18
19
|
* paragraph breaks, so feeding `nextOffset` back walks a document with every
|
|
19
20
|
* character returned exactly once — no overlap, no gap.
|
|
20
21
|
*
|
|
22
|
+
* Every window streams the whole body to learn `totalCharacters`, so a walk
|
|
23
|
+
* would fetch its document once per window. Instead the first read of a
|
|
24
|
+
* document that runs past its window keeps the decompressed body in a
|
|
25
|
+
* {@link DocumentBodyCache} (64 MB total, 16 MB per body, 10-minute TTL), and
|
|
26
|
+
* later windows replay those bytes through the same extractor: one fetch per
|
|
27
|
+
* document per TTL. A replay is local work and never touches the time budget.
|
|
28
|
+
*
|
|
21
29
|
* @module services/congress-documents/congress-documents-service
|
|
22
30
|
*/
|
|
23
|
-
import { JsonRpcErrorCode, McpError, notFound, serviceUnavailable, validationError, } from '@cyanheads/mcp-ts-core/errors';
|
|
24
|
-
import { defaultIsTransient, fetchWithTimeout, requestContextService,
|
|
31
|
+
import { JsonRpcErrorCode, McpError, notFound, requestCancelled, serviceUnavailable, validationError, } from '@cyanheads/mcp-ts-core/errors';
|
|
32
|
+
import { defaultIsTransient, fetchWithTimeout, requestContextService, } from '@cyanheads/mcp-ts-core/utils';
|
|
33
|
+
import { withCallBudget } from '../call-budget.js';
|
|
34
|
+
import { DocumentBodyCache } from './document-body-cache.js';
|
|
25
35
|
import { createStreamingExtractor } from './extract-text-stream.js';
|
|
26
36
|
/**
|
|
27
37
|
* Ceiling on a single document. The largest bodies Congress.gov publishes are
|
|
@@ -29,13 +39,22 @@ import { createStreamingExtractor } from './extract-text-stream.js';
|
|
|
29
39
|
* 6,790,482 bytes as Formatted Text and 9,812,888 as XML — and both formats of a
|
|
30
40
|
* document have to clear it, since a caller sent to the other one by a recovery
|
|
31
41
|
* hint would hit the same refusal. This clears the largest by better than a
|
|
32
|
-
* factor of two; the
|
|
42
|
+
* factor of two; the per-attempt timeout is what a runaway response meets first.
|
|
33
43
|
*/
|
|
34
44
|
export const MAX_DOCUMENT_BYTES = 25_000_000;
|
|
35
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Bounds one attempt's whole exchange, headers and body — a megabyte-scale body
|
|
47
|
+
* needs the room. Clamped to what is left of the call's budget.
|
|
48
|
+
*/
|
|
36
49
|
export const REQUEST_TIMEOUT_MS = 30_000;
|
|
37
50
|
const MAX_ATTEMPTS = 3;
|
|
38
51
|
const BASE_BACKOFF_MS = 500;
|
|
52
|
+
/**
|
|
53
|
+
* Largest piece of a cached body replayed between macrotask yields. Replaying
|
|
54
|
+
* from memory has no network waits, so without the yields a large document's
|
|
55
|
+
* whole parse would hold the event loop in one block.
|
|
56
|
+
*/
|
|
57
|
+
const REPLAY_SLICE_BYTES = 128 * 1024;
|
|
39
58
|
/** Every format URL these tools resolve points here; nothing else is fetched. */
|
|
40
59
|
const ALLOWED_HOSTS = new Set(['www.congress.gov']);
|
|
41
60
|
/** Content types the text extractor can read. PDF and everything else are refused. */
|
|
@@ -65,8 +84,10 @@ function isNativeAbortSignal(value) {
|
|
|
65
84
|
}
|
|
66
85
|
export class CongressDocumentsService {
|
|
67
86
|
maxDocumentBytes;
|
|
68
|
-
|
|
87
|
+
bodyCache;
|
|
88
|
+
constructor(maxDocumentBytes = MAX_DOCUMENT_BYTES, bodyCache = new DocumentBodyCache()) {
|
|
69
89
|
this.maxDocumentBytes = maxDocumentBytes;
|
|
90
|
+
this.bodyCache = bodyCache;
|
|
70
91
|
}
|
|
71
92
|
/**
|
|
72
93
|
* Fetch one document and return the requested character window of its text.
|
|
@@ -75,13 +96,25 @@ export class CongressDocumentsService {
|
|
|
75
96
|
* one — and is still checked against {@link ALLOWED_HOSTS} before any request
|
|
76
97
|
* goes out, so a redirected or malformed upstream link cannot turn this into a
|
|
77
98
|
* general-purpose fetcher.
|
|
99
|
+
*
|
|
100
|
+
* A document whose body is cached is replayed from it with no request at all.
|
|
101
|
+
* Otherwise the fetch spends what is left of the tool call's budget
|
|
102
|
+
* (`call-budget.ts`): running out throws `Timeout` (`upstream_timeout`), and a
|
|
103
|
+
* caller abort ends the call at once.
|
|
78
104
|
*/
|
|
79
105
|
async fetchDocument(params, ctx) {
|
|
80
106
|
this.assertAllowedHost(params.url);
|
|
107
|
+
const signal = this.getAbortSignal(ctx);
|
|
108
|
+
const cached = this.bodyCache.get(params.url);
|
|
109
|
+
if (cached)
|
|
110
|
+
return this.describeWindow(await this.replayWindow(cached, params, signal), params);
|
|
81
111
|
const operation = 'CongressDocumentsService GET document';
|
|
82
112
|
const requestContext = this.getRequestContext(ctx, operation);
|
|
83
|
-
const
|
|
84
|
-
|
|
113
|
+
const read = await withCallBudget((attempt) => this.doFetch(params, requestContext, attempt), {
|
|
114
|
+
call: ctx,
|
|
115
|
+
attemptTimeoutMs: REQUEST_TIMEOUT_MS,
|
|
116
|
+
upstream: 'Congress.gov',
|
|
117
|
+
request: 'the document',
|
|
85
118
|
operation,
|
|
86
119
|
context: requestContext,
|
|
87
120
|
baseDelayMs: BASE_BACKOFF_MS,
|
|
@@ -89,7 +122,33 @@ export class CongressDocumentsService {
|
|
|
89
122
|
isTransient: (error) => this.isRetryableError(error),
|
|
90
123
|
...(signal ? { signal } : {}),
|
|
91
124
|
});
|
|
92
|
-
|
|
125
|
+
const content = this.describeWindow(read.window, params);
|
|
126
|
+
/** A document the window covers to its end is never retained. */
|
|
127
|
+
if (content.nextOffset !== null)
|
|
128
|
+
this.bodyCache.insert(params.url, read.body);
|
|
129
|
+
return content;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Serve a window from a cached body: the decoder and extractor a fetch feeds,
|
|
133
|
+
* given the body in slices with a macrotask between them, checking the
|
|
134
|
+
* caller's signal at each one.
|
|
135
|
+
*/
|
|
136
|
+
async replayWindow(body, params, signal) {
|
|
137
|
+
const decoder = new TextDecoder('utf-8');
|
|
138
|
+
const extractor = createStreamingExtractor({
|
|
139
|
+
characterLimit: params.characterLimit,
|
|
140
|
+
characterOffset: params.characterOffset,
|
|
141
|
+
});
|
|
142
|
+
for (let start = 0; start < body.byteLength; start += REPLAY_SLICE_BYTES) {
|
|
143
|
+
if (start > 0)
|
|
144
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
145
|
+
if (signal?.aborted)
|
|
146
|
+
throw requestCancelled('The document read was cancelled.');
|
|
147
|
+
const slice = body.subarray(start, start + REPLAY_SLICE_BYTES);
|
|
148
|
+
extractor.push(decoder.decode(slice, { stream: true }));
|
|
149
|
+
}
|
|
150
|
+
extractor.push(decoder.decode());
|
|
151
|
+
return extractor.finish();
|
|
93
152
|
}
|
|
94
153
|
/** Describe the extracted `[offset, offset + limit)` window and what remains. */
|
|
95
154
|
describeWindow(window, params) {
|
|
@@ -131,13 +190,17 @@ export class CongressDocumentsService {
|
|
|
131
190
|
});
|
|
132
191
|
}
|
|
133
192
|
}
|
|
134
|
-
|
|
193
|
+
/**
|
|
194
|
+
* One attempt. `attempt.signal` carries both the caller's abort and the call
|
|
195
|
+
* budget, so either ends an exchange already in flight, body included.
|
|
196
|
+
*/
|
|
197
|
+
async doFetch(params, requestContext, attempt) {
|
|
135
198
|
let response;
|
|
136
199
|
try {
|
|
137
|
-
response = await fetchWithTimeout(params.url,
|
|
200
|
+
response = await fetchWithTimeout(params.url, attempt.timeoutMs, requestContext, {
|
|
138
201
|
headers: { Accept: 'text/html, application/xml, text/plain, */*' },
|
|
139
202
|
expectedStatuses: [404],
|
|
140
|
-
|
|
203
|
+
signal: attempt.signal,
|
|
141
204
|
});
|
|
142
205
|
}
|
|
143
206
|
catch (error) {
|
|
@@ -195,12 +258,14 @@ export class CongressDocumentsService {
|
|
|
195
258
|
* Extract the requested character window as the body streams, under a hard
|
|
196
259
|
* byte budget that cancels the stream the moment it is exceeded.
|
|
197
260
|
*
|
|
198
|
-
*
|
|
199
|
-
* across a chunk boundary and the extractor carries its parse
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
261
|
+
* Only the window is extracted into memory: the decoder carries a partial
|
|
262
|
+
* character across a chunk boundary and the extractor carries its parse
|
|
263
|
+
* state. The raw chunks are also captured for the body cache, up to its entry
|
|
264
|
+
* ceiling and no further, so a body past that ceiling keeps the read's live
|
|
265
|
+
* set near the window's own size. Transient allocation still scales with the
|
|
266
|
+
* body — peak RSS is higher than a buffered read of the same document — but
|
|
267
|
+
* it is garbage, not live, so it is concurrent reads rather than one large
|
|
268
|
+
* read that the ceiling has to survive.
|
|
204
269
|
*/
|
|
205
270
|
async readWindow(response, params) {
|
|
206
271
|
const reader = response.body?.getReader();
|
|
@@ -209,6 +274,7 @@ export class CongressDocumentsService {
|
|
|
209
274
|
characterLimit: params.characterLimit,
|
|
210
275
|
characterOffset: params.characterOffset,
|
|
211
276
|
});
|
|
277
|
+
const body = this.bodyCache.capture();
|
|
212
278
|
let bytes = 0;
|
|
213
279
|
if (reader) {
|
|
214
280
|
for (;;) {
|
|
@@ -222,6 +288,7 @@ export class CongressDocumentsService {
|
|
|
222
288
|
await reader.cancel().catch(() => undefined);
|
|
223
289
|
throw this.tooLarge({ bytesRead: bytes });
|
|
224
290
|
}
|
|
291
|
+
body.add(value);
|
|
225
292
|
extractor.push(decoder.decode(value, { stream: true }));
|
|
226
293
|
}
|
|
227
294
|
}
|
|
@@ -232,17 +299,21 @@ export class CongressDocumentsService {
|
|
|
232
299
|
});
|
|
233
300
|
}
|
|
234
301
|
extractor.push(decoder.decode());
|
|
235
|
-
return extractor.finish();
|
|
302
|
+
return { window: extractor.finish(), body };
|
|
236
303
|
}
|
|
237
304
|
/**
|
|
238
305
|
* A body that dies partway through is the transport failing, not a malformed
|
|
239
|
-
* document — the same classification a connection that never opened gets.
|
|
306
|
+
* document — the same classification a connection that never opened gets. A
|
|
307
|
+
* caller abort mid-body stays the cancellation it is.
|
|
240
308
|
*/
|
|
241
309
|
async readChunk(reader) {
|
|
242
310
|
try {
|
|
243
311
|
return await reader.read();
|
|
244
312
|
}
|
|
245
313
|
catch (error) {
|
|
314
|
+
if (error instanceof McpError && error.code === JsonRpcErrorCode.RequestCancelled) {
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
246
317
|
throw serviceUnavailable('The document body from Congress.gov ended before it was complete.', { reason: DOCUMENT_FETCH_FAILED }, { cause: error });
|
|
247
318
|
}
|
|
248
319
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"congress-documents-service.js","sourceRoot":"","sources":["../../../src/services/congress-documents/congress-documents-service.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"congress-documents-service.js","sourceRoot":"","sources":["../../../src/services/congress-documents/congress-documents-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-local cache of decompressed document bodies, so a walk
|
|
3
|
+
* through a multi-window document fetches it once per TTL instead of once per
|
|
4
|
+
* window.
|
|
5
|
+
*
|
|
6
|
+
* Every window streams the whole body, because `totalCharacters` is known only
|
|
7
|
+
* at the end of it. Caching the bytes rather than extracted text keeps the
|
|
8
|
+
* extractor and its input unchanged — a window replayed from cache is the
|
|
9
|
+
* window a fresh fetch returns — and holds each body at one byte per byte with
|
|
10
|
+
* nothing sliced out of it to pin a larger parent.
|
|
11
|
+
*
|
|
12
|
+
* One cache serves every tenant: each body is a public document fetched without
|
|
13
|
+
* credentials from a URL the server resolved and allowlisted itself.
|
|
14
|
+
*
|
|
15
|
+
* @module services/congress-documents/document-body-cache
|
|
16
|
+
*/
|
|
17
|
+
/** Bytes all entries together may hold; the least recently used entries go first. */
|
|
18
|
+
export declare const BODY_CACHE_MAX_BYTES = 64000000;
|
|
19
|
+
/**
|
|
20
|
+
* Largest body one entry holds. Clears the largest known body (116th Congress
|
|
21
|
+
* H.R. 133 enrolled as XML, 9,812,888 bytes); a body past it is read as before
|
|
22
|
+
* and never cached.
|
|
23
|
+
*/
|
|
24
|
+
export declare const BODY_CACHE_MAX_ENTRY_BYTES = 16000000;
|
|
25
|
+
/** How long an entry serves, from its insert — inside congress.gov's own `max-age=1800`. */
|
|
26
|
+
export declare const BODY_CACHE_TTL_MS: number;
|
|
27
|
+
/** The bounds one cache enforces. */
|
|
28
|
+
export interface BodyCacheLimits {
|
|
29
|
+
maxBytes: number;
|
|
30
|
+
maxEntryBytes: number;
|
|
31
|
+
ttlMs: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The chunks of one body as a fetch streams them, from
|
|
35
|
+
* {@link DocumentBodyCache.capture}. Kept until the body passes the entry
|
|
36
|
+
* ceiling, then dropped, after which nothing more is kept.
|
|
37
|
+
*/
|
|
38
|
+
export declare class BodyCapture {
|
|
39
|
+
private readonly maxBytes;
|
|
40
|
+
private byteLength;
|
|
41
|
+
private chunks;
|
|
42
|
+
constructor(maxBytes: number);
|
|
43
|
+
/** Record the next chunk of the body. */
|
|
44
|
+
add(chunk: Uint8Array): void;
|
|
45
|
+
/** The whole body as one buffer it owns, or undefined once it passed the ceiling. */
|
|
46
|
+
toBody(): Uint8Array | undefined;
|
|
47
|
+
}
|
|
48
|
+
/** LRU over decompressed document bodies, keyed by the server-resolved URL. */
|
|
49
|
+
export declare class DocumentBodyCache {
|
|
50
|
+
private readonly limits;
|
|
51
|
+
private readonly entries;
|
|
52
|
+
private totalBytes;
|
|
53
|
+
constructor(limits?: BodyCacheLimits);
|
|
54
|
+
/** Start capturing a body as it streams, under this cache's entry ceiling. */
|
|
55
|
+
capture(): BodyCapture;
|
|
56
|
+
/** The body cached for `url`, now the most recently used, or undefined when absent or expired. */
|
|
57
|
+
get(url: string): Uint8Array | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Cache a captured body as one owned buffer, replacing any entry for `url`
|
|
60
|
+
* and evicting expired, then least recently used, entries until it fits. A
|
|
61
|
+
* capture dropped at the entry ceiling inserts nothing.
|
|
62
|
+
*/
|
|
63
|
+
insert(url: string, capture: BodyCapture): void;
|
|
64
|
+
private remove;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=document-body-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-body-cache.d.ts","sourceRoot":"","sources":["../../../src/services/congress-documents/document-body-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,qFAAqF;AACrF,eAAO,MAAM,oBAAoB,WAAa,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,WAAa,CAAC;AAErD,4FAA4F;AAC5F,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAE7C,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,qBAAa,WAAW;IAIV,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAHrC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAA2B;IAEzC,YAA6B,QAAQ,EAAE,MAAM,EAAI;IAEjD,yCAAyC;IACzC,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAK3B;IAED,qFAAqF;IACrF,MAAM,IAAI,UAAU,GAAG,SAAS,CAS/B;CACF;AAOD,+EAA+E;AAC/E,qBAAa,iBAAiB;IAK1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,UAAU,CAAK;IAEvB,YACmB,MAAM,GAAE,eAIxB,EACC;IAEJ,8EAA8E;IAC9E,OAAO,IAAI,WAAW,CAErB;IAED,kGAAkG;IAClG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAUvC;IAED;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAc9C;IAED,OAAO,CAAC,MAAM;CAMf"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Process-local cache of decompressed document bodies, so a walk
|
|
3
|
+
* through a multi-window document fetches it once per TTL instead of once per
|
|
4
|
+
* window.
|
|
5
|
+
*
|
|
6
|
+
* Every window streams the whole body, because `totalCharacters` is known only
|
|
7
|
+
* at the end of it. Caching the bytes rather than extracted text keeps the
|
|
8
|
+
* extractor and its input unchanged — a window replayed from cache is the
|
|
9
|
+
* window a fresh fetch returns — and holds each body at one byte per byte with
|
|
10
|
+
* nothing sliced out of it to pin a larger parent.
|
|
11
|
+
*
|
|
12
|
+
* One cache serves every tenant: each body is a public document fetched without
|
|
13
|
+
* credentials from a URL the server resolved and allowlisted itself.
|
|
14
|
+
*
|
|
15
|
+
* @module services/congress-documents/document-body-cache
|
|
16
|
+
*/
|
|
17
|
+
/** Bytes all entries together may hold; the least recently used entries go first. */
|
|
18
|
+
export const BODY_CACHE_MAX_BYTES = 64_000_000;
|
|
19
|
+
/**
|
|
20
|
+
* Largest body one entry holds. Clears the largest known body (116th Congress
|
|
21
|
+
* H.R. 133 enrolled as XML, 9,812,888 bytes); a body past it is read as before
|
|
22
|
+
* and never cached.
|
|
23
|
+
*/
|
|
24
|
+
export const BODY_CACHE_MAX_ENTRY_BYTES = 16_000_000;
|
|
25
|
+
/** How long an entry serves, from its insert — inside congress.gov's own `max-age=1800`. */
|
|
26
|
+
export const BODY_CACHE_TTL_MS = 10 * 60_000;
|
|
27
|
+
/**
|
|
28
|
+
* The chunks of one body as a fetch streams them, from
|
|
29
|
+
* {@link DocumentBodyCache.capture}. Kept until the body passes the entry
|
|
30
|
+
* ceiling, then dropped, after which nothing more is kept.
|
|
31
|
+
*/
|
|
32
|
+
export class BodyCapture {
|
|
33
|
+
maxBytes;
|
|
34
|
+
byteLength = 0;
|
|
35
|
+
chunks = [];
|
|
36
|
+
constructor(maxBytes) {
|
|
37
|
+
this.maxBytes = maxBytes;
|
|
38
|
+
}
|
|
39
|
+
/** Record the next chunk of the body. */
|
|
40
|
+
add(chunk) {
|
|
41
|
+
if (this.chunks === null)
|
|
42
|
+
return;
|
|
43
|
+
this.byteLength += chunk.byteLength;
|
|
44
|
+
if (this.byteLength > this.maxBytes)
|
|
45
|
+
this.chunks = null;
|
|
46
|
+
else
|
|
47
|
+
this.chunks.push(chunk);
|
|
48
|
+
}
|
|
49
|
+
/** The whole body as one buffer it owns, or undefined once it passed the ceiling. */
|
|
50
|
+
toBody() {
|
|
51
|
+
if (this.chunks === null)
|
|
52
|
+
return;
|
|
53
|
+
const body = new Uint8Array(this.byteLength);
|
|
54
|
+
let offset = 0;
|
|
55
|
+
for (const chunk of this.chunks) {
|
|
56
|
+
body.set(chunk, offset);
|
|
57
|
+
offset += chunk.byteLength;
|
|
58
|
+
}
|
|
59
|
+
return body;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** LRU over decompressed document bodies, keyed by the server-resolved URL. */
|
|
63
|
+
export class DocumentBodyCache {
|
|
64
|
+
limits;
|
|
65
|
+
entries = new Map();
|
|
66
|
+
totalBytes = 0;
|
|
67
|
+
constructor(limits = {
|
|
68
|
+
maxBytes: BODY_CACHE_MAX_BYTES,
|
|
69
|
+
maxEntryBytes: BODY_CACHE_MAX_ENTRY_BYTES,
|
|
70
|
+
ttlMs: BODY_CACHE_TTL_MS,
|
|
71
|
+
}) {
|
|
72
|
+
this.limits = limits;
|
|
73
|
+
}
|
|
74
|
+
/** Start capturing a body as it streams, under this cache's entry ceiling. */
|
|
75
|
+
capture() {
|
|
76
|
+
return new BodyCapture(this.limits.maxEntryBytes);
|
|
77
|
+
}
|
|
78
|
+
/** The body cached for `url`, now the most recently used, or undefined when absent or expired. */
|
|
79
|
+
get(url) {
|
|
80
|
+
const entry = this.entries.get(url);
|
|
81
|
+
if (!entry)
|
|
82
|
+
return;
|
|
83
|
+
this.entries.delete(url);
|
|
84
|
+
if (entry.expiresAt <= Date.now()) {
|
|
85
|
+
this.totalBytes -= entry.body.byteLength;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.entries.set(url, entry);
|
|
89
|
+
return entry.body;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Cache a captured body as one owned buffer, replacing any entry for `url`
|
|
93
|
+
* and evicting expired, then least recently used, entries until it fits. A
|
|
94
|
+
* capture dropped at the entry ceiling inserts nothing.
|
|
95
|
+
*/
|
|
96
|
+
insert(url, capture) {
|
|
97
|
+
const body = capture.toBody();
|
|
98
|
+
if (body === undefined)
|
|
99
|
+
return;
|
|
100
|
+
this.remove(url);
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
for (const [key, entry] of this.entries) {
|
|
103
|
+
if (entry.expiresAt <= now)
|
|
104
|
+
this.remove(key);
|
|
105
|
+
}
|
|
106
|
+
for (const key of this.entries.keys()) {
|
|
107
|
+
if (this.totalBytes + body.byteLength <= this.limits.maxBytes)
|
|
108
|
+
break;
|
|
109
|
+
this.remove(key);
|
|
110
|
+
}
|
|
111
|
+
this.entries.set(url, { body, expiresAt: now + this.limits.ttlMs });
|
|
112
|
+
this.totalBytes += body.byteLength;
|
|
113
|
+
}
|
|
114
|
+
remove(url) {
|
|
115
|
+
const entry = this.entries.get(url);
|
|
116
|
+
if (!entry)
|
|
117
|
+
return;
|
|
118
|
+
this.entries.delete(url);
|
|
119
|
+
this.totalBytes -= entry.body.byteLength;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=document-body-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-body-cache.js","sourceRoot":"","sources":["../../../src/services/congress-documents/document-body-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,qFAAqF;AACrF,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,UAAU,CAAC;AAErD,4FAA4F;AAC5F,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,MAAM,CAAC;AAS7C;;;;GAIG;AACH,MAAM,OAAO,WAAW;IAIO,QAAQ;IAH7B,UAAU,GAAG,CAAC,CAAC;IACf,MAAM,GAAwB,EAAE,CAAC;IAEzC,YAA6B,QAAgB;wBAAhB,QAAQ;IAAW,CAAC;IAEjD,yCAAyC;IACzC,GAAG,CAAC,KAAiB;QACnB,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI;YAAE,OAAO;QACjC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC;QACpC,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;;YACnD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,qFAAqF;IACrF,MAAM;QACJ,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI;YAAE,OAAO;QACjC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAOD,+EAA+E;AAC/E,MAAM,OAAO,iBAAiB;IAKT,MAAM;IAJR,OAAO,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC5C,UAAU,GAAG,CAAC,CAAC;IAEvB,YACmB,MAAM,GAAoB;QACzC,QAAQ,EAAE,oBAAoB;QAC9B,aAAa,EAAE,0BAA0B;QACzC,KAAK,EAAE,iBAAiB;KACzB;sBAJgB,MAAM;IAKtB,CAAC;IAEJ,8EAA8E;IAC9E,OAAO;QACL,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACpD,CAAC;IAED,kGAAkG;IAClG,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;YACzC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,GAAW,EAAE,OAAoB;QACtC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC9B,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO;QAC/B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG;gBAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAAE,MAAM;YACrE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC;IACrC,CAAC;IAEO,MAAM,CAAC,GAAW;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -9,11 +9,14 @@
|
|
|
9
9
|
* Merge order matters: the framework upsert writes every declared column for each
|
|
10
10
|
* record, so a partial (summary-only) upsert would null the title. The summaries
|
|
11
11
|
* are therefore loaded into a per-congress map first, then attached as each full
|
|
12
|
-
* bill row is emitted.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* bill row is emitted. Every sync re-walks a congress's whole summaries list, so a
|
|
13
|
+
* re-emitted bill never loses a previously-stored summary: the list is requested
|
|
14
|
+
* from the congress's first day with no end, because without `fromDateTime`
|
|
15
|
+
* Congress.gov returns only the last day's summaries, and summaries keep being
|
|
16
|
+
* rewritten long after their congress ends. The durable checkpoint is the bills'
|
|
17
|
+
* `updateDate` high-water mark across every congress, persisted only once the
|
|
18
|
+
* whole walk finishes; refresh re-scans bills from it inclusively
|
|
19
|
+
* (`sort=updateDate asc`), and the upsert makes the overlap harmless.
|
|
17
20
|
* @module services/congress-mirror/ingest
|
|
18
21
|
*/
|
|
19
22
|
import type { SyncGenerator } from '@cyanheads/mcp-ts-core/mirror';
|
|
@@ -23,8 +26,11 @@ export type MirrorApi = Pick<CongressApiService, 'listBills' | 'listSummaries'>;
|
|
|
23
26
|
/**
|
|
24
27
|
* Build the Congress bill ingester. The returned generator walks the configured
|
|
25
28
|
* congresses; for each, it loads the summary map, then streams bill pages
|
|
26
|
-
* (`sort=updateDate asc`) as full merged rows
|
|
27
|
-
*
|
|
29
|
+
* (`sort=updateDate asc`) as full merged rows. The durable checkpoint — the max
|
|
30
|
+
* `updateDate` seen across every congress — rides only the final page, so a run
|
|
31
|
+
* that fails partway leaves the stored checkpoint where it started: a mid-walk
|
|
32
|
+
* checkpoint could already sit past the unvisited updates of a later congress,
|
|
33
|
+
* and the next refresh would skip them.
|
|
28
34
|
*
|
|
29
35
|
* @param getApi - Accessor for the Congress API service (injectable for tests).
|
|
30
36
|
* @param congresses - Congress numbers to mirror.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../../src/services/congress-mirror/ingest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../../src/services/congress-mirror/ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAGV,aAAa,EAEd,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAO1F,yFAAyF;AACzF,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC;AAwHhF;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,SAAS,EACvB,UAAU,EAAE,MAAM,EAAE,GACnB,aAAa,CAqDf"}
|
|
@@ -9,14 +9,18 @@
|
|
|
9
9
|
* Merge order matters: the framework upsert writes every declared column for each
|
|
10
10
|
* record, so a partial (summary-only) upsert would null the title. The summaries
|
|
11
11
|
* are therefore loaded into a per-congress map first, then attached as each full
|
|
12
|
-
* bill row is emitted.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* bill row is emitted. Every sync re-walks a congress's whole summaries list, so a
|
|
13
|
+
* re-emitted bill never loses a previously-stored summary: the list is requested
|
|
14
|
+
* from the congress's first day with no end, because without `fromDateTime`
|
|
15
|
+
* Congress.gov returns only the last day's summaries, and summaries keep being
|
|
16
|
+
* rewritten long after their congress ends. The durable checkpoint is the bills'
|
|
17
|
+
* `updateDate` high-water mark across every congress, persisted only once the
|
|
18
|
+
* whole walk finishes; refresh re-scans bills from it inclusively
|
|
19
|
+
* (`sort=updateDate asc`), and the upsert makes the overlap harmless.
|
|
17
20
|
* @module services/congress-mirror/ingest
|
|
18
21
|
*/
|
|
19
22
|
import { logger } from '@cyanheads/mcp-ts-core/utils';
|
|
23
|
+
import { congressFirstYear } from '../../utils/congress-calendar.js';
|
|
20
24
|
import { htmlToPlainText } from './normalize.js';
|
|
21
25
|
/** Congress.gov list endpoints cap the page size at 250 (confirmed live). */
|
|
22
26
|
const PAGE_SIZE = 250;
|
|
@@ -59,16 +63,25 @@ function deriveBillId(congress, billType, billNumber) {
|
|
|
59
63
|
function toFromDateTime(checkpoint) {
|
|
60
64
|
return /^\d{4}-\d{2}-\d{2}$/.test(checkpoint) ? `${checkpoint}T00:00:00Z` : checkpoint;
|
|
61
65
|
}
|
|
66
|
+
/** January 1 of a congress's first year as a `fromDateTime` that no summary of its bills predates. */
|
|
67
|
+
function congressStartDateTime(congress) {
|
|
68
|
+
return `${congressFirstYear(congress)}-01-01T00:00:00Z`;
|
|
69
|
+
}
|
|
62
70
|
/**
|
|
63
71
|
* Page the CRS summaries list for one congress into a `billId → plain-text
|
|
64
72
|
* summary` map, keeping the latest version per bill (by summary update/action
|
|
65
|
-
* stamp).
|
|
73
|
+
* stamp). The window opens on the congress's first day with no end. The walk
|
|
74
|
+
* keeps the upstream newest-first order: a summary updated mid-walk moves to the
|
|
75
|
+
* front and at worst repeats a row, where oldest-first it would move to the end
|
|
76
|
+
* and the row crossing the next page boundary would be skipped. Summaries ship as
|
|
77
|
+
* HTML and are stripped to plain text before storage.
|
|
66
78
|
*/
|
|
67
79
|
async function buildSummaryMap(api, congress, signal) {
|
|
68
80
|
const latest = new Map();
|
|
81
|
+
const fromDateTime = congressStartDateTime(congress);
|
|
69
82
|
let offset = 0;
|
|
70
83
|
while (!signal.aborted) {
|
|
71
|
-
const result = await api.listSummaries({ congress, limit: PAGE_SIZE, offset });
|
|
84
|
+
const result = await api.listSummaries({ congress, limit: PAGE_SIZE, offset, fromDateTime });
|
|
72
85
|
const rows = result.data;
|
|
73
86
|
if (rows.length === 0)
|
|
74
87
|
break;
|
|
@@ -124,8 +137,11 @@ function toBillRow(raw, fallbackCongress, summaries) {
|
|
|
124
137
|
/**
|
|
125
138
|
* Build the Congress bill ingester. The returned generator walks the configured
|
|
126
139
|
* congresses; for each, it loads the summary map, then streams bill pages
|
|
127
|
-
* (`sort=updateDate asc`) as full merged rows
|
|
128
|
-
*
|
|
140
|
+
* (`sort=updateDate asc`) as full merged rows. The durable checkpoint — the max
|
|
141
|
+
* `updateDate` seen across every congress — rides only the final page, so a run
|
|
142
|
+
* that fails partway leaves the stored checkpoint where it started: a mid-walk
|
|
143
|
+
* checkpoint could already sit past the unvisited updates of a later congress,
|
|
144
|
+
* and the next refresh would skip them.
|
|
129
145
|
*
|
|
130
146
|
* @param getApi - Accessor for the Congress API service (injectable for tests).
|
|
131
147
|
* @param congresses - Congress numbers to mirror.
|
|
@@ -135,6 +151,8 @@ export function createCongressBillIngester(getApi, congresses) {
|
|
|
135
151
|
const api = getApi();
|
|
136
152
|
const fromDateTime = mode === 'refresh' && checkpoint ? toFromDateTime(checkpoint) : undefined;
|
|
137
153
|
let maxUpdate = checkpoint;
|
|
154
|
+
// Each page is yielded one fetch late, so the last one can carry the checkpoint.
|
|
155
|
+
let held;
|
|
138
156
|
logger.info(`Congress bill mirror sync starting (mode=${mode}, congresses=${congresses.join(',')}${fromDateTime ? `, since=${fromDateTime}` : ''})`);
|
|
139
157
|
for (const congress of congresses) {
|
|
140
158
|
if (signal.aborted)
|
|
@@ -167,13 +185,18 @@ export function createCongressBillIngester(getApi, congresses) {
|
|
|
167
185
|
maxUpdate = updated;
|
|
168
186
|
}
|
|
169
187
|
billsMirrored += records.length;
|
|
170
|
-
|
|
188
|
+
if (held)
|
|
189
|
+
yield { records: held };
|
|
190
|
+
held = records;
|
|
171
191
|
if (rows.length < PAGE_SIZE || result.pagination.nextOffset == null)
|
|
172
192
|
break;
|
|
173
193
|
offset += PAGE_SIZE;
|
|
174
194
|
}
|
|
175
195
|
logger.info(`Congress ${congress}: ${billsMirrored} bills mirrored`);
|
|
176
196
|
}
|
|
197
|
+
if (held && !signal.aborted) {
|
|
198
|
+
yield { records: held, ...(maxUpdate ? { checkpoint: maxUpdate } : {}) };
|
|
199
|
+
}
|
|
177
200
|
};
|
|
178
201
|
}
|
|
179
202
|
//# sourceMappingURL=ingest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../../src/services/congress-mirror/ingest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../../src/services/congress-mirror/ingest.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/services/congress-mirror/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/services/congress-mirror/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAa,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtF,0DAA0D;AAC1D,eAAO,MAAM,WAAW,UAAU,CAAC;AAgBnC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CA2BjE"}
|