Skip to content

Commit

Permalink
H-3778: Resolve DNS entries on connection re-use (#5859)
Browse files Browse the repository at this point in the history
Co-authored-by: Tim Diekmann <21277928+TimDiekmann@users.noreply.github.com>
  • Loading branch information
indietyp and TimDiekmann authored Dec 11, 2024
1 parent 99ac6db commit 134b75f
Show file tree
Hide file tree
Showing 8 changed files with 499 additions and 45 deletions.
4 changes: 2 additions & 2 deletions apps/hash-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ const main = async () => {
const rpcHost = getRequiredEnv("HASH_GRAPH_RPC_HOST");
const rpcPort = parseInt(process.env.HASH_GRAPH_RPC_PORT ?? "4002", 10);

app.get("/rpc/echo", (req, res, next) => {
app.get("/rpc/echo", (req, res) => {
// eslint-disable-next-line func-names
const effect = Effect.gen(function* () {
const textQueryParam = req.query.text;
Expand All @@ -569,7 +569,7 @@ const main = async () => {
runtime.runCallback(effect, {
onExit: (exit) => {
if (Exit.isFailure(exit)) {
next(exit.cause);
res.status(500).send(exit.cause.toString());
}
},
});
Expand Down
2 changes: 2 additions & 0 deletions libs/@local/harpc/client/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
"test:unit": "vitest --run"
},
"dependencies": {
"@chainsafe/is-ip": "2.0.2",
"@chainsafe/libp2p-noise": "16.0.0",
"@chainsafe/libp2p-yamux": "7.0.1",
"@libp2p/crypto": "5.0.7",
"@libp2p/identify": "3.0.12",
"@libp2p/interface": "2.2.1",
"@libp2p/ping": "2.0.12",
"@libp2p/tcp": "10.0.13",
"@multiformats/dns": "1.0.6",
"@multiformats/multiaddr": "12.3.4",
"effect": "3.11.3",
"it-stream-types": "2.0.2",
Expand Down
31 changes: 31 additions & 0 deletions libs/@local/harpc/client/typescript/src/net/Transport.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { DNS } from "@multiformats/dns";
import { Data } from "effect";

import type { NoiseConfig, TCPConfig, YamuxConfig } from "./Config.js";
Expand All @@ -16,7 +17,37 @@ export class InitializationError extends Data.TaggedError(

export type Address = internal.Address;

export interface DNSConfig {
/**
* The DNS resolver to use when resolving DNSADDR Multiaddrs.
*/
resolver?: DNS;

/**
* When resolving DNSADDR Multiaddrs that resolve to other DNSADDR Multiaddrs,
* limit how many times we will recursively resolve them.
*
* @default 32
*/
maxRecursiveDepth?: number;

/**
* Amount of cached resolved multiaddrs to keep in memory.
*
* @default 32
*/
cacheCapacity?: number;

/**
* Time in milliseconds until a cached resolved multiaddr is considered stale.
*
* @default 5 minutes
*/
cacheTimeToLive?: number;
}

export interface TransportConfig {
dns?: DNSConfig;
tcp?: TCPConfig;
yamux?: YamuxConfig;
noise?: NoiseConfig;
Expand Down
124 changes: 124 additions & 0 deletions libs/@local/harpc/client/typescript/src/net/internal/multiaddr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import {
isMultiaddr,
type Multiaddr,
type MultiaddrInput,
type ResolveOptions,
} from "@multiformats/multiaddr";
import { Equal, Hash, pipe, Predicate } from "effect";

import { createProto, hashUint8Array } from "../../utils.js";

const MultiaddrSymbol = Symbol.for("@multiformats/js-multiaddr/multiaddr");
type MultiaddrSymbol = typeof MultiaddrSymbol;

const TypeId: unique symbol = Symbol(
"@local/harpc-client/net/internal/HashableMultiaddr",
);
type TypeId = typeof TypeId;

/** @internal */
export interface HashableMultiaddr extends Multiaddr, Equal.Equal {
readonly [TypeId]: TypeId;
readonly [MultiaddrSymbol]: true;
readonly inner: Multiaddr;
}

const HashableMultiaddrProto: Omit<HashableMultiaddr, "inner"> = {
[TypeId]: TypeId,
[MultiaddrSymbol]: true,

get bytes() {
return (this as HashableMultiaddr).inner.bytes;
},

toString(this: HashableMultiaddr) {
return this.inner.toString();
},

toJSON(this: HashableMultiaddr) {
return this.inner.toString();
},

toOptions(this: HashableMultiaddr) {
return this.inner.toOptions();
},

protos(this: HashableMultiaddr) {
return this.inner.protos();
},

protoCodes(this: HashableMultiaddr) {
return this.inner.protoCodes();
},

protoNames(this: HashableMultiaddr) {
return this.inner.protoNames();
},

tuples(this: HashableMultiaddr) {
return this.inner.tuples();
},

stringTuples(this: HashableMultiaddr) {
return this.inner.stringTuples();
},

encapsulate(this: HashableMultiaddr, addr: MultiaddrInput) {
return this.inner.encapsulate(addr);
},

decapsulate(this: HashableMultiaddr, addr: Multiaddr | string) {
return this.inner.decapsulate(addr);
},

decapsulateCode(this: HashableMultiaddr, code: number) {
return this.inner.decapsulateCode(code);
},

getPeerId(this: HashableMultiaddr) {
return this.inner.getPeerId();
},

getPath(this: HashableMultiaddr) {
return this.inner.getPath();
},

equals(this: HashableMultiaddr, other: HashableMultiaddr) {
return this.inner.equals(other.inner);
},

resolve(this: HashableMultiaddr, options?: ResolveOptions) {
return this.inner.resolve(options);
},

nodeAddress(this: HashableMultiaddr) {
return this.inner.nodeAddress();
},

isThinWaistAddress(this: HashableMultiaddr) {
return this.inner.isThinWaistAddress();
},

[Equal.symbol](this: HashableMultiaddr, other: unknown) {
return isMultiaddr(other) && this.inner.equals(other);
},

[Hash.symbol](this: HashableMultiaddr) {
return pipe(
Hash.hash(MultiaddrSymbol),
Hash.combine(hashUint8Array(this.bytes)),
Hash.cached(this),
);
},
};

const isHashableMultiaddr = (value: unknown): value is HashableMultiaddr =>
Predicate.hasProperty(value, TypeId);

/** @internal */
export const make = (inner: Multiaddr): HashableMultiaddr =>
isHashableMultiaddr(inner)
? inner
: (createProto(HashableMultiaddrProto, {
inner,
}) satisfies HashableMultiaddr);
Loading

0 comments on commit 134b75f

Please sign in to comment.