mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2024-12-04 18:00:18 +00:00
feat: Support instance context [fixes DXJ-541] (#392)
* Support context * Update doc * Refactor * Cover by doc * Fix lint
This commit is contained in:
parent
44eb1493b3
commit
1578b791ac
12
README.md
12
README.md
@ -164,6 +164,18 @@ localStorage.debug = "fluence:*";
|
||||
In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will be default—only to show
|
||||
messages logged by debug if the "Verbose" log level is enabled.
|
||||
|
||||
## Low level usage
|
||||
|
||||
JS client also has an API for low level interaction with AVM and Marine JS.
|
||||
It could be handy in advanced scenarios when a user fetches AIR dynamically or generates AIR without default Aqua compiler.
|
||||
|
||||
`callAquaFunction` Allows to call aqua function without schema.
|
||||
|
||||
`registerService` Gives an ability to register service without schema. Passed `service` could be
|
||||
|
||||
- Plain object. In this case all function properties will be registered as AIR service functions.
|
||||
- Class instance. All class methods without inherited ones will be registered as AIR service functions.
|
||||
|
||||
## Development
|
||||
|
||||
To hack on the Fluence JS Client itself, please refer to the [development page](./DEVELOPING.md).
|
||||
|
16
packages/core/js-client/aqua/calc.aqua
Normal file
16
packages/core/js-client/aqua/calc.aqua
Normal file
@ -0,0 +1,16 @@
|
||||
service Calc("calc"):
|
||||
add(n: f32)
|
||||
subtract(n: f32)
|
||||
multiply(n: f32)
|
||||
divide(n: f32)
|
||||
reset()
|
||||
getResult() -> f32
|
||||
|
||||
|
||||
func demoCalc() -> f32:
|
||||
Calc.add(10)
|
||||
Calc.multiply(5)
|
||||
Calc.subtract(8)
|
||||
Calc.divide(6)
|
||||
res <- Calc.getResult()
|
||||
<- res
|
84
packages/core/js-client/src/api.spec.ts
Normal file
84
packages/core/js-client/src/api.spec.ts
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* 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 { fileURLToPath } from "url";
|
||||
|
||||
import { compileFromPath } from "@fluencelabs/aqua-api";
|
||||
import { ServiceDef } from "@fluencelabs/interfaces";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { v5_registerService } from "./api.js";
|
||||
import { callAquaFunction } from "./compilerSupport/callFunction.js";
|
||||
import { withPeer } from "./util/testUtils.js";
|
||||
|
||||
class CalcParent {
|
||||
protected _state: number = 0;
|
||||
|
||||
add(n: number) {
|
||||
this._state += n;
|
||||
}
|
||||
|
||||
subtract(n: number) {
|
||||
this._state -= n;
|
||||
}
|
||||
}
|
||||
|
||||
class Calc extends CalcParent {
|
||||
multiply(n: number) {
|
||||
this._state *= n;
|
||||
}
|
||||
|
||||
divide(n: number) {
|
||||
this._state /= n;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._state = 0;
|
||||
}
|
||||
|
||||
getResult() {
|
||||
return this._state;
|
||||
}
|
||||
}
|
||||
|
||||
describe("User API methods", () => {
|
||||
it("registers user class service and calls own and inherited methods correctly", async () => {
|
||||
await withPeer(async (peer) => {
|
||||
const calcService: Record<never, unknown> = new Calc();
|
||||
|
||||
const { functions, services } = await compileFromPath({
|
||||
filePath: fileURLToPath(new URL("../aqua/calc.aqua", import.meta.url)),
|
||||
});
|
||||
|
||||
const typedServices: Record<string, ServiceDef> = services;
|
||||
|
||||
const { script } = functions["demoCalc"];
|
||||
|
||||
v5_registerService([peer, "calc", calcService], {
|
||||
defaultServiceId: "calc",
|
||||
functions: typedServices["Calc"].functions,
|
||||
});
|
||||
|
||||
const res = await callAquaFunction({
|
||||
args: {},
|
||||
peer,
|
||||
script,
|
||||
});
|
||||
|
||||
expect(res).toBe(7);
|
||||
});
|
||||
});
|
||||
});
|
@ -202,10 +202,16 @@ export const v5_registerService = (
|
||||
// Schema for every function in service
|
||||
const serviceSchema = def.functions.tag === "nil" ? {} : def.functions.fields;
|
||||
|
||||
// Wrapping service impl to convert their args ts -> aqua and backwards
|
||||
// Wrapping service functions, selecting only those listed in schema, to convert their args js -> aqua and backwards
|
||||
const wrappedServiceImpl = Object.fromEntries(
|
||||
Object.entries(serviceImpl).map(([name, func]) => {
|
||||
return [name, wrapJsFunction(func, serviceSchema[name])];
|
||||
Object.keys(serviceSchema).map((schemaKey) => {
|
||||
return [
|
||||
schemaKey,
|
||||
wrapJsFunction(
|
||||
serviceImpl[schemaKey].bind(serviceImpl),
|
||||
serviceSchema[schemaKey],
|
||||
),
|
||||
] as const;
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -46,7 +46,7 @@ const log = logger("aqua");
|
||||
|
||||
export type CallAquaFunctionArgs = {
|
||||
script: string;
|
||||
config: CallAquaFunctionConfig | undefined;
|
||||
config?: CallAquaFunctionConfig | undefined;
|
||||
peer: FluencePeer;
|
||||
args: { [key: string]: JSONValue | ArgCallbackFunction };
|
||||
};
|
||||
|
@ -28,27 +28,22 @@ interface RegisterServiceArgs {
|
||||
service: ServiceImpl;
|
||||
}
|
||||
|
||||
// This function iterates on plain object or class instance functions ignoring inherited functions and prototype chain.
|
||||
const findAllPossibleRegisteredServiceFunctions = (
|
||||
service: ServiceImpl,
|
||||
): Set<string> => {
|
||||
let prototype: Record<string, unknown> = service;
|
||||
const serviceMethods = new Set<string>();
|
||||
): Array<string> => {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const prototype = Object.getPrototypeOf(service) as ServiceImpl;
|
||||
|
||||
do {
|
||||
Object.getOwnPropertyNames(prototype)
|
||||
.filter((prop) => {
|
||||
return typeof prototype[prop] === "function" && prop !== "constructor";
|
||||
})
|
||||
.forEach((prop) => {
|
||||
return serviceMethods.add(prop);
|
||||
});
|
||||
const isClassInstance = prototype.constructor !== Object;
|
||||
|
||||
// coercing 'any' type to 'Record' bcs object prototype is actually an object
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
prototype = Object.getPrototypeOf(prototype) as Record<string, unknown>;
|
||||
} while (prototype.constructor !== Object);
|
||||
if (isClassInstance) {
|
||||
service = prototype;
|
||||
}
|
||||
|
||||
return serviceMethods;
|
||||
return Object.getOwnPropertyNames(service).filter((prop) => {
|
||||
return typeof service[prop] === "function" && prop !== "constructor";
|
||||
});
|
||||
};
|
||||
|
||||
export const registerService = ({
|
||||
|
@ -14,13 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { it, describe, expect, beforeEach, afterEach } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
import { DEFAULT_CONFIG, FluencePeer } from "../../jsPeer/FluencePeer.js";
|
||||
import { ResultCodes } from "../../jsServiceHost/interfaces.js";
|
||||
import { KeyPair } from "../../keypair/index.js";
|
||||
import { loadMarineDeps } from "../../marine/loader.js";
|
||||
import { MarineBackgroundRunner } from "../../marine/worker/index.js";
|
||||
import { EphemeralNetworkClient } from "../client.js";
|
||||
import { EphemeralNetwork, defaultConfig } from "../network.js";
|
||||
import { defaultConfig, EphemeralNetwork } from "../network.js";
|
||||
|
||||
let en: EphemeralNetwork;
|
||||
let client: FluencePeer;
|
||||
@ -33,7 +35,11 @@ describe.skip("Ephemeral networks tests", () => {
|
||||
await en.up();
|
||||
|
||||
const kp = await KeyPair.randomEd25519();
|
||||
client = new EphemeralNetworkClient(DEFAULT_CONFIG, kp, en, relay);
|
||||
|
||||
const marineDeps = await loadMarineDeps("/");
|
||||
const marine = new MarineBackgroundRunner(...marineDeps);
|
||||
|
||||
client = new EphemeralNetworkClient(DEFAULT_CONFIG, kp, marine, en, relay);
|
||||
await client.start();
|
||||
});
|
||||
|
||||
|
@ -15,13 +15,11 @@
|
||||
*/
|
||||
|
||||
import { PeerIdB58 } from "@fluencelabs/interfaces";
|
||||
import { fetchResource } from "@fluencelabs/js-client-isomorphic/fetcher";
|
||||
import { getWorker } from "@fluencelabs/js-client-isomorphic/worker-resolver";
|
||||
|
||||
import { FluencePeer, PeerConfig } from "../jsPeer/FluencePeer.js";
|
||||
import { JsServiceHost } from "../jsServiceHost/JsServiceHost.js";
|
||||
import { KeyPair } from "../keypair/index.js";
|
||||
import { MarineBackgroundRunner } from "../marine/worker/index.js";
|
||||
import { IMarineHost } from "../marine/interfaces.js";
|
||||
|
||||
import { EphemeralNetwork } from "./network.js";
|
||||
|
||||
@ -32,63 +30,12 @@ export class EphemeralNetworkClient extends FluencePeer {
|
||||
constructor(
|
||||
config: PeerConfig,
|
||||
keyPair: KeyPair,
|
||||
marine: IMarineHost,
|
||||
network: EphemeralNetwork,
|
||||
relay: PeerIdB58,
|
||||
) {
|
||||
const conn = network.getRelayConnection(keyPair.getPeerId(), relay);
|
||||
|
||||
let marineJsWasm: ArrayBuffer;
|
||||
let avmWasm: ArrayBuffer;
|
||||
|
||||
const marine = new MarineBackgroundRunner(
|
||||
{
|
||||
async getValue() {
|
||||
// TODO: load worker in parallel with avm and marine, test that it works
|
||||
return getWorker("@fluencelabs/marine-worker", "/");
|
||||
},
|
||||
start() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return marineJsWasm;
|
||||
},
|
||||
async start(): Promise<void> {
|
||||
marineJsWasm = await fetchResource(
|
||||
"@fluencelabs/marine-js",
|
||||
"/dist/marine-js.wasm",
|
||||
"/",
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
});
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return avmWasm;
|
||||
},
|
||||
async start(): Promise<void> {
|
||||
avmWasm = await fetchResource(
|
||||
"@fluencelabs/avm",
|
||||
"/dist/avm.wasm",
|
||||
"/",
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
});
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
super(config, keyPair, marine, new JsServiceHost(), conn);
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
|
||||
import { PeerIdB58 } from "@fluencelabs/interfaces";
|
||||
import { fetchResource } from "@fluencelabs/js-client-isomorphic/fetcher";
|
||||
import { getWorker } from "@fluencelabs/js-client-isomorphic/worker-resolver";
|
||||
import { Subject } from "rxjs";
|
||||
|
||||
import { IConnection } from "../connection/interfaces.js";
|
||||
@ -24,6 +22,7 @@ import { DEFAULT_CONFIG, FluencePeer } from "../jsPeer/FluencePeer.js";
|
||||
import { JsServiceHost } from "../jsServiceHost/JsServiceHost.js";
|
||||
import { fromBase64Sk, KeyPair } from "../keypair/index.js";
|
||||
import { IMarineHost } from "../marine/interfaces.js";
|
||||
import { loadMarineDeps } from "../marine/loader.js";
|
||||
import { MarineBackgroundRunner } from "../marine/worker/index.js";
|
||||
import { Particle } from "../particle/Particle.js";
|
||||
import { logger } from "../util/logger.js";
|
||||
@ -233,55 +232,8 @@ export class EphemeralNetwork {
|
||||
const promises = this.config.peers.map(async (x) => {
|
||||
const kp = await fromBase64Sk(x.sk);
|
||||
|
||||
const [marineJsWasm, avmWasm] = await Promise.all([
|
||||
fetchResource(
|
||||
"@fluencelabs/marine-js",
|
||||
"/dist/marine-js.wasm",
|
||||
"/",
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
}),
|
||||
fetchResource("@fluencelabs/avm", "/dist/avm.wasm", "/").then((res) => {
|
||||
return res.arrayBuffer();
|
||||
}),
|
||||
]);
|
||||
|
||||
const marine = new MarineBackgroundRunner(
|
||||
{
|
||||
async getValue() {
|
||||
// TODO: load worker in parallel with avm and marine, test that it works
|
||||
return getWorker("@fluencelabs/marine-worker", "/");
|
||||
},
|
||||
start() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return marineJsWasm;
|
||||
},
|
||||
start(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return avmWasm;
|
||||
},
|
||||
start(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
);
|
||||
const marineDeps = await loadMarineDeps("/");
|
||||
const marine = new MarineBackgroundRunner(...marineDeps);
|
||||
|
||||
const peerId = kp.getPeerId();
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { fetchResource } from "@fluencelabs/js-client-isomorphic/fetcher";
|
||||
import { getWorker } from "@fluencelabs/js-client-isomorphic/worker-resolver";
|
||||
import { ZodError } from "zod";
|
||||
|
||||
import { ClientPeer, makeClientPeerConfig } from "./clientPeer/ClientPeer.js";
|
||||
@ -28,6 +26,7 @@ import {
|
||||
} from "./clientPeer/types.js";
|
||||
import { callAquaFunction } from "./compilerSupport/callFunction.js";
|
||||
import { registerService } from "./compilerSupport/registerService.js";
|
||||
import { loadMarineDeps } from "./marine/loader.js";
|
||||
import { MarineBackgroundRunner } from "./marine/worker/index.js";
|
||||
|
||||
const DEFAULT_CDN_URL = "https://unpkg.com";
|
||||
@ -47,55 +46,8 @@ const createClient = async (
|
||||
|
||||
const CDNUrl = config.CDNUrl ?? DEFAULT_CDN_URL;
|
||||
|
||||
const [marineJsWasm, avmWasm] = await Promise.all([
|
||||
fetchResource(
|
||||
"@fluencelabs/marine-js",
|
||||
"/dist/marine-js.wasm",
|
||||
CDNUrl,
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
}),
|
||||
fetchResource("@fluencelabs/avm", "/dist/avm.wasm", CDNUrl).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
}),
|
||||
]);
|
||||
|
||||
const marine = new MarineBackgroundRunner(
|
||||
{
|
||||
async getValue() {
|
||||
// TODO: load worker in parallel with avm and marine, test that it works
|
||||
return getWorker("@fluencelabs/marine-worker", CDNUrl);
|
||||
},
|
||||
start() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return marineJsWasm;
|
||||
},
|
||||
start(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return avmWasm;
|
||||
},
|
||||
start(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
);
|
||||
const marineDeps = await loadMarineDeps(CDNUrl);
|
||||
const marine = new MarineBackgroundRunner(...marineDeps);
|
||||
|
||||
const { keyPair, peerConfig, relayConfig } = await makeClientPeerConfig(
|
||||
relay,
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
import { JSONObject, JSONValue, JSONArray } from "@fluencelabs/interfaces";
|
||||
import { CallParameters } from "@fluencelabs/marine-worker";
|
||||
import type { Worker as WorkerImplementation } from "@fluencelabs/threads/master";
|
||||
|
||||
import { IStartable } from "../util/commonTypes.js";
|
||||
|
||||
@ -52,24 +51,3 @@ export interface IMarineHost extends IStartable {
|
||||
callParams?: CallParameters,
|
||||
): Promise<JSONValue>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for something which can hold a value
|
||||
*/
|
||||
export interface IValueLoader<T> {
|
||||
getValue(): T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for something which can load wasm files
|
||||
*/
|
||||
export interface IWasmLoader
|
||||
extends IValueLoader<ArrayBuffer | SharedArrayBuffer>,
|
||||
IStartable {}
|
||||
|
||||
/**
|
||||
* Interface for something which can thread.js based worker
|
||||
*/
|
||||
export interface IWorkerLoader
|
||||
extends IValueLoader<WorkerImplementation | Promise<WorkerImplementation>>,
|
||||
IStartable {}
|
||||
|
47
packages/core/js-client/src/marine/loader.ts
Normal file
47
packages/core/js-client/src/marine/loader.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* 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 { fetchResource } from "@fluencelabs/js-client-isomorphic/fetcher";
|
||||
import { getWorker } from "@fluencelabs/js-client-isomorphic/worker-resolver";
|
||||
import { Worker } from "@fluencelabs/threads/master";
|
||||
|
||||
type StrategyReturnType = [
|
||||
marineJsWasm: ArrayBuffer,
|
||||
avmWasm: ArrayBuffer,
|
||||
worker: Worker,
|
||||
];
|
||||
|
||||
export const loadMarineDeps = async (
|
||||
CDNUrl: string,
|
||||
): Promise<StrategyReturnType> => {
|
||||
const [marineJsWasm, avmWasm] = await Promise.all([
|
||||
fetchResource(
|
||||
"@fluencelabs/marine-js",
|
||||
"/dist/marine-js.wasm",
|
||||
CDNUrl,
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
}),
|
||||
fetchResource("@fluencelabs/avm", "/dist/avm.wasm", CDNUrl).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
}),
|
||||
]);
|
||||
|
||||
// TODO: load worker in parallel with avm and marine, test that it works
|
||||
const worker = await getWorker("@fluencelabs/marine-worker", CDNUrl);
|
||||
|
||||
return [marineJsWasm, avmWasm, worker];
|
||||
};
|
@ -21,10 +21,15 @@ import type {
|
||||
JSONValueNonNullable,
|
||||
CallParameters,
|
||||
} from "@fluencelabs/marine-worker";
|
||||
import { ModuleThread, Thread, spawn } from "@fluencelabs/threads/master";
|
||||
import {
|
||||
ModuleThread,
|
||||
Thread,
|
||||
spawn,
|
||||
Worker,
|
||||
} from "@fluencelabs/threads/master";
|
||||
|
||||
import { MarineLogger, marineLogger } from "../../util/logger.js";
|
||||
import { IMarineHost, IWasmLoader, IWorkerLoader } from "../interfaces.js";
|
||||
import { IMarineHost } from "../interfaces.js";
|
||||
|
||||
export class MarineBackgroundRunner implements IMarineHost {
|
||||
private workerThread?: ModuleThread<MarineBackgroundInterface>;
|
||||
@ -32,9 +37,9 @@ export class MarineBackgroundRunner implements IMarineHost {
|
||||
private loggers = new Map<string, MarineLogger>();
|
||||
|
||||
constructor(
|
||||
private workerLoader: IWorkerLoader,
|
||||
private controlModuleLoader: IWasmLoader,
|
||||
private avmWasmLoader: IWasmLoader,
|
||||
private marineJsWasm: ArrayBuffer,
|
||||
private avmWasm: ArrayBuffer,
|
||||
private worker: Worker,
|
||||
) {}
|
||||
|
||||
async hasService(serviceId: string) {
|
||||
@ -58,16 +63,8 @@ export class MarineBackgroundRunner implements IMarineHost {
|
||||
throw new Error("Worker thread already initialized");
|
||||
}
|
||||
|
||||
await this.controlModuleLoader.start();
|
||||
const wasm = this.controlModuleLoader.getValue();
|
||||
|
||||
await this.avmWasmLoader.start();
|
||||
|
||||
await this.workerLoader.start();
|
||||
const worker = await this.workerLoader.getValue();
|
||||
|
||||
const workerThread: ModuleThread<MarineBackgroundInterface> =
|
||||
await spawn<MarineBackgroundInterface>(worker);
|
||||
await spawn<MarineBackgroundInterface>(this.worker);
|
||||
|
||||
const logfn: LogFunction = (message) => {
|
||||
const serviceLogger = this.loggers.get(message.service);
|
||||
@ -80,9 +77,9 @@ export class MarineBackgroundRunner implements IMarineHost {
|
||||
};
|
||||
|
||||
workerThread.onLogMessage().subscribe(logfn);
|
||||
await workerThread.init(wasm);
|
||||
await workerThread.init(this.marineJsWasm);
|
||||
this.workerThread = workerThread;
|
||||
await this.createService(this.avmWasmLoader.getValue(), "avm");
|
||||
await this.createService(this.avmWasm, "avm");
|
||||
}
|
||||
|
||||
async createService(
|
||||
|
@ -23,8 +23,6 @@ import {
|
||||
JSONValue,
|
||||
ServiceDef,
|
||||
} from "@fluencelabs/interfaces";
|
||||
import { fetchResource } from "@fluencelabs/js-client-isomorphic/fetcher";
|
||||
import { getWorker } from "@fluencelabs/js-client-isomorphic/worker-resolver";
|
||||
import { Subject, Subscribable } from "rxjs";
|
||||
|
||||
import { ClientPeer, makeClientPeerConfig } from "../clientPeer/ClientPeer.js";
|
||||
@ -40,6 +38,8 @@ import {
|
||||
import { JsServiceHost } from "../jsServiceHost/JsServiceHost.js";
|
||||
import { WrapFnIntoServiceCall } from "../jsServiceHost/serviceUtils.js";
|
||||
import { KeyPair } from "../keypair/index.js";
|
||||
import { IMarineHost } from "../marine/interfaces.js";
|
||||
import { loadMarineDeps } from "../marine/loader.js";
|
||||
import { MarineBackgroundRunner } from "../marine/worker/index.js";
|
||||
import { Particle } from "../particle/Particle.js";
|
||||
|
||||
@ -146,61 +146,9 @@ class NoopConnection implements IConnection {
|
||||
}
|
||||
|
||||
export class TestPeer extends FluencePeer {
|
||||
constructor(keyPair: KeyPair, connection: IConnection) {
|
||||
constructor(keyPair: KeyPair, connection: IConnection, marine: IMarineHost) {
|
||||
const jsHost = new JsServiceHost();
|
||||
|
||||
let marineJsWasm: ArrayBuffer;
|
||||
let avmWasm: ArrayBuffer;
|
||||
|
||||
const marine = new MarineBackgroundRunner(
|
||||
{
|
||||
async getValue() {
|
||||
// TODO: load worker in parallel with avm and marine, test that it works
|
||||
return getWorker("@fluencelabs/marine-worker", "/");
|
||||
},
|
||||
start() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return marineJsWasm;
|
||||
},
|
||||
async start(): Promise<void> {
|
||||
marineJsWasm = await fetchResource(
|
||||
"@fluencelabs/marine-js",
|
||||
"/dist/marine-js.wasm",
|
||||
"/",
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
});
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return avmWasm;
|
||||
},
|
||||
async start(): Promise<void> {
|
||||
avmWasm = await fetchResource(
|
||||
"@fluencelabs/avm",
|
||||
"/dist/avm.wasm",
|
||||
"/",
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
});
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
super(DEFAULT_CONFIG, keyPair, marine, jsHost, connection);
|
||||
}
|
||||
}
|
||||
@ -208,7 +156,11 @@ export class TestPeer extends FluencePeer {
|
||||
export const mkTestPeer = async () => {
|
||||
const kp = await KeyPair.randomEd25519();
|
||||
const conn = new NoopConnection();
|
||||
return new TestPeer(kp, conn);
|
||||
|
||||
const marineDeps = await loadMarineDeps("/");
|
||||
const marine = new MarineBackgroundRunner(...marineDeps);
|
||||
|
||||
return new TestPeer(kp, conn, marine);
|
||||
};
|
||||
|
||||
export const withPeer = async (action: (p: FluencePeer) => Promise<void>) => {
|
||||
@ -232,57 +184,8 @@ export const withClient = async (
|
||||
config,
|
||||
);
|
||||
|
||||
let marineJsWasm: ArrayBuffer;
|
||||
let avmWasm: ArrayBuffer;
|
||||
|
||||
const marine = new MarineBackgroundRunner(
|
||||
{
|
||||
async getValue() {
|
||||
// TODO: load worker in parallel with avm and marine, test that it works
|
||||
return getWorker("@fluencelabs/marine-worker", "/");
|
||||
},
|
||||
start() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
stop() {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return marineJsWasm;
|
||||
},
|
||||
async start(): Promise<void> {
|
||||
marineJsWasm = await fetchResource(
|
||||
"@fluencelabs/marine-js",
|
||||
"/dist/marine-js.wasm",
|
||||
"/",
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
});
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
{
|
||||
getValue() {
|
||||
return avmWasm;
|
||||
},
|
||||
async start(): Promise<void> {
|
||||
avmWasm = await fetchResource(
|
||||
"@fluencelabs/avm",
|
||||
"/dist/avm.wasm",
|
||||
"/",
|
||||
).then((res) => {
|
||||
return res.arrayBuffer();
|
||||
});
|
||||
},
|
||||
stop(): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
},
|
||||
);
|
||||
const marineDeps = await loadMarineDeps("/");
|
||||
const marine = new MarineBackgroundRunner(...marineDeps);
|
||||
|
||||
const client = new ClientPeer(peerConfig, relayConfig, keyPair, marine);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user