Skip to content

Commit

Permalink
rdr: Endpoint => consume / produce
Browse files Browse the repository at this point in the history
  • Loading branch information
yoursunny committed Mar 3, 2024
1 parent a4d3a93 commit c59f944
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 61 deletions.
29 changes: 23 additions & 6 deletions pkg/endpoint/src/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import { produce, type Producer, type ProducerHandler, type ProducerOptions } fr
export interface Options extends ConsumerOptions, ProducerOptions {
}

const cOptsKeys: readonly string[] = [
"fw", "describe", "signal", "modifyInterest", "retx", "verifier",
] satisfies ReadonlyArray<keyof ConsumerOptions>;

const pOptsKeys: readonly string[] = [
"fw", "describe", "signal", "routeCapture", "announcement",
"concurrency", "dataSigner", "dataBuffer", "autoBuffer",
] satisfies ReadonlyArray<keyof ProducerOptions>;

/**
* Endpoint provides basic consumer and producer functionality. It is the main entry point for an
* application to interact with the logical forwarder.
Expand All @@ -23,19 +32,27 @@ export interface Options extends ConsumerOptions, ProducerOptions {
* functions instead. This class will be deprecated in the future.
*/
export class Endpoint {
constructor(public readonly opts: Options = {}) {
this.fw = opts.fw ?? Forwarder.getDefault();
}
constructor(public readonly opts: Options = {}) {}

/** Logical forwarder instance. */
public readonly fw: Forwarder;
public get fw(): Forwarder {
return this.opts.fw ?? Forwarder.getDefault();
}

public get cOpts(): ConsumerOptions {
return Object.fromEntries(Object.entries(this.opts).filter(([key]) => cOptsKeys.includes(key)));
}

public get pOpts(): ProducerOptions {
return Object.fromEntries(Object.entries(this.opts).filter(([key]) => pOptsKeys.includes(key)));
}

/**
* Retrieve a single piece of Data.
* @param interest - Interest or Interest name.
*/
public consume(interest: Interest | NameLike, opts: ConsumerOptions = {}): ConsumerContext {
return consume(interest, { ...this.opts, fw: this.fw, ...opts });
return consume(interest, { ...this.opts, ...opts });
}

/**
Expand All @@ -44,7 +61,7 @@ export class Endpoint {
* @param handler - Function to handle incoming Interest.
*/
public produce(prefix: NameLike | undefined, handler: ProducerHandler, opts: ProducerOptions = {}): Producer {
return produce(prefix, handler, { ...this.opts, fw: this.fw, ...opts });
return produce(prefix, handler, { ...this.opts, ...opts });
}
}

Expand Down
1 change: 1 addition & 0 deletions pkg/rdr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"tslib": "^2.6.2"
},
"devDependencies": {
"@ndn/fw": "workspace:^",
"@ndn/keychain": "workspace:*",
"@ndn/util": "workspace:*"
}
Expand Down
62 changes: 24 additions & 38 deletions pkg/rdr/src/consumer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Endpoint, type RetxPolicy } from "@ndn/endpoint";
import { Interest, Name, type NameLike, type Verifier } from "@ndn/packet";
import { consume, type ConsumerOptions, type Endpoint } from "@ndn/endpoint";
import { Interest, Name, type NameLike } from "@ndn/packet";
import { Decoder } from "@ndn/tlv";

