2023-10-17 22:14:08 +07:00
|
|
|
/**
|
|
|
|
* Copyright 2023 Fluence Labs Limited
|
2023-02-13 17:41:35 +03:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
import type {
|
|
|
|
Env,
|
|
|
|
MarineServiceConfig,
|
|
|
|
ModuleDescriptor,
|
|
|
|
} from "@fluencelabs/marine-js/dist/config";
|
|
|
|
import { MarineService } from "@fluencelabs/marine-js/dist/MarineService";
|
|
|
|
import type {
|
|
|
|
CallParameters,
|
|
|
|
JSONArray,
|
|
|
|
JSONObject,
|
|
|
|
LogMessage,
|
|
|
|
} from "@fluencelabs/marine-js/dist/types";
|
|
|
|
import { JSONValue } from "@fluencelabs/marine-js/dist/types";
|
2023-10-25 21:38:44 +07:00
|
|
|
import { expose } from "@fluencelabs/threads/worker";
|
2023-10-17 22:14:08 +07:00
|
|
|
import { Observable, Subject } from "observable-fns";
|
|
|
|
|
|
|
|
const createSimpleModuleDescriptor = (
|
|
|
|
name: string,
|
|
|
|
envs?: Env,
|
|
|
|
): ModuleDescriptor => {
|
|
|
|
return {
|
|
|
|
import_name: name,
|
|
|
|
config: {
|
|
|
|
logger_enabled: true,
|
|
|
|
logging_mask: 0,
|
|
|
|
wasi: {
|
|
|
|
envs: { ...envs },
|
|
|
|
preopened_files: new Set(),
|
|
|
|
mapped_dirs: new Map(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const createSimpleMarineService = (
|
|
|
|
name: string,
|
|
|
|
env?: Env,
|
|
|
|
): MarineServiceConfig => {
|
|
|
|
return {
|
|
|
|
modules_config: [createSimpleModuleDescriptor(name, env)],
|
|
|
|
};
|
|
|
|
};
|
2023-08-09 15:38:40 +03:00
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
const marineServices = new Map<string, MarineService>();
|
2023-08-25 00:15:49 +07:00
|
|
|
let controlModule: WebAssembly.Module | undefined;
|
2023-02-13 17:41:35 +03:00
|
|
|
const onLogMessage = new Subject<LogMessage>();
|
|
|
|
|
|
|
|
const toExpose = {
|
2023-10-17 22:14:08 +07:00
|
|
|
init: (controlModuleWasm: ArrayBuffer | SharedArrayBuffer) => {
|
|
|
|
controlModule = new WebAssembly.Module(new Uint8Array(controlModuleWasm));
|
|
|
|
},
|
|
|
|
|
|
|
|
createService: async (
|
|
|
|
wasm: ArrayBuffer | SharedArrayBuffer,
|
|
|
|
serviceId: string,
|
|
|
|
envs?: Env,
|
|
|
|
): Promise<void> => {
|
|
|
|
if (controlModule == null) {
|
|
|
|
throw new Error(
|
|
|
|
"MarineJS is not initialized. To initialize call `init` function",
|
|
|
|
);
|
|
|
|
}
|
2023-08-25 00:15:49 +07:00
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
if (marineServices.has(serviceId)) {
|
|
|
|
throw new Error(`Service with name ${serviceId} already registered`);
|
|
|
|
}
|
2023-02-13 17:41:35 +03:00
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
const marineConfig = createSimpleMarineService(serviceId, envs);
|
|
|
|
const modules = { [serviceId]: new Uint8Array(wasm) };
|
|
|
|
|
|
|
|
const srv = new MarineService(
|
|
|
|
controlModule,
|
|
|
|
serviceId,
|
|
|
|
onLogMessage.next.bind(onLogMessage),
|
|
|
|
marineConfig,
|
|
|
|
modules,
|
|
|
|
envs,
|
|
|
|
);
|
|
|
|
|
|
|
|
await srv.init();
|
|
|
|
marineServices.set(serviceId, srv);
|
|
|
|
},
|
|
|
|
|
|
|
|
hasService: (serviceId: string) => {
|
|
|
|
return marineServices.has(serviceId);
|
|
|
|
},
|
|
|
|
|
|
|
|
removeService: (serviceId: string) => {
|
|
|
|
if (serviceId === "avm") {
|
|
|
|
throw new Error("Cannot remove 'avm' service");
|
|
|
|
}
|
2023-02-13 17:41:35 +03:00
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
marineServices.get(serviceId)?.terminate();
|
|
|
|
return marineServices.delete(serviceId);
|
|
|
|
},
|
|
|
|
|
|
|
|
terminate: () => {
|
|
|
|
marineServices.forEach((val) => {
|
|
|
|
val.terminate();
|
|
|
|
});
|
|
|
|
|
|
|
|
marineServices.clear();
|
|
|
|
onLogMessage.complete();
|
|
|
|
},
|
|
|
|
|
|
|
|
callService: (
|
|
|
|
serviceId: string,
|
|
|
|
functionName: string,
|
|
|
|
args: JSONArray | JSONObject,
|
|
|
|
callParams: CallParameters,
|
|
|
|
) => {
|
|
|
|
const srv = marineServices.get(serviceId);
|
|
|
|
|
|
|
|
if (srv == null) {
|
|
|
|
throw new Error(`service with id=${serviceId} not found`);
|
|
|
|
}
|
2023-02-13 17:41:35 +03:00
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
// TODO: Make MarineService return JSONValue type
|
|
|
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
|
|
return srv.call(functionName, args, callParams) as JSONValue;
|
|
|
|
},
|
2023-02-13 17:41:35 +03:00
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
onLogMessage() {
|
|
|
|
return Observable.from(onLogMessage);
|
|
|
|
},
|
2023-08-25 00:15:49 +07:00
|
|
|
};
|
|
|
|
|
2023-10-17 22:14:08 +07:00
|
|
|
export type MarineBackgroundInterface = typeof toExpose;
|
2023-02-13 17:41:35 +03:00
|
|
|
|
|
|
|
expose(toExpose);
|