bridge: a discovery request that arrives twice is answered once
A broker that mirrors another delivers every message twice, and the bridge answered both copies of a discovery request. A request is now remembered by its messageId for 60 s, as a directive is, and its copy is dropped with a log line. The messageId is read from the header of the Discover directive or from the request itself when that is the header alone. A request without a messageId is answered every time, as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
d12767f9a7
commit
29ee1a315e
9 changed files with 147 additions and 21 deletions
22
dist/cjs/dispatcher.js
vendored
22
dist/cjs/dispatcher.js
vendored
|
|
@ -163,6 +163,18 @@ class Dispatcher {
|
|||
this.deferralNoted.add(namespace);
|
||||
this.options.log(`warning: Amazon documents no DeferredResponse for ${namespace}, Alexa may not wait for the answer`);
|
||||
}
|
||||
/**
|
||||
* true for a message that came before, within REMEMBERED_MS: a broker that mirrors another delivers each message
|
||||
* twice. endpointId is "" for a message to the root, a discovery request.
|
||||
*/
|
||||
arrivedBefore(endpointId, messageId, now = Date.now()) {
|
||||
this.forget(now);
|
||||
const id = key(endpointId, messageId);
|
||||
if (this.arrived.has(id))
|
||||
return true;
|
||||
this.arrived.set(id, now);
|
||||
return false;
|
||||
}
|
||||
/** The text of a message on the directive topic of endpointId. Resolves when the handlers are done. */
|
||||
async dispatch(endpointId, text) {
|
||||
const { log, emit } = this.options;
|
||||
|
|
@ -182,13 +194,9 @@ class Dispatcher {
|
|||
const { namespace, name, messageId } = raw.header;
|
||||
const correlationToken = typeof raw.header.correlationToken === "string" ? raw.header.correlationToken : "";
|
||||
const receivedAt = Date.now();
|
||||
this.forget(receivedAt);
|
||||
if (typeof messageId === "string") {
|
||||
if (this.arrived.has(key(endpointId, messageId))) {
|
||||
log(`the directive ${messageId} for ${endpointId} is dropped: it arrived before`);
|
||||
return;
|
||||
}
|
||||
this.arrived.set(key(endpointId, messageId), receivedAt);
|
||||
if (typeof messageId === "string" && this.arrivedBefore(endpointId, messageId, receivedAt)) {
|
||||
log(`the directive ${messageId} for ${endpointId} is dropped: it arrived before`);
|
||||
return;
|
||||
}
|
||||
const device = this.options.getDevice(endpointId);
|
||||
if (!device) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue