Enabling Profiling and small bug-fixes
This commit is contained in:
parent
2cd0ff596f
commit
bb89d6b3b5
@ -5,8 +5,8 @@ SETLOCAL
|
|||||||
echo Compiling Backend
|
echo Compiling Backend
|
||||||
|
|
||||||
REM Add the Node Options for SSL these are requrired since Node v.17
|
REM Add the Node Options for SSL these are requrired since Node v.17
|
||||||
set NODE_OPTIONS=--openssl-legacy-provider
|
REM set NODE_OPTIONS=--openssl-legacy-provider
|
||||||
call $env:NODE_OPTIONS="--openssl-legacy-provider"
|
REM call $env:NODE_OPTIONS="--openssl-legacy-provider"
|
||||||
|
|
||||||
|
|
||||||
(npm run-script prettier-format) && (
|
(npm run-script prettier-format) && (
|
||||||
|
30
05-link.bat
30
05-link.bat
@ -4,4 +4,32 @@ cd "%DIR%"
|
|||||||
|
|
||||||
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
|
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
|
||||||
|
|
||||||
npm link
|
(npm link) && (
|
||||||
|
node contribute/toLinkBrowser.js
|
||||||
|
|
||||||
|
cp ./package.json ./build/package.json
|
||||||
|
|
||||||
|
cd ./build
|
||||||
|
|
||||||
|
(npm link) && (
|
||||||
|
cd "%DIR%"
|
||||||
|
node contribute/toNodejs.js
|
||||||
|
) || (
|
||||||
|
cd "%DIR%"
|
||||||
|
node contribute/toNodejs.js
|
||||||
|
)
|
||||||
|
) || (
|
||||||
|
node contribute/toLinkBrowser.js
|
||||||
|
|
||||||
|
cp ./package.json ./build/package.json
|
||||||
|
|
||||||
|
cd ./build
|
||||||
|
|
||||||
|
(npm link) && (
|
||||||
|
cd "%DIR%"
|
||||||
|
node contribute/toNodejs.js
|
||||||
|
) || (
|
||||||
|
cd "%DIR%"
|
||||||
|
node contribute/toNodejs.js
|
||||||
|
)
|
||||||
|
)
|
@ -1 +1 @@
|
|||||||
1.0.21
|
1.0.24
|
28
contribute/toLinkBrowser.js
Normal file
28
contribute/toLinkBrowser.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* @author Martin Karkowski
|
||||||
|
* @email m.karkowski@zema.de
|
||||||
|
* @create date 2022-01-18 13:42:41
|
||||||
|
* @modify date 2022-03-18 08:56:20
|
||||||
|
* @desc [description]
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { readFileSync, writeFileSync } = require("fs");
|
||||||
|
|
||||||
|
const version = readFileSync("./contribute/VERSION", { encoding: "utf-8" });
|
||||||
|
const package = JSON.parse(readFileSync("./package.json", { encoding: "utf-8" }));
|
||||||
|
|
||||||
|
package.description = "NoPE Runtime for the Browser";
|
||||||
|
delete package.main;
|
||||||
|
delete package.browser;
|
||||||
|
delete package.bin;
|
||||||
|
|
||||||
|
package.name = "nope-browser"
|
||||||
|
package.browser = "nope.js";
|
||||||
|
package.main = "nope.js";
|
||||||
|
package.version = version;
|
||||||
|
|
||||||
|
package.files = [
|
||||||
|
"*",
|
||||||
|
];
|
||||||
|
|
||||||
|
writeFileSync("./package.json", JSON.stringify(package, undefined, 2), { encoding: "utf-8" });
|
27
helpers/convert_ticks.js
Normal file
27
helpers/convert_ticks.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* to run the
|
||||||
|
* https://nodejs.org/en/docs/guides/simple-profiling/
|
||||||
|
*/
|
||||||
|
|
||||||
|
const listFiles = require('../dist-nodejs/helpers/fileMethods').listFiles;
|
||||||
|
const { exec } = require("child_process");
|
||||||
|
const { promisify } = require("util")
|
||||||
|
|
||||||
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const tick_files = await listFiles("./", "-v8.log")
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
for (const file in tick_files) {
|
||||||
|
console.log(`converting ${file}`)
|
||||||
|
promises.push(
|
||||||
|
execAsync(`node --prof-process ${file} > ${file}.txt`)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(console.error)
|
@ -25,6 +25,7 @@ import { generateLogfilePath, useLogFile } from "../logger/fileLogging";
|
|||||||
import { getNopeLogger } from "../logger/getLogger";
|
import { getNopeLogger } from "../logger/getLogger";
|
||||||
import { LoggerLevel, LoggerLevels } from "../logger/nopeLogger";
|
import { LoggerLevel, LoggerLevels } from "../logger/nopeLogger";
|
||||||
import { setGlobalLoggerLevel } from "../logger/setGlobalLoggerLevel";
|
import { setGlobalLoggerLevel } from "../logger/setGlobalLoggerLevel";
|
||||||
|
import { recordCPUProfile } from "../profiling/index.nodejs";
|
||||||
import {
|
import {
|
||||||
INopeINopeConnectivityTimeOptions,
|
INopeINopeConnectivityTimeOptions,
|
||||||
ValidDefaultSelectors,
|
ValidDefaultSelectors,
|
||||||
@ -60,6 +61,8 @@ export interface RunArgs {
|
|||||||
forceSelectors: boolean;
|
forceSelectors: boolean;
|
||||||
// The Id to use.
|
// The Id to use.
|
||||||
id: string;
|
id: string;
|
||||||
|
// Flag to enable profiling. Defaults to false.
|
||||||
|
profile: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: RunArgs = {
|
export const DEFAULT_SETTINGS: RunArgs = {
|
||||||
@ -78,6 +81,7 @@ export const DEFAULT_SETTINGS: RunArgs = {
|
|||||||
forceUsingSelectors: false,
|
forceUsingSelectors: false,
|
||||||
logToFile: false,
|
logToFile: false,
|
||||||
id: generateId(),
|
id: generateId(),
|
||||||
|
profile: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,6 +218,13 @@ export async function readInArgs(
|
|||||||
dest: "communicationLogLevel",
|
dest: "communicationLogLevel",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
parser.add_argument("--profile", {
|
||||||
|
help: "Flag to enable Profiling",
|
||||||
|
action: "append",
|
||||||
|
nargs: "?",
|
||||||
|
dest: "profile",
|
||||||
|
});
|
||||||
|
|
||||||
const args: RunArgs = parser.parse_args();
|
const args: RunArgs = parser.parse_args();
|
||||||
|
|
||||||
if (args.params === "not-provided") {
|
if (args.params === "not-provided") {
|
||||||
@ -221,6 +232,7 @@ export async function readInArgs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.skipLoadingConfig = Array.isArray(args.skipLoadingConfig);
|
args.skipLoadingConfig = Array.isArray(args.skipLoadingConfig);
|
||||||
|
args.profile = Array.isArray(args.profile);
|
||||||
args.logToFile = Array.isArray(args.logToFile);
|
args.logToFile = Array.isArray(args.logToFile);
|
||||||
args.forceUsingSelectors = Array.isArray(args.forceUsingSelectors);
|
args.forceUsingSelectors = Array.isArray(args.forceUsingSelectors);
|
||||||
|
|
||||||
@ -243,6 +255,8 @@ export async function runNopeBackend(
|
|||||||
|
|
||||||
const args = Object.assign(_defaultSettings, _args);
|
const args = Object.assign(_defaultSettings, _args);
|
||||||
|
|
||||||
|
const closeCallbacks = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Try to read in the default config file.
|
// Try to read in the default config file.
|
||||||
opts = JSON.parse(
|
opts = JSON.parse(
|
||||||
@ -256,7 +270,7 @@ export async function runNopeBackend(
|
|||||||
|
|
||||||
if (args.logToFile) {
|
if (args.logToFile) {
|
||||||
const fileName = generateLogfilePath("run");
|
const fileName = generateLogfilePath("run");
|
||||||
useLogFile(fileName, 10);
|
closeCallbacks.push(useLogFile(fileName, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoggerLevels.includes(args.log)) {
|
if (LoggerLevels.includes(args.log)) {
|
||||||
@ -266,6 +280,11 @@ export async function runNopeBackend(
|
|||||||
// Define a Logger
|
// Define a Logger
|
||||||
const logger = getNopeLogger("starter");
|
const logger = getNopeLogger("starter");
|
||||||
|
|
||||||
|
if (args.profile) {
|
||||||
|
logger.warn("Enabled Profiling.");
|
||||||
|
closeCallbacks.push(recordCPUProfile());
|
||||||
|
}
|
||||||
|
|
||||||
if (!Object.getOwnPropertyNames(validLayers).includes(args.channel)) {
|
if (!Object.getOwnPropertyNames(validLayers).includes(args.channel)) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"Invalid Channel. Please use the following values. " +
|
"Invalid Channel. Please use the following values. " +
|
||||||
@ -286,6 +305,46 @@ export async function runNopeBackend(
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _closing = false;
|
||||||
|
const _dispose = (reason?, p?) => {
|
||||||
|
if (_closing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_closing = true;
|
||||||
|
|
||||||
|
if (reason) {
|
||||||
|
// If there is a reason
|
||||||
|
logger.error("Unhandled Rejection at: Promise", p, "reason:", reason);
|
||||||
|
logger.error(reason);
|
||||||
|
} else {
|
||||||
|
// We should close the Process:
|
||||||
|
logger.warn("received 'ctrl+c'. Shutting down the Instances");
|
||||||
|
}
|
||||||
|
// Exit the Process
|
||||||
|
const promises = [];
|
||||||
|
for (const callback of closeCallbacks) {
|
||||||
|
try {
|
||||||
|
promises.push(callback());
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("During exiting, an error occourd");
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wait for all Promises to finish.
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Subscribe to unhandled Reactions.
|
||||||
|
process.on("unhandledRejection", (reason, p) => _dispose(reason, p));
|
||||||
|
process.on("SIGINT", () => _dispose());
|
||||||
|
process.on("SIGTERM", () => _dispose());
|
||||||
|
process.on("exit", () => {
|
||||||
|
logger.info("Completed. Goodbye");
|
||||||
|
});
|
||||||
|
|
||||||
// Assign the Default Setting for the Channel.
|
// Assign the Default Setting for the Channel.
|
||||||
opts.params = layerDefaultParameters[args.channel];
|
opts.params = layerDefaultParameters[args.channel];
|
||||||
|
|
||||||
@ -336,38 +395,34 @@ export async function runNopeBackend(
|
|||||||
},
|
},
|
||||||
_args.singleton
|
_args.singleton
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add the Dispatcher
|
||||||
|
closeCallbacks.push(async () => {
|
||||||
|
await loader.dispatcher.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
// If required load all Packages.
|
||||||
|
if (!args.skipLoadingConfig) {
|
||||||
|
// Try to load the Modules.
|
||||||
|
|
||||||
|
if (args.delay > 0) {
|
||||||
|
logger.info(`Waiting ${args.delay} [s] to get all information.`);
|
||||||
|
await sleep(args.delay * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.info("loading Packages");
|
||||||
|
await loadPackages(loader, args.file, args.delay);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("Unable to load the Packages defined in " + args.file);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
getNopeLogger("cli", "info").error("failed to load the Packages", e);
|
getNopeLogger("cli", "info").error("failed to load the Packages", e);
|
||||||
|
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If required load all Packages.
|
|
||||||
if (!args.skipLoadingConfig) {
|
|
||||||
// Try to load the Modules.
|
|
||||||
|
|
||||||
if (args.delay > 0) {
|
|
||||||
logger.info(`Waiting ${args.delay} [s] to get all information.`);
|
|
||||||
await sleep(args.delay * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
logger.info("loading Packages");
|
|
||||||
await loadPackages(loader, args.file, args.delay);
|
|
||||||
} catch (e) {
|
|
||||||
logger.error("Unable to load the Packages defined in " + args.file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const _dispose = () => {
|
|
||||||
// We should close the Process:
|
|
||||||
logger.warn("received 'ctrl+c'. Shutting down the Instances");
|
|
||||||
loader.dispatcher.dispose().finally(process.exit);
|
|
||||||
};
|
|
||||||
|
|
||||||
process.on("SIGINT", _dispose);
|
|
||||||
process.on("SIGTERM", _dispose);
|
|
||||||
process.on("exit", () => {
|
|
||||||
logger.info("Completed. Goodbye");
|
|
||||||
});
|
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,16 +441,6 @@ export async function run(
|
|||||||
forcedArgs: Partial<RunArgs> = {},
|
forcedArgs: Partial<RunArgs> = {},
|
||||||
quite = false
|
quite = false
|
||||||
) {
|
) {
|
||||||
// Subscribe to unhandled Reactions.
|
|
||||||
process.on("unhandledRejection", (reason, p) => {
|
|
||||||
console.log("Unhandled Rejection at: Promise", p, "reason:", reason);
|
|
||||||
console.error(reason);
|
|
||||||
// application specific logging, throwing an error, or other logic here
|
|
||||||
|
|
||||||
// Forward the error
|
|
||||||
throw reason;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!quite) {
|
if (!quite) {
|
||||||
console.log(NOPELOGO);
|
console.log(NOPELOGO);
|
||||||
console.log("\n\n");
|
console.log("\n\n");
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { SPLITCHAR } from "./objectMethods";
|
import { SPLITCHAR } from "./objectMethods";
|
||||||
|
|
||||||
export const SEPARATOR = "/";
|
export const SEPARATOR = "/";
|
||||||
export const SINGLE_LEVEL_WILDCARD = "+";
|
export const SINGLE_LEVEL_WILDCARD = "+";
|
||||||
export const MULTI_LEVEL_WILDCARD = "#";
|
export const MULTI_LEVEL_WILDCARD = "#";
|
||||||
|
@ -10,6 +10,7 @@ import { writeFile } from "fs";
|
|||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { createFile } from "../helpers/fileMethods";
|
import { createFile } from "../helpers/fileMethods";
|
||||||
import { replaceAll } from "../helpers/stringMethods";
|
import { replaceAll } from "../helpers/stringMethods";
|
||||||
|
import { sleep } from "../index.browser";
|
||||||
import { getCentralNopeLogger, getNopeLogger } from "./getLogger";
|
import { getCentralNopeLogger, getNopeLogger } from "./getLogger";
|
||||||
|
|
||||||
export const CURRENT_DATE = _parsableISOString();
|
export const CURRENT_DATE = _parsableISOString();
|
||||||
@ -45,7 +46,10 @@ export function generateLogfilePath(name: string): string {
|
|||||||
* @param {number} [bufferSize=0] Default Buffer-Size. If > 0 we will write the log with buffering.
|
* @param {number} [bufferSize=0] Default Buffer-Size. If > 0 we will write the log with buffering.
|
||||||
* @backend **Only in Nodejs available**
|
* @backend **Only in Nodejs available**
|
||||||
*/
|
*/
|
||||||
export function useLogFile(pathToFile = DEFAULT_FILE, bufferSize = 0): void {
|
export function useLogFile(
|
||||||
|
pathToFile = DEFAULT_FILE,
|
||||||
|
bufferSize = 100
|
||||||
|
): () => Promise<void> {
|
||||||
const logger = getCentralNopeLogger();
|
const logger = getCentralNopeLogger();
|
||||||
|
|
||||||
// Define a function, that will write the content of the Buffer to our
|
// Define a function, that will write the content of the Buffer to our
|
||||||
@ -128,20 +132,19 @@ export function useLogFile(pathToFile = DEFAULT_FILE, bufferSize = 0): void {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (bufferSize > 0) {
|
const clearBufferAtEnd = async () => {
|
||||||
const clearBufferAtEnd = function () {
|
consoleLogger.info("Shutdown detected! Trying to Write the Buffer");
|
||||||
consoleLogger.info("Shutdown detected! Trying to Write the Buffer");
|
|
||||||
|
|
||||||
if (readyToWrite) {
|
while (!readyToWrite) {
|
||||||
// Now if the Data is ready, lets write the
|
await sleep(50);
|
||||||
// buffer to the File.
|
}
|
||||||
writeBufferToFile(() => process.exit(0));
|
|
||||||
} else {
|
|
||||||
setTimeout(clearBufferAtEnd, 50);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process.on("SIGINT", clearBufferAtEnd);
|
const promise = new Promise<void>((resolve, reject) => {
|
||||||
process.on("SIGTERM", clearBufferAtEnd);
|
writeBufferToFile(resolve);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
await promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
return clearBufferAtEnd;
|
||||||
}
|
}
|
||||||
|
93
lib/profiling/index.nodejs.ts
Normal file
93
lib/profiling/index.nodejs.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
"use strict";
|
||||||
|
const fs = require("fs");
|
||||||
|
const v8Profiler = require("v8-profiler-next");
|
||||||
|
|
||||||
|
import { join } from "path";
|
||||||
|
import { replaceAll } from "../helpers/stringMethods";
|
||||||
|
import { getNopeLogger } from "../index.browser";
|
||||||
|
import { createFile } from "../index.nodejs";
|
||||||
|
|
||||||
|
export const CURRENT_DATE = _parsableISOString();
|
||||||
|
export const DEFAULT_LOG_LOCATION = join(process.cwd(), "logs");
|
||||||
|
const DEFAULT_FILE = join(
|
||||||
|
DEFAULT_LOG_LOCATION,
|
||||||
|
"cpu_profile_" + CURRENT_DATE + ".cpuprofile"
|
||||||
|
);
|
||||||
|
const logger = getNopeLogger("CPU-Profiler");
|
||||||
|
|
||||||
|
function _parsableISOString(date = new Date()) {
|
||||||
|
let isoString = date.toISOString();
|
||||||
|
isoString = replaceAll(isoString, ":", "-");
|
||||||
|
isoString = replaceAll(isoString, ".", "-");
|
||||||
|
return isoString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a Log-File Path based on the given name with the following format:
|
||||||
|
* /logs/{name}_{date}.log
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {string} name Name of the File.
|
||||||
|
* @return {string}
|
||||||
|
* @backend **Only in Nodejs available**
|
||||||
|
*/
|
||||||
|
export function generateLogfilePath(name: string): string {
|
||||||
|
return join(
|
||||||
|
DEFAULT_LOG_LOCATION,
|
||||||
|
name + "_" + _parsableISOString() + ".cpuprofile"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function recordCPUProfile(pathToFile = DEFAULT_FILE) {
|
||||||
|
const title = "cpu-profile";
|
||||||
|
|
||||||
|
// set generateType 1 to generate new format for cpuprofile
|
||||||
|
// to be compatible with cpuprofile parsing in vscode.
|
||||||
|
v8Profiler.setGenerateType(1);
|
||||||
|
|
||||||
|
// ex. 5 mins cpu profile
|
||||||
|
v8Profiler.startProfiling(title, true);
|
||||||
|
|
||||||
|
let stopped = false;
|
||||||
|
|
||||||
|
const stopProfiling = async () => {
|
||||||
|
if (stopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopped = true;
|
||||||
|
|
||||||
|
const profile = v8Profiler.stopProfiling(title);
|
||||||
|
|
||||||
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
profile.export(function (error, result) {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const result: any = await promise;
|
||||||
|
|
||||||
|
// if it doesn't have the extension .cpuprofile then
|
||||||
|
// chrome's profiler tool won't like it.
|
||||||
|
|
||||||
|
// examine the profile:
|
||||||
|
// Navigate to chrome://inspect
|
||||||
|
// Click Open dedicated DevTools for Node
|
||||||
|
// Select the profiler tab
|
||||||
|
// Load your file
|
||||||
|
logger.info(
|
||||||
|
"Please open google chrome and open chrome://inspect and load the file",
|
||||||
|
pathToFile
|
||||||
|
);
|
||||||
|
|
||||||
|
await createFile(pathToFile, result);
|
||||||
|
|
||||||
|
// Clear the Profile.
|
||||||
|
profile.delete();
|
||||||
|
};
|
||||||
|
|
||||||
|
return stopProfiling;
|
||||||
|
}
|
@ -1,9 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @author Martin Karkowski
|
* @author Martin Karkowski
|
||||||
* @email m.karkowski@zema.de
|
* @email m.karkowski@zema.de
|
||||||
* @create date 2021-11-12 12:25:30
|
|
||||||
* @modify date 2022-01-06 09:54:44
|
|
||||||
* @desc [description]
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { memoize } from "lodash";
|
import { memoize } from "lodash";
|
||||||
@ -45,7 +42,9 @@ type TMatchting<O extends INopeTopic = INopeTopic> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class PubSubSystemBase<
|
export class PubSubSystemBase<
|
||||||
AD extends IEventAdditionalData = IEventAdditionalData,
|
AD extends IEventAdditionalData & {
|
||||||
|
pubSubUpdate?: boolean;
|
||||||
|
} = IEventAdditionalData,
|
||||||
I extends INopeEventEmitter<
|
I extends INopeEventEmitter<
|
||||||
unknown,
|
unknown,
|
||||||
unknown,
|
unknown,
|
||||||
@ -106,9 +105,12 @@ export class PubSubSystemBase<
|
|||||||
subTopic: string | false;
|
subTopic: string | false;
|
||||||
pubTopic: string | false;
|
pubTopic: string | false;
|
||||||
callback?: IEventCallback<unknown, AD>;
|
callback?: IEventCallback<unknown, AD>;
|
||||||
|
observer?: INopeObserver;
|
||||||
}
|
}
|
||||||
>();
|
>();
|
||||||
|
|
||||||
|
protected _emittersToObservers = new Map<O, INopeObserver>();
|
||||||
|
|
||||||
protected _matched = new Map<string, TMatchting>();
|
protected _matched = new Map<string, TMatchting>();
|
||||||
protected _generateEmitterType: () => I;
|
protected _generateEmitterType: () => I;
|
||||||
|
|
||||||
@ -183,11 +185,19 @@ export class PubSubSystemBase<
|
|||||||
|
|
||||||
// Define a callback, which will be used to forward
|
// Define a callback, which will be used to forward
|
||||||
// the data into the system:
|
// the data into the system:
|
||||||
|
let observer: INopeObserver = undefined;
|
||||||
let callback: IEventCallback<unknown, AD> = undefined;
|
let callback: IEventCallback<unknown, AD> = undefined;
|
||||||
|
|
||||||
if (pubTopic) {
|
if (pubTopic) {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
callback = (content, opts) => {
|
callback = (content, opts) => {
|
||||||
|
// Internal Data-Update of the pub-sub-system
|
||||||
|
// we wont push the data again. Otherwise, we
|
||||||
|
// risk an recursive endloop.
|
||||||
|
if (opts.pubSubUpdate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We use this callback to forward the data into the system:
|
// We use this callback to forward the data into the system:
|
||||||
_this._pushData(pubTopic as string, content, opts as AD);
|
_this._pushData(pubTopic as string, content, opts as AD);
|
||||||
};
|
};
|
||||||
@ -199,6 +209,7 @@ export class PubSubSystemBase<
|
|||||||
pubTopic,
|
pubTopic,
|
||||||
subTopic,
|
subTopic,
|
||||||
callback,
|
callback,
|
||||||
|
observer,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update the Matching Rules.
|
// Update the Matching Rules.
|
||||||
@ -206,9 +217,12 @@ export class PubSubSystemBase<
|
|||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
// If necessary. Add the Callback.
|
// If necessary. Add the Callback.
|
||||||
emitter.subscribe(callback, {
|
observer = emitter.subscribe(callback, {
|
||||||
skipCurrent: !this._sendCurrentDataOnSubscription,
|
skipCurrent: !this._sendCurrentDataOnSubscription,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Now lets store our binding.
|
||||||
|
this._emittersToObservers.set(emitter as unknown as O, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, if required, add the Data to the emitter.
|
// Now, if required, add the Data to the emitter.
|
||||||
@ -495,7 +509,7 @@ export class PubSubSystemBase<
|
|||||||
protected _notify(
|
protected _notify(
|
||||||
topic: string,
|
topic: string,
|
||||||
options: Partial<AD>,
|
options: Partial<AD>,
|
||||||
_exclusiveEmitter: O = null
|
_emitter: O = null
|
||||||
): void {
|
): void {
|
||||||
// Check whether a Matching exists for this
|
// Check whether a Matching exists for this
|
||||||
// Topic, if not add it.
|
// Topic, if not add it.
|
||||||
@ -511,10 +525,12 @@ export class PubSubSystemBase<
|
|||||||
_emitters,
|
_emitters,
|
||||||
] of referenceToMatch.dataPull.entries()) {
|
] of referenceToMatch.dataPull.entries()) {
|
||||||
for (const _emitter of _emitters) {
|
for (const _emitter of _emitters) {
|
||||||
// Get a new copy for every element.
|
// Get a new copy for every emitter.
|
||||||
const data = this._pullData(_pathToPull, null);
|
const data = this._pullData(_pathToPull, null);
|
||||||
|
|
||||||
if (_exclusiveEmitter !== null && _emitter !== _exclusiveEmitter) {
|
// Only if we want to notify an exclusive emitter we
|
||||||
|
// have to continue, if our emitter isnt matched.
|
||||||
|
if (_emitter !== null && _emitter === _emitter) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Iterate through all Subscribers
|
// Iterate through all Subscribers
|
||||||
@ -532,7 +548,7 @@ export class PubSubSystemBase<
|
|||||||
// Get a new copy for every element.
|
// Get a new copy for every element.
|
||||||
const data = this._pullData(_pattern, null);
|
const data = this._pullData(_pattern, null);
|
||||||
|
|
||||||
if (_exclusiveEmitter !== null && _emitter !== _exclusiveEmitter) {
|
if (_emitter !== null && _emitter !== _emitter) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Iterate through all Subscribers
|
// Iterate through all Subscribers
|
||||||
@ -578,6 +594,9 @@ export class PubSubSystemBase<
|
|||||||
): void {
|
): void {
|
||||||
const _options = this._updateOptions(options);
|
const _options = this._updateOptions(options);
|
||||||
|
|
||||||
|
// Force the Update to be true.
|
||||||
|
_options.pubSubUpdate = true;
|
||||||
|
|
||||||
if (containsWildcards(path)) {
|
if (containsWildcards(path)) {
|
||||||
throw 'The Path contains wildcards. Please use the method "patternbasedPullData" instead';
|
throw 'The Path contains wildcards. Please use the method "patternbasedPullData" instead';
|
||||||
} else if (path === "") {
|
} else if (path === "") {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @author Martin Karkowski
|
* @author Martin Karkowski
|
||||||
* @email m.karkowski@zema.de
|
* @email m.karkowski@zema.de
|
||||||
* @create date 2021-11-12 17:33:12
|
|
||||||
* @modify date 2022-01-06 08:32:34
|
|
||||||
* @desc [description]
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { INopeDescriptor } from "./nopeDescriptor.interface";
|
import { INopeDescriptor } from "./nopeDescriptor.interface";
|
||||||
@ -22,6 +19,9 @@ export interface ITopicSetContentOptions extends IEventAdditionalData {
|
|||||||
topic: string;
|
topic: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Topic Type.
|
||||||
|
*/
|
||||||
export type INopeTopic<T = any, S = T, G = T> = INopeEventEmitter<
|
export type INopeTopic<T = any, S = T, G = T> = INopeEventEmitter<
|
||||||
T,
|
T,
|
||||||
S,
|
S,
|
||||||
|
30
package-lock.json
generated
30
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "nope",
|
"name": "nope",
|
||||||
"version": "1.0.17",
|
"version": "1.0.24",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "nope",
|
"name": "nope",
|
||||||
"version": "1.0.17",
|
"version": "1.0.24",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1",
|
"argparse": "^2.0.1",
|
||||||
@ -33,6 +33,7 @@
|
|||||||
"ts-morph": "^13.0.2",
|
"ts-morph": "^13.0.2",
|
||||||
"typescript-json-schema": "^0.52.0",
|
"typescript-json-schema": "^0.52.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
|
"v8-profiler-next": "^1.5.1",
|
||||||
"websocket-stream": "^5.5.2"
|
"websocket-stream": "^5.5.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -6620,9 +6621,7 @@
|
|||||||
"node_modules/nan": {
|
"node_modules/nan": {
|
||||||
"version": "2.15.0",
|
"version": "2.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
|
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"node_modules/nanomatch": {
|
"node_modules/nanomatch": {
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
@ -17240,6 +17239,15 @@
|
|||||||
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
|
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/v8-profiler-next": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/v8-profiler-next/-/v8-profiler-next-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-7gnfJ3x7zN3gzmVs69OvJBNze5dLCIeY2Necy+IzomWmprSCRsBbCn5GfwAJHkWJxzoex3gyRexxvYGlgR93yg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"nan": "^2.14.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/validate-npm-package-name": {
|
"node_modules/validate-npm-package-name": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
|
||||||
@ -23506,9 +23514,7 @@
|
|||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.15.0",
|
"version": "2.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
|
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"nanomatch": {
|
"nanomatch": {
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
@ -31533,6 +31539,14 @@
|
|||||||
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
|
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"v8-profiler-next": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/v8-profiler-next/-/v8-profiler-next-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-7gnfJ3x7zN3gzmVs69OvJBNze5dLCIeY2Necy+IzomWmprSCRsBbCn5GfwAJHkWJxzoex3gyRexxvYGlgR93yg==",
|
||||||
|
"requires": {
|
||||||
|
"nan": "^2.14.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"validate-npm-package-name": {
|
"validate-npm-package-name": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nope",
|
"name": "nope",
|
||||||
"version": "1.0.21",
|
"version": "1.0.24",
|
||||||
"description": "NoPE Runtime for Nodejs. For Browser-Support please use nope-browser",
|
"description": "NoPE Runtime for Nodejs. For Browser-Support please use nope-browser",
|
||||||
"files": [
|
"files": [
|
||||||
"dist-nodejs/**/*",
|
"dist-nodejs/**/*",
|
||||||
@ -63,6 +63,7 @@
|
|||||||
"ts-morph": "^13.0.2",
|
"ts-morph": "^13.0.2",
|
||||||
"typescript-json-schema": "^0.52.0",
|
"typescript-json-schema": "^0.52.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
|
"v8-profiler-next": "^1.5.1",
|
||||||
"websocket-stream": "^5.5.2"
|
"websocket-stream": "^5.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "nope",
|
|
||||||
"version": "1.0.3",
|
|
||||||
"description": "NoPE Runtime for Nodejs. For Browser-Support please use nope-browser",
|
|
||||||
"browser": "build/nope.js",
|
|
||||||
"main": "dist-nodejs/index.nodejs.js",
|
|
||||||
"files": [
|
|
||||||
"build/**/*",
|
|
||||||
"dist-nodejs/**/*",
|
|
||||||
"lib/**/*",
|
|
||||||
"bin/*"
|
|
||||||
],
|
|
||||||
"bin": {
|
|
||||||
"nope-js": "./bin/nope"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "mocha",
|
|
||||||
"compile-nodejs": "tsc -p ./tsconfig.json",
|
|
||||||
"compile": "tsc -p ./tsconfig.browser.json",
|
|
||||||
"build": "npx webpack -c webpack-typescript.config.js",
|
|
||||||
"doc": "npx jsdoc ./dist/**/* -d docs",
|
|
||||||
"dev": "NODE_OPTIONS='--inspect' next dev",
|
|
||||||
"start": "node ./dist/lib/cli/nope.js",
|
|
||||||
"prettier-format": "run-script-os",
|
|
||||||
"prettier-format:win32": "prettier \"./lib/**/*.ts\" --write",
|
|
||||||
"prettier-format:darwin:linux": "prettier 'lib/**/*.ts' --write",
|
|
||||||
"prettier-format:default": "prettier 'lib/**/*.ts' --write",
|
|
||||||
"prettier-watch": "run-script-os",
|
|
||||||
"prettier-watch:win32": "onchange \"lib/**/*.ts\" -- prettier --write {{changed}}",
|
|
||||||
"prettier-watch:darwin:linux": "onchange 'lib/**/*.ts' -- prettier --write {{changed}}",
|
|
||||||
"prettier-watch:default": "onchange 'lib/**/*.ts' -- prettier --write {{changed}}"
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"reporter": "spec",
|
|
||||||
"spec": "dist/**/*.spec.js"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://git.zema.de/tfs/ZISS/_git/nope-js"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Martin Karkowski",
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://git.zema.de/tfs/ZISS/_git/nope-js/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://git.zema.de/tfs/ZISS/_git/nope-js#readme",
|
|
||||||
"dependencies": {
|
|
||||||
"async": "^3.2.2",
|
|
||||||
"comment-parser": "^1.3.0",
|
|
||||||
"cors": "^2.8.5",
|
|
||||||
"handlebars": "^4.7.7",
|
|
||||||
"inquirer": "^8.2.0",
|
|
||||||
"inquirer-fuzzy-path": "^2.3.0",
|
|
||||||
"inquirer-search-list": "^1.2.6",
|
|
||||||
"inversify": "^6.0.1",
|
|
||||||
"js-logger": "^1.6.1",
|
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"mathjs": "^10.0.2",
|
|
||||||
"mqtt": "^4.3.4",
|
|
||||||
"mqtt-pattern": "^1.2.0",
|
|
||||||
"next": "^12.0.7",
|
|
||||||
"npm": "^8.3.0",
|
|
||||||
"npx": "^10.2.2",
|
|
||||||
"reflect-metadata": "^0.1.13",
|
|
||||||
"run-script-os": "^1.1.6",
|
|
||||||
"rxjs": "^7.5.1",
|
|
||||||
"socket.io": "^4.4.1",
|
|
||||||
"socket.io-client": "^4.4.1",
|
|
||||||
"ts-morph": "^13.0.2",
|
|
||||||
"typescript-json-schema": "^0.52.0",
|
|
||||||
"uuid": "^8.3.2",
|
|
||||||
"websocket-stream": "^5.5.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/preset-typescript": "^7.16.7",
|
|
||||||
"@types/async": "^3.2.12",
|
|
||||||
"@types/chai": "^4.3.0",
|
|
||||||
"@types/lodash": "^4.14.178",
|
|
||||||
"@types/node": "^17.0.8",
|
|
||||||
"@types/socket.io": "^3.0.1",
|
|
||||||
"@types/socket.io-client": "^1.4.36",
|
|
||||||
"chai": "^4.3.4",
|
|
||||||
"dts-bundle": "^0.7.3",
|
|
||||||
"dts-bundle-webpack": "^1.0.2",
|
|
||||||
"eslint": "^8.6.0",
|
|
||||||
"eslint-config-prettier": "^8.3.0",
|
|
||||||
"eslint-plugin-import": "^2.25.4",
|
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
|
||||||
"mocha": "^9.1.3",
|
|
||||||
"npm-check-updates": "^12.1.0",
|
|
||||||
"onchange": "^7.1.0",
|
|
||||||
"prettier": "2.5.1",
|
|
||||||
"typedoc": "^0.22.10",
|
|
||||||
"typescript": "^4.5.4",
|
|
||||||
"webpack": "^4.46.0",
|
|
||||||
"webpack-cli": "^4.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user