Skip to content

Commit

Permalink
feat(metadata): use error codes (#1904)
Browse files Browse the repository at this point in the history
  • Loading branch information
danisharora099 committed Mar 12, 2024
1 parent 1e86c3d commit 1882023
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 72 deletions.
22 changes: 11 additions & 11 deletions packages/core/src/lib/light_push/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
IMessage,
Libp2p,
ProtocolCreateOptions,
SendError
ProtocolError
} from "@waku/interfaces";
import { PushResponse } from "@waku/proto";
import { isMessageSizeUnderCap } from "@waku/utils";
Expand All @@ -32,7 +32,7 @@ type PreparePushMessageResult =
}
| {
query: null;
error: SendError;
error: ProtocolError;
};

type CoreSendResult =
Expand Down Expand Up @@ -66,20 +66,20 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
try {
if (!message.payload || message.payload.length === 0) {
log.error("Failed to send waku light push: payload is empty");
return { query: null, error: SendError.EMPTY_PAYLOAD };
return { query: null, error: ProtocolError.EMPTY_PAYLOAD };
}

if (!(await isMessageSizeUnderCap(encoder, message))) {
log.error("Failed to send waku light push: message is bigger than 1MB");
return { query: null, error: SendError.SIZE_TOO_BIG };
return { query: null, error: ProtocolError.SIZE_TOO_BIG };
}

const protoMessage = await encoder.toProtoObj(message);
if (!protoMessage) {
log.error("Failed to encode to protoMessage, aborting push");
return {
query: null,
error: SendError.ENCODE_FAILED
error: ProtocolError.ENCODE_FAILED
};
}

Expand All @@ -90,7 +90,7 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {

return {
query: null,
error: SendError.GENERIC_FAIL
error: ProtocolError.GENERIC_FAIL
};
}
}
Expand Down Expand Up @@ -126,7 +126,7 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
return {
success: null,
failure: {
error: SendError.REMOTE_PEER_FAULT,
error: ProtocolError.REMOTE_PEER_FAULT,
peerId: peer.id
}
};
Expand All @@ -146,7 +146,7 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
return {
success: null,
failure: {
error: SendError.GENERIC_FAIL,
error: ProtocolError.GENERIC_FAIL,
peerId: peer.id
}
};
Expand All @@ -165,7 +165,7 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
return {
success: null,
failure: {
error: SendError.DECODE_FAILED,
error: ProtocolError.DECODE_FAILED,
peerId: peer.id
}
};
Expand All @@ -176,7 +176,7 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
return {
success: null,
failure: {
error: SendError.REMOTE_PEER_FAULT,
error: ProtocolError.REMOTE_PEER_FAULT,
peerId: peer.id
}
};
Expand All @@ -187,7 +187,7 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
return {
success: null,
failure: {
error: SendError.REMOTE_PEER_REJECTED,
error: ProtocolError.REMOTE_PEER_REJECTED,
peerId: peer.id
}
};
Expand Down
82 changes: 56 additions & 26 deletions packages/core/src/lib/metadata/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { PeerId } from "@libp2p/interface";
import { IncomingStreamData } from "@libp2p/interface";
import type {
IMetadata,
Libp2pComponents,
PeerIdStr,
ShardInfo
import {
type IMetadata,
type Libp2pComponents,
type PeerIdStr,
ProtocolError,
QueryResult,
type ShardInfo
} from "@waku/interfaces";
import { proto_metadata } from "@waku/proto";
import { encodeRelayShard, Logger, shardInfoToPubsubTopics } from "@waku/utils";
Expand All @@ -21,7 +23,7 @@ export const MetadataCodec = "/vac/waku/metadata/1.0.0";

class Metadata extends BaseProtocol implements IMetadata {
private libp2pComponents: Libp2pComponents;
handshakesConfirmed: Set<PeerIdStr> = new Set();
handshakesConfirmed: Map<PeerIdStr, ShardInfo> = new Map();

constructor(
public shardInfo: ShardInfo,
Expand Down Expand Up @@ -57,13 +59,13 @@ class Metadata extends BaseProtocol implements IMetadata {
async (source) => await all(source)
);

const remoteShardInfoResponse =
this.decodeMetadataResponse(encodedResponse);
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);

await this.savePeerShardInfo(
connection.remotePeer,
remoteShardInfoResponse
);
if (error) {
return;
}

await this.savePeerShardInfo(connection.remotePeer, shardInfo);
} catch (error) {
log.error("Error handling metadata request", error);
}
Expand All @@ -72,12 +74,15 @@ class Metadata extends BaseProtocol implements IMetadata {
/**
* Make a metadata query to a peer
*/
async query(peerId: PeerId): Promise<ShardInfo> {
async query(peerId: PeerId): Promise<QueryResult> {
const request = proto_metadata.WakuMetadataRequest.encode(this.shardInfo);

const peer = await this.peerStore.get(peerId);
if (!peer) {
throw new Error(`Peer ${peerId.toString()} not found`);
return {
shardInfo: null,
error: ProtocolError.NO_PEER_AVAILABLE
};
}

const stream = await this.getStream(peer);
Expand All @@ -90,22 +95,38 @@ class Metadata extends BaseProtocol implements IMetadata {
async (source) => await all(source)
);

const decodedResponse = this.decodeMetadataResponse(encodedResponse);
const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);

if (error) {
return {
shardInfo: null,
error
};
}

await this.savePeerShardInfo(peerId, decodedResponse);
await this.savePeerShardInfo(peerId, shardInfo);

return decodedResponse;
return {
shardInfo,
error: null
};
}

public async confirmOrAttemptHandshake(peerId: PeerId): Promise<void> {
if (this.handshakesConfirmed.has(peerId.toString())) return;

await this.query(peerId);
public async confirmOrAttemptHandshake(peerId: PeerId): Promise<QueryResult> {
const shardInfo = this.handshakesConfirmed.get(peerId.toString());
if (shardInfo) {
return {
shardInfo,
error: null
};
}

return;
return await this.query(peerId);
}

private decodeMetadataResponse(encodedResponse: Uint8ArrayList[]): ShardInfo {
private decodeMetadataResponse(
encodedResponse: Uint8ArrayList[]
): QueryResult {
const bytes = new Uint8ArrayList();

encodedResponse.forEach((chunk) => {
Expand All @@ -115,9 +136,18 @@ class Metadata extends BaseProtocol implements IMetadata {
bytes
) as ShardInfo;

if (!response) log.error("Error decoding metadata response");
if (!response) {
log.error("Error decoding metadata response");
return {
shardInfo: null,
error: ProtocolError.DECODE_FAILED
};
}

return response;
return {
shardInfo: response,
error: null
};
}

private async savePeerShardInfo(
Expand All @@ -131,7 +161,7 @@ class Metadata extends BaseProtocol implements IMetadata {
}
});

this.handshakesConfirmed.add(peerId.toString());
this.handshakesConfirmed.set(peerId.toString(), shardInfo);
}
}

Expand Down
20 changes: 17 additions & 3 deletions packages/interfaces/src/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import type { PeerId } from "@libp2p/interface";

import type { ShardInfo } from "./enr.js";
import type { IBaseProtocolCore, ShardingParams } from "./protocols.js";
import type {
IBaseProtocolCore,
ProtocolError,
ShardingParams
} from "./protocols.js";

export type QueryResult =
| {
shardInfo: ShardInfo;
error: null;
}
| {
shardInfo: null;
error: ProtocolError;
};

// IMetadata always has shardInfo defined while it is optionally undefined in IBaseProtocol
export interface IMetadata extends Omit<IBaseProtocolCore, "shardInfo"> {
shardInfo: ShardingParams;
confirmOrAttemptHandshake(peerId: PeerId): Promise<void>;
query(peerId: PeerId): Promise<ShardInfo | undefined>;
confirmOrAttemptHandshake(peerId: PeerId): Promise<QueryResult>;
query(peerId: PeerId): Promise<QueryResult>;
}
4 changes: 2 additions & 2 deletions packages/interfaces/src/protocols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export type Callback<T extends IDecodedMessage> = (
msg: T
) => void | Promise<void>;

export enum SendError {
export enum ProtocolError {
/** Could not determine the origin of the fault. Best to check connectivity and try again */
GENERIC_FAIL = "Generic error",
/**
Expand Down Expand Up @@ -150,7 +150,7 @@ export enum SendError {
}

export interface Failure {
error: SendError;
error: ProtocolError;
peerId?: PeerId;
}

Expand Down
8 changes: 4 additions & 4 deletions packages/relay/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {
IRelay,
Libp2p,
ProtocolCreateOptions,
ProtocolError,
PubsubTopic,
SendError,
SendResult
} from "@waku/interfaces";
import { isWireSizeUnderCap, toAsyncIterator } from "@waku/utils";
Expand Down Expand Up @@ -109,7 +109,7 @@ class Relay implements IRelay {
successes,
failures: [
{
error: SendError.TOPIC_NOT_CONFIGURED
error: ProtocolError.TOPIC_NOT_CONFIGURED
}
]
};
Expand All @@ -122,7 +122,7 @@ class Relay implements IRelay {
successes,
failures: [
{
error: SendError.ENCODE_FAILED
error: ProtocolError.ENCODE_FAILED
}
]
};
Expand All @@ -134,7 +134,7 @@ class Relay implements IRelay {
successes,
failures: [
{
error: SendError.SIZE_TOO_BIG
error: ProtocolError.SIZE_TOO_BIG
}
]
};
Expand Down
8 changes: 4 additions & 4 deletions packages/sdk/src/protocols/light_push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
type IMessage,
type Libp2p,
type ProtocolCreateOptions,
SendError,
ProtocolError,
type SendResult
} from "@waku/interfaces";
import { ensurePubsubTopicIsConfigured, Logger } from "@waku/utils";
Expand Down Expand Up @@ -37,7 +37,7 @@ export class LightPushSDK extends BaseProtocolSDK implements ILightPushSDK {
return {
failures: [
{
error: SendError.TOPIC_NOT_CONFIGURED
error: ProtocolError.TOPIC_NOT_CONFIGURED
}
],
successes: []
Expand All @@ -48,7 +48,7 @@ export class LightPushSDK extends BaseProtocolSDK implements ILightPushSDK {
if (!peers.length) {
return {
successes,
failures: [{ error: SendError.NO_PEER_AVAILABLE }]
failures: [{ error: ProtocolError.NO_PEER_AVAILABLE }]
};
}

Expand All @@ -69,7 +69,7 @@ export class LightPushSDK extends BaseProtocolSDK implements ILightPushSDK {
}
} else {
log.error("Failed to send message to peer", result.reason);
failures.push({ error: SendError.GENERIC_FAIL });
failures.push({ error: ProtocolError.GENERIC_FAIL });
// TODO: handle renewing faulty peers with new peers (https://github.com/waku-org/js-waku/issues/1463)
}
}
Expand Down
8 changes: 4 additions & 4 deletions packages/tests/tests/light-push/index.node.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
DefaultPubsubTopic,
IRateLimitProof,
LightNode,
SendError
ProtocolError
} from "@waku/interfaces";
import { utf8ToBytes } from "@waku/sdk";
import { expect } from "chai";
Expand Down Expand Up @@ -97,7 +97,7 @@ const runTests = (strictNodeCheck: boolean): void => {
expect(pushResponse.successes.length).to.eq(0);
console.log("validated 1");
expect(pushResponse.failures?.map((failure) => failure.error)).to.include(
SendError.EMPTY_PAYLOAD
ProtocolError.EMPTY_PAYLOAD
);
console.log("validated 2");
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq(
Expand Down Expand Up @@ -190,7 +190,7 @@ const runTests = (strictNodeCheck: boolean): void => {
expect(pushResponse.successes.length).to.eq(0);
expect(
pushResponse.failures?.map((failure) => failure.error)
).to.include(SendError.REMOTE_PEER_REJECTED);
).to.include(ProtocolError.REMOTE_PEER_REJECTED);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq(
false
);
Expand Down Expand Up @@ -262,7 +262,7 @@ const runTests = (strictNodeCheck: boolean): void => {
});
expect(pushResponse.successes.length).to.eq(0);
expect(pushResponse.failures?.map((failure) => failure.error)).to.include(
SendError.SIZE_TOO_BIG
ProtocolError.SIZE_TOO_BIG
);
expect(await serviceNodes.messageCollector.waitForMessages(1)).to.eq(
false
Expand Down
Loading

0 comments on commit 1882023

Please sign in to comment.