socket-function 0.8.39 → 0.8.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SocketFunction.ts CHANGED
@@ -201,6 +201,8 @@ export class SocketFunction {
201
201
  public static mountedNodeId: string = "";
202
202
  public static mountedIP: string = "";
203
203
  private static hasMounted = false;
204
+ private static onMountCallback: () => void = () => { };
205
+ public static mountPromise: Promise<void> = new Promise(r => this.onMountCallback = r);
204
206
  public static async mount(config: SocketServerConfig) {
205
207
  if (this.mountedNodeId) {
206
208
  throw new Error("SocketFunction already mounted, mounting twice in one thread is not allowed.");
@@ -223,6 +225,7 @@ export class SocketFunction {
223
225
  await callback();
224
226
  }
225
227
  }
228
+ this.onMountCallback();
226
229
  return this.mountedNodeId;
227
230
  }
228
231
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "socket-function",
3
- "version": "0.8.39",
3
+ "version": "0.8.40",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -10,7 +10,7 @@
10
10
  "node-forge": "https://github.com/sliftist/forge#name",
11
11
  "preact": "^10.10.6",
12
12
  "rdtsc-now": "^0.3.0",
13
- "typenode": "^4.9.4-c",
13
+ "typenode": "^4.9.4-f",
14
14
  "ws": "^8.8.0"
15
15
  },
