MCPcopy Create free account
hub / github.com/EvoMap/evolver / ackDelivered

Method ackDelivered

src/proxy/sync/inbound.js:144–208  ·  view source on GitHub ↗
(channel = 'evomap-hub')

Source from the content-addressed store, hash-verified

142 }
143
144 async ackDelivered(channel = 'evomap-hub') {
145 const waitMs = this._hubUnreachableWaitMs();
146 if (waitMs > 0) {
147 return {
148 acked: 0,
149 error: 'hub_unreachable_backoff',
150 hubUnreachable: true,
151 retryAfterMs: waitMs,
152 };
153 }
154
155 const delivered = this.store.list({
156 type: '%',
157 direction: 'inbound',
158 status: 'delivered',
159 limit: 100,
160 }).filter(m => m.channel === channel);
161
162 if (delivered.length === 0) return { acked: 0 };
163
164 const endpoint = `${this.hubUrl}/a2a/mailbox/ack`;
165
166 try {
167 const senderId = this.store.getState('node_id');
168 // Round-8 (§21.5): drain the response body so the undici long-poll
169 // dispatcher pool is not leaked one socket per ack. ackDelivered
170 // is called every inbound poll cycle (default 1-10s); the
171 // pre-round-8 code captured no reference to res and never called
172 // .json()/.text()/body.cancel(), so each ack pinned a socket
173 // until GC. After a few minutes of activity the strict-pool was
174 // exhausted and proxy-mode heartbeats hung on next acquire --
175 // matches the "alive once then dead" user symptom in proxy mode.
176 const res = await hubFetch(endpoint, {
177 method: 'POST',
178 headers: this.getHeaders(),
179 body: JSON.stringify({ sender_id: senderId, message_ids: delivered.map(m => m.id) }),
180 signal: AbortSignal.timeout(10_000),
181 });
182 await throwIfHubUnreachableResponse(res, 'inbound ack');
183 this._recordHubReachable();
184 if (res.status === 403 || res.status === 401) {
185 const errText = await readHubResponseText(res).catch(() => 'unknown');
186 throw new AuthError(`Hub ${res.status}: ${sanitizeHubResponseForLog(errText)}`, res.status);
187 }
188 if (!res.ok) {
189 const errText = await readHubResponseText(res).catch(() => 'unknown');
190 throw new Error(`Hub returned ${res.status}: ${sanitizeHubResponseForLog(errText)}`);
191 }
192 await drainHubResponse(res);
193 return { acked: delivered.length };
194 } catch (err) {
195 if (err instanceof AuthError) throw err;
196 if (isHubUnreachableError(err)) {
197 const retryAfterMs = this._recordHubUnreachable(err);
198 return {
199 acked: 0,
200 error: 'hub_unreachable',
201 hubUnreachable: true,

Callers 1

_scheduleInboundMethod · 0.80

Calls 6

_hubUnreachableWaitMsMethod · 0.95
_recordHubReachableMethod · 0.95
_recordHubUnreachableMethod · 0.95
getStateMethod · 0.80
getHeadersMethod · 0.80
listMethod · 0.45

Tested by

no test coverage detected