2024-03-11 18:50:34 +05:30
|
|
|
import type { PeerId } from "@libp2p/interface";
|
2024-06-19 01:52:16 -04:00
|
|
|
import { ConnectionManager, LightPushCore } from "@waku/core";
|
2024-03-11 18:50:34 +05:30
|
|
|
import {
|
|
|
|
|
Failure,
|
|
|
|
|
type IEncoder,
|
|
|
|
|
ILightPushSDK,
|
|
|
|
|
type IMessage,
|
|
|
|
|
type Libp2p,
|
|
|
|
|
type ProtocolCreateOptions,
|
2024-03-12 16:40:08 +05:30
|
|
|
ProtocolError,
|
2024-07-03 12:09:34 +05:30
|
|
|
ProtocolUseOptions,
|
|
|
|
|
SDKProtocolResult
|
2024-03-11 18:50:34 +05:30
|
|
|
} from "@waku/interfaces";
|
|
|
|
|
import { ensurePubsubTopicIsConfigured, Logger } from "@waku/utils";
|
|
|
|
|
|
2024-09-17 11:34:59 +05:30
|
|
|
import { ReliabilityMonitorManager } from "../../reliability_monitor/index.js";
|
|
|
|
|
import { SenderReliabilityMonitor } from "../../reliability_monitor/sender.js";
|
|
|
|
|
import { BaseProtocolSDK } from "../base_protocol.js";
|
2024-03-11 18:50:34 +05:30
|
|
|
|
|
|
|
|
const log = new Logger("sdk:light-push");
|
|
|
|
|
|
2024-04-19 17:20:34 +05:30
|
|
|
class LightPushSDK extends BaseProtocolSDK implements ILightPushSDK {
|
2024-03-11 18:50:34 +05:30
|
|
|
public readonly protocol: LightPushCore;
|
|
|
|
|
|
2024-09-17 11:34:59 +05:30
|
|
|
private readonly reliabilityMonitor: SenderReliabilityMonitor;
|
|
|
|
|
|
2024-07-19 15:58:17 +05:30
|
|
|
public constructor(
|
2024-06-19 01:52:16 -04:00
|
|
|
connectionManager: ConnectionManager,
|
|
|
|
|
libp2p: Libp2p,
|
|
|
|
|
options?: ProtocolCreateOptions
|
|
|
|
|
) {
|
2024-08-13 05:23:20 +05:30
|
|
|
super(
|
|
|
|
|
new LightPushCore(connectionManager.configuredPubsubTopics, libp2p),
|
|
|
|
|
connectionManager,
|
|
|
|
|
{
|
|
|
|
|
numPeersToUse: options?.numPeersToUse
|
|
|
|
|
}
|
|
|
|
|
);
|
2024-06-19 01:52:16 -04:00
|
|
|
|
2024-09-17 11:34:59 +05:30
|
|
|
this.reliabilityMonitor = ReliabilityMonitorManager.createSenderMonitor(
|
|
|
|
|
this.renewPeer.bind(this)
|
|
|
|
|
);
|
|
|
|
|
|
2024-06-19 01:52:16 -04:00
|
|
|
this.protocol = this.core as LightPushCore;
|
2024-03-11 18:50:34 +05:30
|
|
|
}
|
|
|
|
|
|
2024-07-19 15:58:17 +05:30
|
|
|
public async send(
|
2024-06-19 01:52:16 -04:00
|
|
|
encoder: IEncoder,
|
|
|
|
|
message: IMessage,
|
2024-07-03 12:09:34 +05:30
|
|
|
_options?: ProtocolUseOptions
|
2024-06-19 01:52:16 -04:00
|
|
|
): Promise<SDKProtocolResult> {
|
|
|
|
|
const options = {
|
|
|
|
|
autoRetry: true,
|
|
|
|
|
..._options
|
2024-07-03 12:09:34 +05:30
|
|
|
} as ProtocolUseOptions;
|
2024-06-19 01:52:16 -04:00
|
|
|
|
2024-03-11 18:50:34 +05:30
|
|
|
const successes: PeerId[] = [];
|
|
|
|
|
const failures: Failure[] = [];
|
|
|
|
|
|
|
|
|
|
const { pubsubTopic } = encoder;
|
|
|
|
|
try {
|
|
|
|
|
ensurePubsubTopicIsConfigured(pubsubTopic, this.protocol.pubsubTopics);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
log.error("Failed to send waku light push: pubsub topic not configured");
|
|
|
|
|
return {
|
|
|
|
|
failures: [
|
|
|
|
|
{
|
2024-03-12 16:40:08 +05:30
|
|
|
error: ProtocolError.TOPIC_NOT_CONFIGURED
|
2024-03-11 18:50:34 +05:30
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
successes: []
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 01:52:16 -04:00
|
|
|
const hasPeers = await this.hasPeers(options);
|
|
|
|
|
if (!hasPeers) {
|
2024-03-11 18:50:34 +05:30
|
|
|
return {
|
|
|
|
|
successes,
|
2024-06-19 01:52:16 -04:00
|
|
|
failures: [
|
|
|
|
|
{
|
|
|
|
|
error: ProtocolError.NO_PEER_AVAILABLE
|
|
|
|
|
}
|
|
|
|
|
]
|
2024-03-11 18:50:34 +05:30
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 01:52:16 -04:00
|
|
|
const sendPromises = this.connectedPeers.map((peer) =>
|
2024-03-11 18:50:34 +05:30
|
|
|
this.protocol.send(encoder, message, peer)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const results = await Promise.allSettled(sendPromises);
|
|
|
|
|
|
|
|
|
|
for (const result of results) {
|
|
|
|
|
if (result.status === "fulfilled") {
|
|
|
|
|
const { failure, success } = result.value;
|
|
|
|
|
if (success) {
|
|
|
|
|
successes.push(success);
|
|
|
|
|
}
|
|
|
|
|
if (failure) {
|
2024-09-17 11:34:59 +05:30
|
|
|
failures.push(failure);
|
2024-06-19 01:52:16 -04:00
|
|
|
if (failure.peerId) {
|
2024-09-17 11:34:59 +05:30
|
|
|
const peer = this.connectedPeers.find((connectedPeer) =>
|
|
|
|
|
connectedPeer.id.equals(failure.peerId)
|
|
|
|
|
);
|
|
|
|
|
if (peer) {
|
|
|
|
|
log.info(`
|
|
|
|
|
Failed to send message to peer ${failure.peerId}.
|
|
|
|
|
Retrying the message with the same peer in the background.
|
|
|
|
|
If this fails, the peer will be renewed.
|
|
|
|
|
`);
|
|
|
|
|
void this.reliabilityMonitor.attemptRetriesOrRenew(
|
|
|
|
|
failure.peerId,
|
|
|
|
|
() => this.protocol.send(encoder, message, peer)
|
|
|
|
|
);
|
2024-07-10 15:34:16 +05:30
|
|
|
}
|
2024-06-19 01:52:16 -04:00
|
|
|
}
|
2024-03-11 18:50:34 +05:30
|
|
|
}
|
|
|
|
|
} else {
|
2024-08-29 11:20:19 +02:00
|
|
|
log.error("Failed unexpectedly while sending:", result.reason);
|
2024-03-12 16:40:08 +05:30
|
|
|
failures.push({ error: ProtocolError.GENERIC_FAIL });
|
2024-03-11 18:50:34 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
successes,
|
|
|
|
|
failures
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function wakuLightPush(
|
2024-06-19 01:52:16 -04:00
|
|
|
connectionManager: ConnectionManager,
|
2024-03-11 18:50:34 +05:30
|
|
|
init: Partial<ProtocolCreateOptions> = {}
|
|
|
|
|
): (libp2p: Libp2p) => ILightPushSDK {
|
2024-06-19 01:52:16 -04:00
|
|
|
return (libp2p: Libp2p) => new LightPushSDK(connectionManager, libp2p, init);
|
2024-03-11 18:50:34 +05:30
|
|
|
}
|