16
16
  "scripts": {
@@ -10,8 +10,9 @@ import { getClientNodeId, getNodeIdLocation, registerNodeClient } from "./nodeCa
10
10
  import debugbreak from "debugbreak";
11
11
  import { lazy } from "./caching";
12
12
  import { JSONLACKS } from "./JSONLACKS/JSONLACKS";
13
- import { red } from "./formatting/logColors";
14
- import { isSplitableArray } from "./fixLargeNetworkCalls";
13
+ import { red, yellow } from "./formatting/logColors";
14
+ import { isSplitableArray, markArrayAsSplitable } from "./fixLargeNetworkCalls";
15
+ import { delay } from "./batching";
15
16
 
16
17
  const MIN_RETRY_DELAY = 1000;
17
18
 
@@ -56,6 +57,8 @@ export interface SenderInterface {
56
57
  addEventListener(event: "message", listener: (data: ws.RawData | ws.MessageEvent | string) => void): void;
57
58
 
58
59
  readyState: number;
60
+
61
+ ping?(): void;
59
62
  }
60
63
 
61
64
  export async function createCallFactory(
@@ -82,6 +85,18 @@ export async function createCallFactory(
82
85
  // in return calls.
83
86
  let nextSeqNum = Date.now() + Math.random();
84
87
 
88
+ // NOTE: I'm not sure if this is needed, I thought it was, but... now I think
89
+ // it probably isn't...
90
+ // if (webSocketBase?.readyState === 1 /* OPEN */ && webSocketBase.ping) {
91
+ // // Heartbeat loop, otherwise onDisconnect is never called.
92
+ // ((async () => {
93
+ // while (webSocketBase?.readyState === 1 /* OPEN */ && webSocketBase.ping) {
94
+ // await delay(1000 * 60);
95
+ // webSocketBase.ping?.();
96
+ // }
97
+ // }))().catch(() => { });
98
+ // }
99
+
85
100
  let lastConnectionAttempt = 0;
86
101
 
87
102
  let callerContext: CallerContextBase = {
@@ -120,6 +135,7 @@ export async function createCallFactory(
120
135
  if (data.byteLength > SocketFunction.MAX_MESSAGE_SIZE * 1.5) {
121
136
  let splitArgIndex = call.args.findIndex(isSplitableArray);
122
137
  if (splitArgIndex >= 0) {
138
+ console.log(yellow(`Splitting large call due to large args: ${call.classGuid}.${call.functionName}`));
123
139
  let SPLIT_GROUPS = 10;
124
140
  let splitArg = call.args[splitArgIndex] as unknown[];
125
141
  let subCalls = list(SPLIT_GROUPS).map(index => {
@@ -127,12 +143,15 @@ export async function createCallFactory(
127
143
  let end = Math.floor((index + 1) / SPLIT_GROUPS * splitArg.length);
128
144
  return splitArg.slice(start, end);
129
145
  }).filter(x => x.length > 0);
130
- for (let splitList of subCalls) {
146
+
147
+ let calls = subCalls.map(async splitList => {
131
148
  let subCall = { ...call };
132
149
  subCall.args = subCall.args.slice();
133
- subCall.args[splitArgIndex] = splitList;
150
+ subCall.args[splitArgIndex] = markArrayAsSplitable(splitList);
134
151
  await callFactory.performCall(subCall);
135
- }
152
+ });
153
+ await Promise.allSettled(calls);
154
+ await Promise.all(calls);
136
155
  // Eh... we COULD return the array of results, but... then the result would sometimes be an array,
137
156
  // some times not, so, it is better to return a string which will make it more clear why it sometimes varies.
138
157
  return "CALLS_SPLIT_DUE_TO_LARGE_ARGS";
@@ -355,7 +374,7 @@ export async function createCallFactory(
355
374
  }
356
375
  throw new Error(`Unhandled data type ${typeof message}`);
357
376
  } catch (e: any) {
358
- debugbreak(1);
377
+ debugbreak(2);
359
378
  debugger;
360
379
  console.error(e.stack);
361
380
  }
package/src/caching.ts CHANGED
@@ -3,7 +3,6 @@ import { AnyFunction, Args, canHaveChildren } from "./types";
3
3
 
4
4
  export function lazy<T>(factory: () => T): () => T {
5
5
  let value: { value: T } | undefined = undefined;
6
-
7
6
  return () => {
8
7
  if (!value) {
9
8
  value = { value: factory() };
@@ -33,8 +32,10 @@ export function cacheEmptyArray<T>(array: T[]): T[] {
33
32
 
34
33
  export function cache<Output, Key>(getValue: (key: Key) => Output): {
35
34
  (key: Key): Output;
35
+ // NOTE: If you want to clear all, just make a new cache!
36
36
  clear(key: Key): void;
37
37
  forceSet(key: Key, value: Output): void;
38
+ getAllKeys(): Key[];
38
39
  } {
39
40
  let startingCalculating = new Set<Key>();
40
41
  let values = new Map<Key, Output>();
@@ -61,6 +62,9 @@ export function cache<Output, Key>(getValue: (key: Key) => Output): {
61
62
  values.set(key, value);
62
63
  startingCalculating.add(key);
63
64
  };
65
+ cache.getAllKeys = () => {
66
+ return [...values.keys()];
67
+ };
64
68
  return cache;
65
69
  }
66
70
 
@@ -5,5 +5,5 @@ export function markArrayAsSplitable<T>(data: T[]): T[] {
5
5
  }
6
6
  export function isSplitableArray<T>(data: T): data is T & (unknown[]) {
7
7
  if (!Array.isArray(data)) return false;
8
- return (data as any)[arrayIsSplitable] === true;
8
+ return !!(data as any)[arrayIsSplitable];
9
9
  }
package/src/misc.ts CHANGED
@@ -139,6 +139,9 @@ export function getKeys(obj: unknown) {
139
139
  }
140
140
  return keyArray;
141
141
  }
142
+ export function getStringKeys<T extends {}>(obj: T): ((keyof T) & string)[] {
143
+ return Object.keys(obj) as any;
144
+ }
142
145
 
143
146
  if (isNode()) {
144
147
  // TODO: Find a better place for this...
@@ -1,6 +1,6 @@
1
1
  import debugbreak from "debugbreak";
2
2
  import { formatTime, formatNumber } from "../formatting/format";
3
- import { red, yellow, blue } from "../formatting/logColors";
3
+ import { red, yellow, blue, magenta } from "../formatting/logColors";
4
4
 
5
5
  import { getOwnTime, getPendingOwnTimeInstances, getPendingOwnTimeObjs, OwnTimeObj } from "./getOwnTime";
6
6
  import { addToStats, addToStatsValue, createStatsValue, getStatsTop, StatsValue } from "./stats";
@@ -108,9 +108,9 @@ export function logMeasureTable(
108
108
  let totalTime = entries.map(x => getTime(x).sum).reduce((a, b) => a + b, 0);
109
109
 
110
110
  console.log();
111
- let title = yellow(`Profiled ${formatTime(totalTime)}`);
111
+ let title = yellow(`Profiled ${formatTime(totalTime)} (logged at ${new Date().toISOString()})`);
112
112
  if (name) {
113
- title += ` ${blue(name)}`;
113
+ title = `(${blue(name)}) ${title}`;
114
114
  }
115
115
  console.log(title);
116
116
  function percent(value: number) {
@@ -142,7 +142,7 @@ export function logMeasureTable(
142
142
 
143
143
  let ownTimeTop = getStatsTop(getTime(entry));
144
144
  if (ownTimeTop.topHeavy) {
145
- output += red(` TOP ${percent(ownTimeTop.valueFraction)} of the time is owned by ${percent(ownTimeTop.countFraction)} of the calls`);
145
+ output += red(` TOP ${percent(ownTimeTop.valueFraction)} of the time is owned by ${percent(ownTimeTop.countFraction)} of the calls (${formatTime(ownTimeTop.value / ownTimeTop.count)} per * ${formatNumber(ownTimeTop.count)} = ${formatTime(ownTimeTop.value)})`);
146
146
  }
147
147
 
148
148
  if (entry.stillOpenCount > 0) {
@@ -12,6 +12,7 @@ import debugbreak from "debugbreak";
12
12
  import { getNodeId } from "./nodeCache";
13
13
  import crypto from "crypto";
14
14
  import { Watchable } from "./misc";
15
+ import { delay, runInfinitePoll } from "./batching";
15
16
 
16
17
  export type SocketServerConfig = (
17
18
  https.ServerOptions & {
@@ -38,7 +38,7 @@ export function createWebsocketFactory(): (nodeId: string) => SenderInterface {
38
38
  console.log(`Connecting to ${address}:${port}`);
39
39
  }
40
40
  let webSocket = new ws.WebSocket(`wss://${address}:${port}`, {
41
- ca: tls.rootCertificates.concat(getTrustedCertificates()),
41
+ ca: getTrustedCertificates()
42
42
  });
43
43
  let result = Object.assign(webSocket, { socket: undefined as tls.TLSSocket | undefined });
44
44
  webSocket.once("upgrade", e => {