From bcd7336ff998c92d971b7a85b070760831e87492 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Fri, 17 Jun 2022 19:38:18 -0500 Subject: [PATCH 01/14] fix/custom metadata header alloc (#231) * fix: clear buffer when allocating for custom metadata header * test: add composite metadata tests - encodeAndAddCustomMetadata - encodeCustomMetadataHeader Signed-off-by: Kevin Viglucci --- .../encodeAndAddCustomMetadata.spec.ts | 40 +++++++++++++++++++ .../__tests__/encodeCustomMetadataHeader.ts | 33 +++++++++++++++ .../__tests__/test-utils/hex.ts | 24 +++++++++++ .../rsocket-composite-metadata/jest.config.ts | 17 ++++++++ .../rsocket-composite-metadata/jest.setup.ts | 1 + .../rsocket-composite-metadata/package.json | 2 +- .../src/CompositeMetadata.ts | 10 ++--- 7 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 packages/rsocket-composite-metadata/__tests__/encodeAndAddCustomMetadata.spec.ts create mode 100644 packages/rsocket-composite-metadata/__tests__/encodeCustomMetadataHeader.ts create mode 100644 packages/rsocket-composite-metadata/__tests__/test-utils/hex.ts create mode 100644 packages/rsocket-composite-metadata/jest.config.ts create mode 100644 packages/rsocket-composite-metadata/jest.setup.ts diff --git a/packages/rsocket-composite-metadata/__tests__/encodeAndAddCustomMetadata.spec.ts b/packages/rsocket-composite-metadata/__tests__/encodeAndAddCustomMetadata.spec.ts new file mode 100644 index 00000000..d591f933 --- /dev/null +++ b/packages/rsocket-composite-metadata/__tests__/encodeAndAddCustomMetadata.spec.ts @@ -0,0 +1,40 @@ +import { encodeAndAddCustomMetadata } from "rsocket-composite-metadata"; +import { hex } from "./test-utils/hex"; + +describe("encodeAndAddCustomMetadata", () => { + it("throws if custom mimtype length is less than 1", () => { + expect(() => + encodeAndAddCustomMetadata(Buffer.from([]), "", Buffer.from("1234")) + ).toThrow( + "Custom mime type must have a strictly positive length that fits on 7 unsigned bits, ie 1-128" + ); + }); + + it("throws if custom mimtype length is greater than 127", () => { + let mime = ""; + while (mime.length < 130) { + mime += "a"; + } + expect(() => + encodeAndAddCustomMetadata(Buffer.from([]), mime, Buffer.from("1234")) + ).toThrow( + "Custom mime type must have a strictly positive length that fits on 7 unsigned bits, ie 1-128" + ); + }); + + it("encodes the header and payload as per spec", () => { + const { c, u, s, t, o, m } = hex; + const metadata = encodeAndAddCustomMetadata( + Buffer.from([]), + "custom", + Buffer.from("1234") + ); + const expectedHeaderLength8 = "05"; + const expectedPayloadLength24 = "000004"; + const expectedHeader = `${expectedHeaderLength8}${c}${u}${s}${t}${o}${m}${expectedPayloadLength24}`; + const expectedPayload = `${hex["1"]}${hex["2"]}${hex["3"]}${hex["4"]}`; + expect(metadata.toString("hex")).toBe( + `${expectedHeader}${expectedPayload}` + ); + }); +}); diff --git a/packages/rsocket-composite-metadata/__tests__/encodeCustomMetadataHeader.ts b/packages/rsocket-composite-metadata/__tests__/encodeCustomMetadataHeader.ts new file mode 100644 index 00000000..e8b1b5da --- /dev/null +++ b/packages/rsocket-composite-metadata/__tests__/encodeCustomMetadataHeader.ts @@ -0,0 +1,33 @@ +import { encodeCustomMetadataHeader } from "rsocket-composite-metadata"; +import { hex } from "./test-utils/hex"; + +describe("encodeCustomMetadataHeader", () => { + it("throws if length is less than 1", () => { + expect(() => encodeCustomMetadataHeader("", 0)).toThrow( + "Custom mime type must have a strictly positive length that fits on 7 unsigned bits, ie 1-128" + ); + }); + + it("throws if length is greater than 127", () => { + let mime = ""; + while (mime.length < 130) { + mime += "a"; + } + expect(() => encodeCustomMetadataHeader(mime, mime.length)).toThrow( + "Custom mime type must have a strictly positive length that fits on 7 unsigned bits, ie 1-128" + ); + }); + + it("encodes the header as per spec", () => { + const { t, e, s } = hex; + const mime = "test"; + // length minus 1 (uint8) + const expectedLength8 = "03"; + // full length (uint24) + const expectedLength24 = "000004"; + const header = encodeCustomMetadataHeader(mime, mime.length); + expect(header.toString("hex")).toBe( + `${expectedLength8}${t}${e}${s}${t}${expectedLength24}` + ); + }); +}); diff --git a/packages/rsocket-composite-metadata/__tests__/test-utils/hex.ts b/packages/rsocket-composite-metadata/__tests__/test-utils/hex.ts new file mode 100644 index 00000000..4bfe6bd1 --- /dev/null +++ b/packages/rsocket-composite-metadata/__tests__/test-utils/hex.ts @@ -0,0 +1,24 @@ +function numHex(s) { + let a = s.toString(16); + if (a.length % 2 > 0) { + a = "0" + a; + } + return a; +} + +function strHex(s) { + let a = ""; + for (let i = 0; i < s.length; i++) { + a = a + numHex(s.charCodeAt(i)); + } + + return a; +} + +const alphabetNumeric = "abcdefghijklmnopqrstuvqxyz0123456789"; + +export const hex: any = {}; + +alphabetNumeric.split("").forEach((c) => { + hex[c] = strHex(c); +}); diff --git a/packages/rsocket-composite-metadata/jest.config.ts b/packages/rsocket-composite-metadata/jest.config.ts new file mode 100644 index 00000000..aa6e88e7 --- /dev/null +++ b/packages/rsocket-composite-metadata/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from "@jest/types"; +import { pathsToModuleNameMapper } from "ts-jest/utils"; +import { compilerOptions } from "../../tsconfig.json"; + +const config: Config.InitialOptions = { + preset: "ts-jest", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { + // This has to match the baseUrl defined in tsconfig.json. + prefix: "/../../", + }), + modulePathIgnorePatterns: ["/__tests__/test-utils"], + collectCoverage: true, + collectCoverageFrom: ["/src/**/*.ts", "!**/node_modules/**"], + setupFilesAfterEnv: ["/jest.setup.ts"], +}; + +export default config; diff --git a/packages/rsocket-composite-metadata/jest.setup.ts b/packages/rsocket-composite-metadata/jest.setup.ts new file mode 100644 index 00000000..2289a344 --- /dev/null +++ b/packages/rsocket-composite-metadata/jest.setup.ts @@ -0,0 +1 @@ +expect.extend({}); diff --git a/packages/rsocket-composite-metadata/package.json b/packages/rsocket-composite-metadata/package.json index b927ee16..cf766f36 100644 --- a/packages/rsocket-composite-metadata/package.json +++ b/packages/rsocket-composite-metadata/package.json @@ -16,7 +16,7 @@ "clean": "rimraf -rf ./dist", "compile": "tsc -p tsconfig.build.json", "prepublishOnly": "yarn run build", - "test": "echo \"Error: no test specified\" && exit 0" + "test": "yarn jest" }, "dependencies": { "rsocket-core": "^1.0.0-alpha.1" diff --git a/packages/rsocket-composite-metadata/src/CompositeMetadata.ts b/packages/rsocket-composite-metadata/src/CompositeMetadata.ts index 2bb7f484..d780d0bc 100644 --- a/packages/rsocket-composite-metadata/src/CompositeMetadata.ts +++ b/packages/rsocket-composite-metadata/src/CompositeMetadata.ts @@ -170,14 +170,14 @@ export function encodeCustomMetadataHeader( customMime: string, metadataLength: number ): Buffer { + // allocate one byte + the length of the mimetype const metadataHeader: Buffer = Buffer.allocUnsafe(4 + customMime.length); - // reserve 1 byte for the customMime length - // /!\ careful not to read that first byte, which is random at this point - // int writerIndexInitial = metadataHeader.writerIndex(); - // metadataHeader.writerIndex(writerIndexInitial + 1); + + // fill the buffer to clear previous memory + metadataHeader.fill(0); // write the custom mime in UTF8 but validate it is all ASCII-compatible - // (which produces the right result since ASCII chars are still encoded on 1 byte in UTF8) + // (which produces the correct result since ASCII chars are still encoded on 1 byte in UTF8) const customMimeLength: number = metadataHeader.write(customMime, 1); if (!isAscii(metadataHeader, 1)) { throw new Error("Custom mime type must be US_ASCII characters only"); From c5113bbd2ab35ed5aa74d4e7d101aca5e5528ead Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Fri, 17 Jun 2022 19:48:18 -0500 Subject: [PATCH 02/14] chore(release): release - rsocket-adapter-rxjs@1.0.0-alpha.2 - rsocket-composite-metadata@1.0.0-alpha.2 - rsocket-examples@1.0.0-alpha.2 - rsocket-messaging@1.0.0-alpha.2 --- packages/rsocket-adapter-rxjs/package.json | 4 ++-- packages/rsocket-composite-metadata/package.json | 2 +- packages/rsocket-examples/package.json | 6 +++--- packages/rsocket-messaging/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/rsocket-adapter-rxjs/package.json b/packages/rsocket-adapter-rxjs/package.json index 8f5c404b..745a1d19 100644 --- a/packages/rsocket-adapter-rxjs/package.json +++ b/packages/rsocket-adapter-rxjs/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-adapter-rxjs", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.2", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ }, "dependencies": { "rsocket-core": "^1.0.0-alpha.1", - "rsocket-messaging": "^1.0.0-alpha.1", + "rsocket-messaging": "^1.0.0-alpha.2", "rxjs": "^7.4.0" }, "devDependencies": { diff --git a/packages/rsocket-composite-metadata/package.json b/packages/rsocket-composite-metadata/package.json index cf766f36..c76a476e 100644 --- a/packages/rsocket-composite-metadata/package.json +++ b/packages/rsocket-composite-metadata/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-composite-metadata", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.2", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", diff --git a/packages/rsocket-examples/package.json b/packages/rsocket-examples/package.json index a4a6cd1c..1ca96708 100644 --- a/packages/rsocket-examples/package.json +++ b/packages/rsocket-examples/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-examples", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.2", "license": "Apache-2.0", "private": true, "files": [ @@ -19,8 +19,8 @@ "start-client-server-rx-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/ClientServerCompositeMetadataRouteExample.ts" }, "dependencies": { - "rsocket-adapter-rxjs": "^1.0.0-alpha.1", - "rsocket-composite-metadata": "^1.0.0-alpha.1", + "rsocket-adapter-rxjs": "^1.0.0-alpha.2", + "rsocket-composite-metadata": "^1.0.0-alpha.2", "rsocket-core": "^1.0.0-alpha.1", "rsocket-tcp-client": "^1.0.0-alpha.1", "rsocket-tcp-server": "^1.0.0-alpha.1", diff --git a/packages/rsocket-messaging/package.json b/packages/rsocket-messaging/package.json index 0b407192..261b20f6 100644 --- a/packages/rsocket-messaging/package.json +++ b/packages/rsocket-messaging/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-messaging", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.2", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -19,7 +19,7 @@ "test": "echo \"Error: no test specified\" && exit 0" }, "dependencies": { - "rsocket-composite-metadata": "^1.0.0-alpha.1", + "rsocket-composite-metadata": "^1.0.0-alpha.2", "rsocket-core": "^1.0.0-alpha.1" }, "devDependencies": { From 6489f213b81a20698012b76bafdc6b323c3dce67 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Sat, 18 Jun 2022 22:20:34 -0500 Subject: [PATCH 03/14] test: add encodeWellKnownMetadataHeader test --- .../encodeWellKnownMetadataHeader.ts.snap | 10 ++++++++++ .../__tests__/encodeWellKnownMetadataHeader.ts | 15 +++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 packages/rsocket-composite-metadata/__tests__/__snapshots__/encodeWellKnownMetadataHeader.ts.snap create mode 100644 packages/rsocket-composite-metadata/__tests__/encodeWellKnownMetadataHeader.ts diff --git a/packages/rsocket-composite-metadata/__tests__/__snapshots__/encodeWellKnownMetadataHeader.ts.snap b/packages/rsocket-composite-metadata/__tests__/__snapshots__/encodeWellKnownMetadataHeader.ts.snap new file mode 100644 index 00000000..f899ffe6 --- /dev/null +++ b/packages/rsocket-composite-metadata/__tests__/__snapshots__/encodeWellKnownMetadataHeader.ts.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`encodeWellKnownMetadataHeader encodes the header as per spec 1`] = ` +Array [ + 133, + 0, + 0, + 16, +] +`; diff --git a/packages/rsocket-composite-metadata/__tests__/encodeWellKnownMetadataHeader.ts b/packages/rsocket-composite-metadata/__tests__/encodeWellKnownMetadataHeader.ts new file mode 100644 index 00000000..72bcd0f7 --- /dev/null +++ b/packages/rsocket-composite-metadata/__tests__/encodeWellKnownMetadataHeader.ts @@ -0,0 +1,15 @@ +import { + encodeWellKnownMetadataHeader, + WellKnownMimeType, +} from "rsocket-composite-metadata"; + +describe("encodeWellKnownMetadataHeader", () => { + it("encodes the header as per spec", () => { + const header = encodeWellKnownMetadataHeader( + WellKnownMimeType.APPLICATION_JSON.identifier, + WellKnownMimeType.APPLICATION_JSON.toString().length + ); + const actual = header.toJSON().data; + expect(actual).toMatchSnapshot(); + }); +}); From 877a5c7fae871603624d0f9b9a297b2f38be10fe Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Sun, 19 Jun 2022 10:22:55 -0500 Subject: [PATCH 04/14] test: add encodeAndAddWellKnownMetadata tests Signed-off-by: Kevin Viglucci --- .../encodeAndAddWellKnownMetadata.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 packages/rsocket-composite-metadata/__tests__/encodeAndAddWellKnownMetadata.ts diff --git a/packages/rsocket-composite-metadata/__tests__/encodeAndAddWellKnownMetadata.ts b/packages/rsocket-composite-metadata/__tests__/encodeAndAddWellKnownMetadata.ts new file mode 100644 index 00000000..8f48e7aa --- /dev/null +++ b/packages/rsocket-composite-metadata/__tests__/encodeAndAddWellKnownMetadata.ts @@ -0,0 +1,44 @@ +import { + encodeAndAddWellKnownMetadata, + WellKnownMimeType, +} from "rsocket-composite-metadata"; +import { readUInt24BE } from "rsocket-core"; + +describe("encodeWellKnownMetadataHeader", () => { + it("encodes the header as per spec when WellKnownMimeType given", () => { + const metadata = encodeAndAddWellKnownMetadata( + Buffer.from([]), + WellKnownMimeType.MESSAGE_RSOCKET_MIMETYPE, + Buffer.from("test") + ); + + // 122 | 128 + const maskedId = metadata.readUInt8(0); + const length = readUInt24BE(metadata, 1); + const value = metadata.slice(4, metadata.length); + + expect(maskedId).toBe(250); + expect(length).toBe(4); + expect(value.length).toBe(4); + expect(value.toString("utf-8")).toBe("test"); + }); + + it("encodes the header as per spec when identifier given", () => { + const metadata = encodeAndAddWellKnownMetadata( + Buffer.from([]), + // MESSAGE_RSOCKET_MIMETYPE + 122, + Buffer.from("test") + ); + + // 122 | 128 + const maskedId = metadata.readUInt8(0); + const length = readUInt24BE(metadata, 1); + const value = metadata.slice(4, metadata.length); + + expect(maskedId).toBe(250); + expect(length).toBe(4); + expect(value.length).toBe(4); + expect(value.toString("utf-8")).toBe("test"); + }); +}); From 8cc5c7e0c348a96fbf1ab00afae4bb8f49bc2e18 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Sun, 19 Jun 2022 15:51:27 -0500 Subject: [PATCH 05/14] test: add encodeCompositeMetadata tests --- .../__tests__/encodeCompositeMetadata.ts | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 packages/rsocket-composite-metadata/__tests__/encodeCompositeMetadata.ts diff --git a/packages/rsocket-composite-metadata/__tests__/encodeCompositeMetadata.ts b/packages/rsocket-composite-metadata/__tests__/encodeCompositeMetadata.ts new file mode 100644 index 00000000..210f3867 --- /dev/null +++ b/packages/rsocket-composite-metadata/__tests__/encodeCompositeMetadata.ts @@ -0,0 +1,152 @@ +import { + encodeCompositeMetadata, + WellKnownMimeType, +} from "rsocket-composite-metadata"; +import { readUInt24BE } from "rsocket-core"; + +describe("encodeCompositeMetadata encodes the metadata", () => { + describe("when given a map", () => { + it("handles WellKnownMimeType instances as keys", () => { + const metadata = new Map(); + metadata.set( + WellKnownMimeType.MESSAGE_RSOCKET_MIMETYPE, + Buffer.from("test") + ); + + const encoded = encodeCompositeMetadata(metadata); + + // 122 | 128 + const maskedId = encoded.readUInt8(0); + const length = readUInt24BE(encoded, 1); + const value = encoded.slice(4, encoded.length); + + expect(maskedId).toBe(250); + expect(length).toBe(4); + expect(value.length).toBe(4); + expect(value.toString("utf-8")).toBe("test"); + }); + + it("handles WellKnownMimeType identifiers as keys", () => { + const metadata = new Map(); + metadata.set(122, Buffer.from("test")); + + const encoded = encodeCompositeMetadata(metadata); + + // 122 | 128 + const maskedId = encoded.readUInt8(0); + const length = readUInt24BE(encoded, 1); + const value = encoded.slice(4, encoded.length); + + expect(maskedId).toBe(250); + expect(length).toBe(4); + expect(value.length).toBe(4); + expect(value.toString("utf-8")).toBe("test"); + }); + + it("handles custom mimetypes as keys", () => { + const metadata = new Map(); + metadata.set("custom", Buffer.from("test")); + + const encoded = encodeCompositeMetadata(metadata); + + const mimeTypeLengthMinusOne = encoded.readUInt8(0); + const start = 1; + const end = mimeTypeLengthMinusOne + 2; + const mimeType = encoded.slice(start, end); + const metadataLength = readUInt24BE(encoded, mimeTypeLengthMinusOne + 2); + const metadataValue = encoded.slice(encoded.length - metadataLength); + + expect(mimeTypeLengthMinusOne).toBe(5); + expect(mimeType.toString("utf-8")).toBe("custom"); + expect(metadataLength).toBe(4); + expect(metadataValue.toString("utf-8")).toBe("test"); + }); + + it("handles mimetype value as function", () => { + const metadata = new Map(); + metadata.set("custom", () => Buffer.from("test")); + + const encoded = encodeCompositeMetadata(metadata); + + const mimeTypeLengthMinusOne = encoded.readUInt8(0); + const start = 1; + const end = mimeTypeLengthMinusOne + 2; + const mimeType = encoded.slice(start, end); + const metadataLength = readUInt24BE(encoded, mimeTypeLengthMinusOne + 2); + const metadataValue = encoded.slice(encoded.length - metadataLength); + + expect(mimeTypeLengthMinusOne).toBe(5); + expect(mimeType.toString("utf-8")).toBe("custom"); + expect(metadataLength).toBe(4); + expect(metadataValue.toString("utf-8")).toBe("test"); + }); + }); + + describe("when given a array", () => { + it("handles WellKnownMimeType instances as keys", () => { + const encoded = encodeCompositeMetadata([ + [WellKnownMimeType.MESSAGE_RSOCKET_MIMETYPE, Buffer.from("test")], + ]); + + // 122 | 128 + const maskedId = encoded.readUInt8(0); + const length = readUInt24BE(encoded, 1); + const value = encoded.slice(4, encoded.length); + + expect(maskedId).toBe(250); + expect(length).toBe(4); + expect(value.length).toBe(4); + expect(value.toString("utf-8")).toBe("test"); + }); + + it("handles WellKnownMimeType identifiers as keys", () => { + const encoded = encodeCompositeMetadata([[122, Buffer.from("test")]]); + + // 122 | 128 + const maskedId = encoded.readUInt8(0); + const length = readUInt24BE(encoded, 1); + const value = encoded.slice(4, encoded.length); + + expect(maskedId).toBe(250); + expect(length).toBe(4); + expect(value.length).toBe(4); + expect(value.toString("utf-8")).toBe("test"); + }); + + it("handles custom mimetypes as keys", () => { + const encoded = encodeCompositeMetadata([ + ["custom", Buffer.from("test")], + ]); + + const mimeTypeLengthMinusOne = encoded.readUInt8(0); + const start = 1; + const end = mimeTypeLengthMinusOne + 2; + const mimeType = encoded.slice(start, end); + const metadataLength = readUInt24BE(encoded, mimeTypeLengthMinusOne + 2); + const metadataValue = encoded.slice(encoded.length - metadataLength); + + expect(mimeTypeLengthMinusOne).toBe(5); + expect(mimeType.toString("utf-8")).toBe("custom"); + expect(metadataLength).toBe(4); + expect(metadataValue.toString("utf-8")).toBe("test"); + }); + + it("handles mimetype value as function", () => { + const encoded = encodeCompositeMetadata([ + ["custom", () => Buffer.from("test")], + ]); + + const mimeTypeLengthMinusOne = encoded.readUInt8(0); + const start = 1; + const end = mimeTypeLengthMinusOne + 2; + const mimeType = encoded.slice(start, end); + const metadataLength = readUInt24BE(encoded, mimeTypeLengthMinusOne + 2); + const metadataValue = encoded.slice(encoded.length - metadataLength); + + expect(mimeTypeLengthMinusOne).toBe(5); + expect(mimeType.toString("utf-8")).toBe("custom"); + expect(metadataLength).toBe(4); + expect(metadataValue.toString("utf-8")).toBe("test"); + }); + }); +}); From f9957009a222823a0b4cce73b831cc29c113b7f1 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Tue, 9 Aug 2022 09:35:29 -0500 Subject: [PATCH 06/14] Optional metadata for rxjs requesters (#241) * feat: support optional metadata in rxjs adapter requesters Signed-off-by: Kevin Viglucci * chore(release): release - rsocket-adapter-rxjs@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-composite-metadata@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-core@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-examples@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-messaging@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-tcp-client@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-tcp-server@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-websocket-client@1.0.0-alpha-rxjs-adapter-optional-metadata.0 - rsocket-websocket-server@1.0.0-alpha-rxjs-adapter-optional-metadata.0 Signed-off-by: Kevin Viglucci --- packages/rsocket-adapter-rxjs/package.json | 6 +- .../rsocket-adapter-rxjs/src/Requesters.ts | 100 ++++++++++-------- .../rsocket-composite-metadata/package.json | 4 +- packages/rsocket-core/package.json | 2 +- packages/rsocket-examples/package.json | 16 +-- packages/rsocket-messaging/package.json | 6 +- packages/rsocket-tcp-client/package.json | 4 +- packages/rsocket-tcp-server/package.json | 4 +- .../rsocket-websocket-client/package.json | 4 +- .../rsocket-websocket-server/package.json | 4 +- 10 files changed, 79 insertions(+), 71 deletions(-) diff --git a/packages/rsocket-adapter-rxjs/package.json b/packages/rsocket-adapter-rxjs/package.json index 745a1d19..5411149d 100644 --- a/packages/rsocket-adapter-rxjs/package.json +++ b/packages/rsocket-adapter-rxjs/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-adapter-rxjs", - "version": "1.0.0-alpha.2", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -19,8 +19,8 @@ "test": "echo \"Error: no test specified\" && exit 0" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha.1", - "rsocket-messaging": "^1.0.0-alpha.2", + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-messaging": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", "rxjs": "^7.4.0" }, "devDependencies": { diff --git a/packages/rsocket-adapter-rxjs/src/Requesters.ts b/packages/rsocket-adapter-rxjs/src/Requesters.ts index d6b20468..bd6d518a 100644 --- a/packages/rsocket-adapter-rxjs/src/Requesters.ts +++ b/packages/rsocket-adapter-rxjs/src/Requesters.ts @@ -48,21 +48,23 @@ export function fireAndForget( inputCodec: Codec ): ( rsocket: RSocket, - metadata: Map + metadata?: Map ) => Observable { return ( rsocket: RSocket, - metadata: Map - ) => - new RSocketPublisherToObservable((s) => + metadata?: Map + ) => { + const encodedMetadata = metadata ? encodeCompositeMetadata(metadata) : null; + return new RSocketPublisherToObservable((s) => rsocket.fireAndForget( { data: data ? inputCodec.encode(data) : Buffer.allocUnsafe(0), - metadata: encodeCompositeMetadata(metadata), + metadata: encodedMetadata, }, s ) ); + }; } export function requestResponse( @@ -71,23 +73,25 @@ export function requestResponse( outputCodec: Codec ): ( rsocket: RSocket, - metadata: Map + metadata?: Map ) => Observable { return ( rsocket: RSocket, - metadata: Map - ) => - new RSocketPublisherToObservable( + metadata?: Map + ) => { + const encodedMetadata = metadata ? encodeCompositeMetadata(metadata) : null; + return new RSocketPublisherToObservable( (s) => rsocket.requestResponse( { data: data ? inputCodec.encode(data) : Buffer.allocUnsafe(0), - metadata: encodeCompositeMetadata(metadata), + metadata: encodedMetadata, }, s ), outputCodec ); + }; } export function requestStream( @@ -98,18 +102,19 @@ export function requestStream( scheduler: SchedulerLike = asyncScheduler ): ( rsocket: RSocket, - metadata: Map + metadata?: Map ) => Observable { return ( rsocket: RSocket, - metadata: Map - ) => - new RSocketPublisherToPrefetchingObservable( + metadata?: Map + ) => { + const encodedMetadata = metadata ? encodeCompositeMetadata(metadata) : null; + return new RSocketPublisherToPrefetchingObservable( (s, n) => rsocket.requestStream( { data: data ? inputCodec.encode(data) : Buffer.allocUnsafe(0), - metadata: encodeCompositeMetadata(metadata), + metadata: encodedMetadata, }, n, s @@ -118,6 +123,7 @@ export function requestStream( outputCodec, scheduler ); + }; } export function requestChannel( @@ -128,9 +134,9 @@ export function requestChannel( scheduler: SchedulerLike = asyncScheduler ): ( rsocket: RSocket, - metadata: Map + metadata?: Map ) => Observable { - const [firstValueObservable, restValuestObservable] = partition( + const [firstValueObservable, restValuesObservable] = partition( datas.pipe( share({ connector: () => new Subject(), @@ -142,35 +148,37 @@ export function requestChannel( return ( rsocket: RSocket, - metadata: Map - ) => - firstValueObservable.pipe( + metadata?: Map + ) => { + const encodedMetadata = metadata ? encodeCompositeMetadata(metadata) : null; + return firstValueObservable.pipe( take(1), - concatMap( - (firstValue) => - new Observer2BufferingSubscriberToPublisher2PrefetchingObservable( - ( - s: OnTerminalSubscriber & - OnNextSubscriber & - OnExtensionSubscriber & - Requestable & - Cancellable - ) => - rsocket.requestChannel( - { - data: inputCodec.encode(firstValue), - metadata: encodeCompositeMetadata(metadata), - }, - prefetch, - false, - s - ), - prefetch, - restValuestObservable, - inputCodec, - outputCodec, - scheduler - ) as Observable - ) + concatMap((firstValue) => { + return new Observer2BufferingSubscriberToPublisher2PrefetchingObservable( + ( + s: OnTerminalSubscriber & + OnNextSubscriber & + OnExtensionSubscriber & + Requestable & + Cancellable + ) => { + return rsocket.requestChannel( + { + data: inputCodec.encode(firstValue), + metadata: encodedMetadata, + }, + prefetch, + false, + s + ); + }, + prefetch, + restValuesObservable, + inputCodec, + outputCodec, + scheduler + ) as Observable; + }) ); + }; } diff --git a/packages/rsocket-composite-metadata/package.json b/packages/rsocket-composite-metadata/package.json index c76a476e..2964279a 100644 --- a/packages/rsocket-composite-metadata/package.json +++ b/packages/rsocket-composite-metadata/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-composite-metadata", - "version": "1.0.0-alpha.2", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -19,7 +19,7 @@ "test": "yarn jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha.1" + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-core/package.json b/packages/rsocket-core/package.json index 4205ea6f..a2dedc9f 100644 --- a/packages/rsocket-core/package.json +++ b/packages/rsocket-core/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-core", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", diff --git a/packages/rsocket-examples/package.json b/packages/rsocket-examples/package.json index 1ca96708..4e9a8e31 100644 --- a/packages/rsocket-examples/package.json +++ b/packages/rsocket-examples/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-examples", - "version": "1.0.0-alpha.2", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "private": true, "files": [ @@ -19,13 +19,13 @@ "start-client-server-rx-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/ClientServerCompositeMetadataRouteExample.ts" }, "dependencies": { - "rsocket-adapter-rxjs": "^1.0.0-alpha.2", - "rsocket-composite-metadata": "^1.0.0-alpha.2", - "rsocket-core": "^1.0.0-alpha.1", - "rsocket-tcp-client": "^1.0.0-alpha.1", - "rsocket-tcp-server": "^1.0.0-alpha.1", - "rsocket-websocket-client": "^1.0.0-alpha.1", - "rsocket-websocket-server": "^1.0.0-alpha.1", + "rsocket-adapter-rxjs": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-composite-metadata": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-tcp-client": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-tcp-server": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-websocket-client": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-websocket-server": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", "ws": "~8.2.3" }, "devDependencies": { diff --git a/packages/rsocket-messaging/package.json b/packages/rsocket-messaging/package.json index 261b20f6..170cd854 100644 --- a/packages/rsocket-messaging/package.json +++ b/packages/rsocket-messaging/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-messaging", - "version": "1.0.0-alpha.2", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -19,8 +19,8 @@ "test": "echo \"Error: no test specified\" && exit 0" }, "dependencies": { - "rsocket-composite-metadata": "^1.0.0-alpha.2", - "rsocket-core": "^1.0.0-alpha.1" + "rsocket-composite-metadata": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-tcp-client/package.json b/packages/rsocket-tcp-client/package.json index a468de4d..a07a0f15 100644 --- a/packages/rsocket-tcp-client/package.json +++ b/packages/rsocket-tcp-client/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-tcp-client", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha.1" + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-tcp-server/package.json b/packages/rsocket-tcp-server/package.json index 89cfda80..5022b4ed 100644 --- a/packages/rsocket-tcp-server/package.json +++ b/packages/rsocket-tcp-server/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-tcp-server", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha.1" + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-websocket-client/package.json b/packages/rsocket-websocket-client/package.json index 5aa6b165..e6a59899 100644 --- a/packages/rsocket-websocket-client/package.json +++ b/packages/rsocket-websocket-client/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-websocket-client", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha.1" + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-websocket-server/package.json b/packages/rsocket-websocket-server/package.json index 9cbf6206..69d653eb 100644 --- a/packages/rsocket-websocket-server/package.json +++ b/packages/rsocket-websocket-server/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-websocket-server", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "echo \"Error: no test specified\" && exit 0" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha.1", + "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", "ws": "~8.2.3" }, "devDependencies": { From 7dc895fd0eb6c6c3f7ab9a945525f64a8df80bd1 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Tue, 9 Aug 2022 09:38:34 -0500 Subject: [PATCH 07/14] chore(release): release - rsocket-adapter-rxjs@1.0.0-alpha.3 - rsocket-composite-metadata@1.0.0-alpha.3 - rsocket-core@1.0.0-alpha.3 - rsocket-examples@1.0.0-alpha.3 - rsocket-messaging@1.0.0-alpha.3 - rsocket-tcp-client@1.0.0-alpha.3 - rsocket-tcp-server@1.0.0-alpha.3 - rsocket-websocket-client@1.0.0-alpha.3 - rsocket-websocket-server@1.0.0-alpha.3 --- packages/rsocket-adapter-rxjs/package.json | 6 +++--- packages/rsocket-composite-metadata/package.json | 4 ++-- packages/rsocket-core/package.json | 2 +- packages/rsocket-examples/package.json | 16 ++++++++-------- packages/rsocket-messaging/package.json | 6 +++--- packages/rsocket-tcp-client/package.json | 4 ++-- packages/rsocket-tcp-server/package.json | 4 ++-- packages/rsocket-websocket-client/package.json | 4 ++-- packages/rsocket-websocket-server/package.json | 4 ++-- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/rsocket-adapter-rxjs/package.json b/packages/rsocket-adapter-rxjs/package.json index 5411149d..68ab4c21 100644 --- a/packages/rsocket-adapter-rxjs/package.json +++ b/packages/rsocket-adapter-rxjs/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-adapter-rxjs", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -19,8 +19,8 @@ "test": "echo \"Error: no test specified\" && exit 0" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-messaging": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-core": "^1.0.0-alpha.3", + "rsocket-messaging": "^1.0.0-alpha.3", "rxjs": "^7.4.0" }, "devDependencies": { diff --git a/packages/rsocket-composite-metadata/package.json b/packages/rsocket-composite-metadata/package.json index 2964279a..f78246c3 100644 --- a/packages/rsocket-composite-metadata/package.json +++ b/packages/rsocket-composite-metadata/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-composite-metadata", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -19,7 +19,7 @@ "test": "yarn jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" + "rsocket-core": "^1.0.0-alpha.3" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-core/package.json b/packages/rsocket-core/package.json index a2dedc9f..693d6cf5 100644 --- a/packages/rsocket-core/package.json +++ b/packages/rsocket-core/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-core", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", diff --git a/packages/rsocket-examples/package.json b/packages/rsocket-examples/package.json index 4e9a8e31..d344a2b2 100644 --- a/packages/rsocket-examples/package.json +++ b/packages/rsocket-examples/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-examples", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "private": true, "files": [ @@ -19,13 +19,13 @@ "start-client-server-rx-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/ClientServerCompositeMetadataRouteExample.ts" }, "dependencies": { - "rsocket-adapter-rxjs": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-composite-metadata": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-tcp-client": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-tcp-server": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-websocket-client": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-websocket-server": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-adapter-rxjs": "^1.0.0-alpha.3", + "rsocket-composite-metadata": "^1.0.0-alpha.3", + "rsocket-core": "^1.0.0-alpha.3", + "rsocket-tcp-client": "^1.0.0-alpha.3", + "rsocket-tcp-server": "^1.0.0-alpha.3", + "rsocket-websocket-client": "^1.0.0-alpha.3", + "rsocket-websocket-server": "^1.0.0-alpha.3", "ws": "~8.2.3" }, "devDependencies": { diff --git a/packages/rsocket-messaging/package.json b/packages/rsocket-messaging/package.json index 170cd854..9a8599e1 100644 --- a/packages/rsocket-messaging/package.json +++ b/packages/rsocket-messaging/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-messaging", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -19,8 +19,8 @@ "test": "echo \"Error: no test specified\" && exit 0" }, "dependencies": { - "rsocket-composite-metadata": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" + "rsocket-composite-metadata": "^1.0.0-alpha.3", + "rsocket-core": "^1.0.0-alpha.3" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-tcp-client/package.json b/packages/rsocket-tcp-client/package.json index a07a0f15..866a6bde 100644 --- a/packages/rsocket-tcp-client/package.json +++ b/packages/rsocket-tcp-client/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-tcp-client", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" + "rsocket-core": "^1.0.0-alpha.3" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-tcp-server/package.json b/packages/rsocket-tcp-server/package.json index 5022b4ed..cc45a7fc 100644 --- a/packages/rsocket-tcp-server/package.json +++ b/packages/rsocket-tcp-server/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-tcp-server", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" + "rsocket-core": "^1.0.0-alpha.3" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-websocket-client/package.json b/packages/rsocket-websocket-client/package.json index e6a59899..4abee493 100644 --- a/packages/rsocket-websocket-client/package.json +++ b/packages/rsocket-websocket-client/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-websocket-client", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "jest" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0" + "rsocket-core": "^1.0.0-alpha.3" }, "devDependencies": { "rimraf": "~3.0.2", diff --git a/packages/rsocket-websocket-server/package.json b/packages/rsocket-websocket-server/package.json index 69d653eb..d82ce24c 100644 --- a/packages/rsocket-websocket-server/package.json +++ b/packages/rsocket-websocket-server/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-websocket-server", - "version": "1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "version": "1.0.0-alpha.3", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", @@ -20,7 +20,7 @@ "test": "echo \"Error: no test specified\" && exit 0" }, "dependencies": { - "rsocket-core": "^1.0.0-alpha-rxjs-adapter-optional-metadata.0", + "rsocket-core": "^1.0.0-alpha.3", "ws": "~8.2.3" }, "devDependencies": { From 71d17733114cf4379b3f6de69deae9a5375a4ffb Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Tue, 9 Aug 2022 21:45:30 -0500 Subject: [PATCH 08/14] chore: expand rxjs example to leverage fire and forget Signed-off-by: Kevin Viglucci --- ...ientServerCompositeMetadataRouteExample.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/packages/rsocket-examples/src/rxjs/ClientServerCompositeMetadataRouteExample.ts b/packages/rsocket-examples/src/rxjs/ClientServerCompositeMetadataRouteExample.ts index 85822ed9..56b4dfa7 100644 --- a/packages/rsocket-examples/src/rxjs/ClientServerCompositeMetadataRouteExample.ts +++ b/packages/rsocket-examples/src/rxjs/ClientServerCompositeMetadataRouteExample.ts @@ -24,6 +24,7 @@ import { firstValueFrom, map, Observable, + of, tap, timer, interval, @@ -37,6 +38,7 @@ class EchoService { handleEchoRequestResponse(data: string): Observable { return timer(1000).pipe(map(() => `Echo: ${data}`)); } + handleEchoRequestStream(data: string): Observable { return interval(1000).pipe( map(() => `RxEchoService Echo: ${data}`), @@ -45,6 +47,7 @@ class EchoService { }) ); } + handleEchoRequestChannel(datas: Observable): Observable { datas .pipe( @@ -60,6 +63,11 @@ class EchoService { }) ); } + + handleLogFireAndForget(data: string): Observable { + Logger.info(`[server] received: ${data}`); + return of(null); + } } function makeServer() { @@ -75,6 +83,13 @@ function makeServer() { accept: async () => { const echoService = new EchoService(); return RSocketResponder.builder() + .route( + "EchoService.log", + RxRespondersFactory.fireAndForget( + echoService.handleLogFireAndForget, + stringCodec + ) + ) .route( "EchoService.echo", RxRespondersFactory.requestResponse( @@ -114,6 +129,25 @@ function makeConnector() { }); } +async function fireAndForget(rsocket: RSocketRequester, route: string = "") { + return new Promise((resolve, reject) => { + rsocket + .route(route) + .request(RxRequestersFactory.fireAndForget("Hello World", stringCodec)) + .subscribe({ + complete() { + // give server a chance to handle before continuing + setTimeout(() => { + resolve(null); + }, 100); + }, + error(err) { + reject(err); + }, + }); + }); +} + async function requestResponse(rsocket: RSocketRequester, route: string = "") { return firstValueFrom( rsocket @@ -180,6 +214,7 @@ class StringCodec implements Codec { decode(buffer: Buffer): string { return buffer.toString(); } + encode(entity: string): Buffer { return Buffer.from(entity); } @@ -195,6 +230,10 @@ async function main() { const rsocket = await connector.connect(); const requester = RSocketRequester.wrap(rsocket); + Logger.info(`----- Fire And Forget -----`); + + await fireAndForget(requester, "EchoService.log"); + Logger.info(`----- Request Response -----`); // this request will pass From d493ebe8ddd423b116a95e58fea6a86032e78396 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Tue, 9 Aug 2022 21:53:50 -0500 Subject: [PATCH 09/14] refactor: rename rxjs messaging composite metadata routing example Signed-off-by: Kevin Viglucci --- packages/rsocket-examples/package.json | 2 +- ...Example.ts => RxjsMessagingCompositeMetadataRouteExample.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/rsocket-examples/src/rxjs/{ClientServerCompositeMetadataRouteExample.ts => RxjsMessagingCompositeMetadataRouteExample.ts} (100%) diff --git a/packages/rsocket-examples/package.json b/packages/rsocket-examples/package.json index d344a2b2..d8376b09 100644 --- a/packages/rsocket-examples/package.json +++ b/packages/rsocket-examples/package.json @@ -16,7 +16,7 @@ "start-client-server-request-response-tcp": "ts-node -r tsconfig-paths/register src/ClientServerRequestResponseExampleTcp.ts", "start-client-server-request-response-websocket": "ts-node -r tsconfig-paths/register src/ClientServerRequestResponseExampleWebSocket.ts", "start-client-server-composite-metadata-route": "ts-node -r tsconfig-paths/register src/ClientServerCompositeMetadataRouteExample.ts", - "start-client-server-rx-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/ClientServerCompositeMetadataRouteExample.ts" + "start-client-server-rxjs-messaging-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts" }, "dependencies": { "rsocket-adapter-rxjs": "^1.0.0-alpha.3", diff --git a/packages/rsocket-examples/src/rxjs/ClientServerCompositeMetadataRouteExample.ts b/packages/rsocket-examples/src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts similarity index 100% rename from packages/rsocket-examples/src/rxjs/ClientServerCompositeMetadataRouteExample.ts rename to packages/rsocket-examples/src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts From 2f1020fb629393814c860419556e67adf37745cb Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Tue, 9 Aug 2022 22:07:21 -0500 Subject: [PATCH 10/14] chore: add rxjs example without rsocket-messaging Signed-off-by: Kevin Viglucci --- packages/rsocket-examples/package.json | 3 +- .../src/rxjs/RxjsRequesterResponderExample.ts | 229 ++++++++++++++++++ 2 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 packages/rsocket-examples/src/rxjs/RxjsRequesterResponderExample.ts diff --git a/packages/rsocket-examples/package.json b/packages/rsocket-examples/package.json index d8376b09..84d1cab7 100644 --- a/packages/rsocket-examples/package.json +++ b/packages/rsocket-examples/package.json @@ -16,7 +16,8 @@ "start-client-server-request-response-tcp": "ts-node -r tsconfig-paths/register src/ClientServerRequestResponseExampleTcp.ts", "start-client-server-request-response-websocket": "ts-node -r tsconfig-paths/register src/ClientServerRequestResponseExampleWebSocket.ts", "start-client-server-composite-metadata-route": "ts-node -r tsconfig-paths/register src/ClientServerCompositeMetadataRouteExample.ts", - "start-client-server-rxjs-messaging-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts" + "start-client-server-rxjs-messaging-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts", + "start-client-server-rxjs-requester-responder": "ts-node -r tsconfig-paths/register src/rxjs/RxjsRequesterResponderExample.ts" }, "dependencies": { "rsocket-adapter-rxjs": "^1.0.0-alpha.3", diff --git a/packages/rsocket-examples/src/rxjs/RxjsRequesterResponderExample.ts b/packages/rsocket-examples/src/rxjs/RxjsRequesterResponderExample.ts new file mode 100644 index 00000000..c5ee32b1 --- /dev/null +++ b/packages/rsocket-examples/src/rxjs/RxjsRequesterResponderExample.ts @@ -0,0 +1,229 @@ +/* + * Copyright 2021-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RSocket, RSocketConnector, RSocketServer } from "rsocket-core"; +import { Codec } from "rsocket-messaging"; +import { RxRequestersFactory, RxRespondersFactory } from "rsocket-adapter-rxjs"; +import { TcpClientTransport } from "rsocket-tcp-client"; +import { TcpServerTransport } from "rsocket-tcp-server"; +import { exit } from "process"; +import { + firstValueFrom, + interval, + map, + Observable, + of, + take, + tap, + timer, +} from "rxjs"; +import Logger from "../shared/logger"; + +let serverCloseable; + +class EchoService { + handleEchoRequestResponse(data: string): Observable { + return timer(1000).pipe(map(() => `Echo: ${data}`)); + } + + handleEchoRequestStream(data: string): Observable { + return interval(1000).pipe( + map(() => `RxEchoService Echo: ${data}`), + tap((value) => { + Logger.info(`[server] sending: ${value}`); + }) + ); + } + + handleEchoRequestChannel(datas: Observable): Observable { + datas + .pipe( + tap((value) => { + Logger.info(`[server] receiving: ${value}`); + }) + ) + .subscribe(); + return interval(200).pipe( + map((data) => `RxEchoService Echo: ${data}`), + tap((value) => { + Logger.info(`[server] sending: ${value}`); + }) + ); + } + + handleLogFireAndForget(data: string): Observable { + Logger.info(`[server] received: ${data}`); + return of(null); + } +} + +function makeServer() { + const stringCodec = new StringCodec(); + return new RSocketServer({ + transport: new TcpServerTransport({ + listenOptions: { + port: 9090, + host: "127.0.0.1", + }, + }), + acceptor: { + accept: async () => { + const echoService = new EchoService(); + return { + fireAndForget: RxRespondersFactory.fireAndForget( + echoService.handleLogFireAndForget, + stringCodec + ), + requestResponse: RxRespondersFactory.requestResponse( + echoService.handleEchoRequestResponse, + { inputCodec: stringCodec, outputCodec: stringCodec } + ), + requestStream: RxRespondersFactory.requestStream( + echoService.handleEchoRequestStream, + { inputCodec: stringCodec, outputCodec: stringCodec } + ), + requestChannel: RxRespondersFactory.requestChannel( + echoService.handleEchoRequestChannel, + { inputCodec: stringCodec, outputCodec: stringCodec }, + 4 + ), + }; + }, + }, + }); +} + +function makeConnector() { + return new RSocketConnector({ + transport: new TcpClientTransport({ + connectionOptions: { + host: "127.0.0.1", + port: 9090, + }, + }), + }); +} + +async function fireAndForget(rsocket: RSocket, route: string = "") { + return new Promise((resolve, reject) => { + const request = RxRequestersFactory.fireAndForget( + "Hello World", + stringCodec + ); + request(rsocket).subscribe({ + complete() { + // give server a chance to handle before continuing + setTimeout(() => { + resolve(null); + }, 100); + }, + error(err) { + reject(err); + }, + }); + }); +} + +async function requestResponse(rsocket: RSocket) { + const request = RxRequestersFactory.requestResponse( + "Hello World", + stringCodec, + stringCodec + ); + return firstValueFrom( + request(rsocket).pipe(tap((data) => Logger.info(`payload[data: ${data};]`))) + ); +} + +async function requestStream(rsocket: RSocket) { + const request = RxRequestersFactory.requestStream( + "Hello World", + stringCodec, + stringCodec, + 5 + ); + return request(rsocket) + .pipe( + tap((data) => { + Logger.info(`[client] received[data: ${data}]`); + }), + take(10) + ) + .toPromise(); +} + +async function requestChannel(rsocket: RSocket) { + const request = RxRequestersFactory.requestChannel( + interval(1000).pipe( + map((i) => `Hello World ${i}`), + tap((data) => { + Logger.info(`[client] produced[data: ${data}]`); + }) + ), + stringCodec, + stringCodec, + 5 + ); + return request(rsocket) + .pipe( + tap((data) => { + Logger.info(`[client] received[data: ${data}]`); + }), + take(25) + ) + .toPromise(); +} + +class StringCodec implements Codec { + readonly mimeType: string = "text/plain"; + + decode(buffer: Buffer): string { + return buffer.toString(); + } + + encode(entity: string): Buffer { + return Buffer.from(entity); + } +} + +const stringCodec = new StringCodec(); + +async function main() { + const server = makeServer(); + const connector = makeConnector(); + + serverCloseable = await server.bind(); + const rsocket = await connector.connect(); + + Logger.info(`----- Fire And Forget -----`); + await fireAndForget(rsocket); + + Logger.info(`----- Request Response -----`); + await requestResponse(rsocket); + + Logger.info(`----- Request Stream -----`); + await requestStream(rsocket); + + Logger.info(`----- Request Channel -----`); + await requestChannel(rsocket); +} + +main() + .then(() => exit()) + .catch((error: Error) => { + console.error(error); + exit(1); + }); From 36bd9f5d40894076ad56af65191b07eabfac1af4 Mon Sep 17 00:00:00 2001 From: Oleh Dokuka <5380167+OlegDokuka@users.noreply.github.com> Date: Thu, 11 Aug 2022 07:51:46 +0300 Subject: [PATCH 11/14] fixes request channel to drop second element (#244) unexpectedly, in the rxjs `partition` operator the index is a local variable per subscription, thus the second subscription starts indexing from 0 once again even though the element is a second one (index should be 1 in that case). Therefore, to overcome this problem the PR introduces a local variable to track the first element. --- packages/rsocket-adapter-rxjs/src/Requesters.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/rsocket-adapter-rxjs/src/Requesters.ts b/packages/rsocket-adapter-rxjs/src/Requesters.ts index bd6d518a..79ce94ac 100644 --- a/packages/rsocket-adapter-rxjs/src/Requesters.ts +++ b/packages/rsocket-adapter-rxjs/src/Requesters.ts @@ -136,6 +136,7 @@ export function requestChannel( rsocket: RSocket, metadata?: Map ) => Observable { + let once = false; const [firstValueObservable, restValuesObservable] = partition( datas.pipe( share({ @@ -143,7 +144,14 @@ export function requestChannel( resetOnRefCountZero: true, }) ), - (_value, index) => index === 0 + (_value) => { + const previous = once; + if (!previous) { + once = true; + } + + return !previous; + } ); return ( From 106d6d936ab636ec0ba604e51e7569da4375945a Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Fri, 12 Aug 2022 22:36:47 -0500 Subject: [PATCH 12/14] chore(release): release - rsocket-adapter-rxjs@1.0.0-alpha.4 - rsocket-examples@1.0.0-alpha.4 --- packages/rsocket-adapter-rxjs/package.json | 2 +- packages/rsocket-examples/package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rsocket-adapter-rxjs/package.json b/packages/rsocket-adapter-rxjs/package.json index 68ab4c21..a1e9b47e 100644 --- a/packages/rsocket-adapter-rxjs/package.json +++ b/packages/rsocket-adapter-rxjs/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-adapter-rxjs", - "version": "1.0.0-alpha.3", + "version": "1.0.0-alpha.4", "license": "Apache-2.0", "main": "dist/index", "types": "dist/index", diff --git a/packages/rsocket-examples/package.json b/packages/rsocket-examples/package.json index 84d1cab7..16b849eb 100644 --- a/packages/rsocket-examples/package.json +++ b/packages/rsocket-examples/package.json @@ -1,6 +1,6 @@ { "name": "rsocket-examples", - "version": "1.0.0-alpha.3", + "version": "1.0.0-alpha.4", "license": "Apache-2.0", "private": true, "files": [ @@ -20,7 +20,7 @@ "start-client-server-rxjs-requester-responder": "ts-node -r tsconfig-paths/register src/rxjs/RxjsRequesterResponderExample.ts" }, "dependencies": { - "rsocket-adapter-rxjs": "^1.0.0-alpha.3", + "rsocket-adapter-rxjs": "^1.0.0-alpha.4", "rsocket-composite-metadata": "^1.0.0-alpha.3", "rsocket-core": "^1.0.0-alpha.3", "rsocket-tcp-client": "^1.0.0-alpha.3", From f734934b3f0ecd599cc4510e5cf37606eb102096 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Fri, 12 Aug 2022 22:38:00 -0500 Subject: [PATCH 13/14] docs: update release docs with example lerna command --- RELEASE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASE.md b/RELEASE.md index 4259cf54..d628dd2e 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,6 +12,12 @@ ex: `@rsocket/adapter-rxjs@1.0.0-alpha.1` Lerna will not push the git tags after creation. You should push the git tags once you are confident in your changes. +### Example + +``` +lerna version prerelease --sign-git-commit +``` + ## Publishing The `Test, Build, Release` Workflow on GitHub can be run to [manually trigger](https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow) publishing of packages to NPM. This workflow will only publish versions which do not already exist on NPM. From 8f862ad6c6c72e54728966d352b5959f1534af25 Mon Sep 17 00:00:00 2001 From: Kevin Viglucci Date: Fri, 9 Sep 2022 22:27:55 -0500 Subject: [PATCH 14/14] chore: add simple webpack example (#246) Signed-off-by: Kevin Viglucci --- .../src/webpack/simple/client/index.html | 11 +++++ .../src/webpack/simple/client/index.js | 37 +++++++++++++++ .../src/webpack/simple/client/package.json | 31 +++++++++++++ .../webpack/simple/client/webpack.config.js | 33 ++++++++++++++ .../src/webpack/simple/server/package.json | 30 +++++++++++++ .../src/webpack/simple/server/server.js | 45 +++++++++++++++++++ 6 files changed, 187 insertions(+) create mode 100644 packages/rsocket-examples/src/webpack/simple/client/index.html create mode 100644 packages/rsocket-examples/src/webpack/simple/client/index.js create mode 100644 packages/rsocket-examples/src/webpack/simple/client/package.json create mode 100644 packages/rsocket-examples/src/webpack/simple/client/webpack.config.js create mode 100644 packages/rsocket-examples/src/webpack/simple/server/package.json create mode 100644 packages/rsocket-examples/src/webpack/simple/server/server.js diff --git a/packages/rsocket-examples/src/webpack/simple/client/index.html b/packages/rsocket-examples/src/webpack/simple/client/index.html new file mode 100644 index 00000000..cc2c9d86 --- /dev/null +++ b/packages/rsocket-examples/src/webpack/simple/client/index.html @@ -0,0 +1,11 @@ + + + + + RSocket Webpack Example + + +

RSocket Webpack Example

+
+ + diff --git a/packages/rsocket-examples/src/webpack/simple/client/index.js b/packages/rsocket-examples/src/webpack/simple/client/index.js new file mode 100644 index 00000000..2316cf11 --- /dev/null +++ b/packages/rsocket-examples/src/webpack/simple/client/index.js @@ -0,0 +1,37 @@ +import { RSocketConnector } from "rsocket-core"; +import { WebsocketClientTransport } from "rsocket-websocket-client"; + +(async () => { + const outputDiv = document.querySelector("#output"); + + const connector = new RSocketConnector({ + transport: new WebsocketClientTransport({ + url: "ws://localhost:9090", + wsCreator: (url) => new WebSocket(url), + }), + }); + + const rsocket = await connector.connect(); + + rsocket.requestResponse( + { + data: Buffer.from("Hello World"), + }, + { + onError: (e) => reject(e), + onNext: (payload, isComplete) => { + const div = document.createElement("div"); + div.textContent = `[${new Date().toISOString()}] payload[data: ${ + payload.data + }; metadata: ${payload.metadata}]|${isComplete}`; + outputDiv.appendChild(div); + }, + onComplete: () => { + const div = document.createElement("div"); + div.textContent = `Stream completed...`; + outputDiv.appendChild(div); + }, + onExtension: () => {}, + } + ); +})(); diff --git a/packages/rsocket-examples/src/webpack/simple/client/package.json b/packages/rsocket-examples/src/webpack/simple/client/package.json new file mode 100644 index 00000000..4aaef5d4 --- /dev/null +++ b/packages/rsocket-examples/src/webpack/simple/client/package.json @@ -0,0 +1,31 @@ +{ + "name": "rsocket-examples-websocket-simple-client", + "version": "0.0.0", + "license": "Apache-2.0", + "private": true, + "files": [ + "dist", + "LICENSE" + ], + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "webpack", + "serve": "webpack serve" + }, + "engines": { + "node": "^16.17.0" + }, + "devDependencies": { + "buffer": "^6.0.3", + "rsocket-adapter-rxjs": "^1.0.0-alpha.4", + "rsocket-composite-metadata": "^1.0.0-alpha.3", + "rsocket-core": "^1.0.0-alpha.3", + "rsocket-websocket-client": "^1.0.0-alpha.3", + "webpack": "^5.74.0", + "webpack-cli": "^4.10.0", + "webpack-dev-server": "^4.11.0" + }, + "dependencies": { + "html-webpack-plugin": "^5.5.0" + } +} diff --git a/packages/rsocket-examples/src/webpack/simple/client/webpack.config.js b/packages/rsocket-examples/src/webpack/simple/client/webpack.config.js new file mode 100644 index 00000000..79fef9c3 --- /dev/null +++ b/packages/rsocket-examples/src/webpack/simple/client/webpack.config.js @@ -0,0 +1,33 @@ +const path = require("path"); +const webpack = require("webpack"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); + +module.exports = { + entry: "./index.js", + mode: "development", + output: { + filename: "main.js", + path: path.resolve(__dirname, "dist"), + }, + devtool: "source-map", + devServer: { + static: { + directory: path.join(__dirname, "dist"), + }, + compress: false, + port: 9000, + }, + resolve: { + fallback: { + buffer: require.resolve("buffer/"), + }, + }, + plugins: [ + new HtmlWebpackPlugin({ + template: "./index.html", + }), + new webpack.ProvidePlugin({ + Buffer: ["buffer", "Buffer"], + }), + ], +}; diff --git a/packages/rsocket-examples/src/webpack/simple/server/package.json b/packages/rsocket-examples/src/webpack/simple/server/package.json new file mode 100644 index 00000000..be29a758 --- /dev/null +++ b/packages/rsocket-examples/src/webpack/simple/server/package.json @@ -0,0 +1,30 @@ +{ + "name": "rsocket-examples-websocket-simple-server", + "version": "0.0.0", + "license": "Apache-2.0", + "private": true, + "files": [ + "dist", + "LICENSE" + ], + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "engines": { + "node": "^16.17.0" + }, + "dependencies": { + "rsocket-adapter-rxjs": "^1.0.0-alpha.4", + "rsocket-composite-metadata": "^1.0.0-alpha.3", + "rsocket-core": "^1.0.0-alpha.3", + "rsocket-tcp-client": "^1.0.0-alpha.3", + "rsocket-tcp-server": "^1.0.0-alpha.3", + "rsocket-websocket-client": "^1.0.0-alpha.3", + "rsocket-websocket-server": "^1.0.0-alpha.3", + "ws": "~8.2.3" + }, + "devDependencies": { + + } +} diff --git a/packages/rsocket-examples/src/webpack/simple/server/server.js b/packages/rsocket-examples/src/webpack/simple/server/server.js new file mode 100644 index 00000000..24ce2924 --- /dev/null +++ b/packages/rsocket-examples/src/webpack/simple/server/server.js @@ -0,0 +1,45 @@ +const { RSocketServer } = require("rsocket-core"); +const { WebsocketServerTransport } = require("rsocket-websocket-server"); +const WebSocket = require("ws"); + +const port = 9090; + +const server = new RSocketServer({ + transport: new WebsocketServerTransport({ + wsCreator: (options) => { + return new WebSocket.Server({ + port: port, + }); + }, + }), + acceptor: { + accept: async () => ({ + requestResponse: (payload, responderStream) => { + const timeout = setTimeout( + () => + responderStream.onNext( + { + data: Buffer.concat([Buffer.from("Echo: "), payload.data]), + }, + true + ), + 1000 + ); + return { + cancel: () => { + clearTimeout(timeout); + console.log("cancelled"); + }, + onExtension: () => { + console.log("Received Extension request"); + }, + }; + }, + }), + }, +}); + +(async () => { + await server.bind(); + console.log(`Server listening on port ${port}`); +})();