import { Metadata, MetadataKeyword } from "./metadata";
Expand All @@ -23,7 +23,10 @@ export function makeDiscoveryInterest(prefix: NameLike): Interest {
* @param opts - Other options.
* @returns Metadata packet.
*/
export async function retrieveMetadata(prefix: NameLike, opts?: retrieveMetadata.Options): Promise<Metadata>;
export async function retrieveMetadata(
prefix: NameLike,
cOpts?: ConsumerOptions & EndpointOptions
): Promise<Metadata>;

/**
* Retrieve metadata packet of subclass type.
Expand All @@ -33,52 +36,35 @@ export async function retrieveMetadata(prefix: NameLike, opts?: retrieveMetadata
* @param opts - Other options.
* @returns Metadata packet of type C.
*/
export async function retrieveMetadata<C extends Metadata.Constructor>(prefix: NameLike, ctor: C, opts?: retrieveMetadata.Options): Promise<InstanceType<C>>;
export async function retrieveMetadata<C extends Metadata.Constructor>(
prefix: NameLike, ctor: C,
cOpts?: ConsumerOptions & EndpointOptions
): Promise<InstanceType<C>>;

export async function retrieveMetadata(prefix: NameLike, arg2: any = {}, opts: retrieveMetadata.Options = {}) {
export async function retrieveMetadata(
prefix: NameLike, arg2: any,
cOpts?: ConsumerOptions & EndpointOptions,
) {
let ctor: Metadata.Constructor = Metadata;
if (typeof arg2 === "function") {
ctor = arg2;
} else {
opts = arg2;
cOpts = arg2;
}
const {
endpoint = new Endpoint(),
retx,
signal,
verifier,
} = opts;

const interest = makeDiscoveryInterest(prefix);
const data = await endpoint.consume(interest, {
const data = await consume(interest, {
describe: `RDR-c(${prefix})`,
retx,
signal,
verifier,
...cOpts?.endpoint?.cOpts, // eslint-disable-line etc/no-deprecated
...cOpts,
});
return Decoder.decode(data.content, ctor);
}

export namespace retrieveMetadata {
export interface Options {
/**
* Endpoint for communication.
* @defaultValue
* Endpoint on default logical forwarder.
*/
endpoint?: Endpoint;

/** Interest retransmission policy. */
retx?: RetxPolicy;

/** Abort signal to cancel retrieval. */
signal?: AbortSignal;

/**
* Data verifier.
* @defaultValue
* No verification.
*/
verifier?: Verifier;
}
interface EndpointOptions {
/**
* Endpoint for communication.
* @deprecated Use {@link ConsumerOptions} fields only.
*/
endpoint?: Endpoint;
}
24 changes: 16 additions & 8 deletions pkg/rdr/src/producer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Endpoint, type Producer } from "@ndn/endpoint";
import { type Endpoint, produce, type Producer, type ProducerOptions } from "@ndn/endpoint";
import { Segment, Version } from "@ndn/naming-convention2";
import { Data, type Interest, Name, type NameLike, noopSigning, type Signer } from "@ndn/packet";
import { Encoder } from "@ndn/tlv";
Expand Down Expand Up @@ -57,13 +57,14 @@ export function isDiscoveryInterest({ name, canBePrefix, mustBeFresh }: Interest
export function serveMetadata(m: Metadata | (() => Metadata), opts: serveMetadata.Options = {}): Producer {
const {
prefix: prefixInput,
endpoint = new Endpoint(),
announcement,
endpoint, // eslint-disable-line etc/no-deprecated
pOpts,
announcement, // eslint-disable-line etc/no-deprecated
} = opts;
const makeMetadata = typeof m === "function" ? m : () => m;
const prefix = makeName(makeMetadata(), prefixInput).getPrefix(-2);

return endpoint.produce(prefix,
return produce(prefix,
async (interest) => {
if (isDiscoveryInterest(interest) && interest.name.length === prefix.length) {
return makeMetadataPacket(makeMetadata(), opts);
Expand All @@ -73,19 +74,26 @@ export function serveMetadata(m: Metadata | (() => Metadata), opts: serveMetadat
{
describe: `RDR-s(${prefix})`,
announcement,
...endpoint?.pOpts,
...pOpts,
});
}
export namespace serveMetadata {
export interface Options extends makeMetadataPacket.Options {
/**
* Endpoint for communication.
* @defaultValue
* Endpoint on default logical forwarder.
* @deprecated Specify `.pOpts`.
*/
endpoint?: Endpoint;

/** Prefix to announce from producer. */
announcement?: Endpoint.RouteAnnouncement;
/** Producer options. */
pOpts?: ProducerOptions;

/**
* Prefix to announce from producer.
* @deprecated Specify in `.pOpts.announcement`.
*/
announcement?: ProducerOptions.RouteAnnouncement;
}
}

18 changes: 9 additions & 9 deletions pkg/rdr/tests/rdr.t.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import "@ndn/packet/test-fixture/expect";

import { Endpoint } from "@ndn/endpoint";
import { consume } from "@ndn/endpoint";
import { Forwarder } from "@ndn/fw";
import { generateSigningKey } from "@ndn/keychain";
import { Version } from "@ndn/naming-convention2";
import { Interest, Name, type Signer, type Verifier } from "@ndn/packet";
import { Decoder, Extensible, Extension, ExtensionRegistry, NNI, StructFieldNNI, StructFieldText } from "@ndn/tlv";
import { Closers, toUtf8 } from "@ndn/util";
import { Closers } from "@ndn/util";
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";

import { Metadata, retrieveMetadata, serveMetadata } from "..";
Expand All @@ -20,7 +21,7 @@ beforeAll(async () => {
const closers = new Closers();
afterEach(() => {
closers.close();
Endpoint.deleteDefaultForwarder();
Forwarder.deleteDefault();
});

describe("consumer", () => {
Expand Down Expand Up @@ -50,14 +51,13 @@ describe("producer", () => {
const p = serveMetadata(simpleMetadata);
closers.push(p);

const endpoint = new Endpoint();
const [data] = await Promise.all([
endpoint.consume(new Interest("/D/32=metadata", Interest.CanBePrefix, Interest.MustBeFresh)),
expect(endpoint.consume(new Interest("/D/32=metadata", Interest.CanBePrefix,
consume(new Interest("/D/32=metadata", Interest.CanBePrefix, Interest.MustBeFresh)),
expect(consume(new Interest("/D/32=metadata", Interest.CanBePrefix,
Interest.Lifetime(100)))).rejects.toThrow(),
expect(endpoint.consume(new Interest("/D/32=metadata", Interest.MustBeFresh,
expect(consume(new Interest("/D/32=metadata", Interest.MustBeFresh,
Interest.Lifetime(100)))).rejects.toThrow(),
expect(endpoint.consume(new Interest(new Name("/D/32=metadata").append(Version, 4),
expect(consume(new Interest(new Name("/D/32=metadata").append(Version, 4),
Interest.CanBePrefix, Interest.MustBeFresh,
Interest.Lifetime(100)))).rejects.toThrow(),
]);
Expand All @@ -73,7 +73,7 @@ describe("producer", () => {
const p = serveMetadata(makeMetadata, { prefix: "/R", freshnessPeriod: 100 });
closers.push(p);

const data = await new Endpoint().consume(new Interest("/R/32=metadata", Interest.CanBePrefix, Interest.MustBeFresh));
const data = await consume(new Interest("/R/32=metadata", Interest.CanBePrefix, Interest.MustBeFresh));
expect(data.name).toHaveLength(4);
expect(data.freshnessPeriod).toBe(100);
const name2 = Decoder.decode(data.content, Name);
Expand Down

0 comments on commit c59f944

Please sign in to comment.