@camstack/system 1.1.20 → 1.1.21
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/dist/addon-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/index.js +4 -1
- package/dist/index.mjs +2 -2
- package/dist/kernel/index.d.ts +2 -1
- package/dist/kernel/moleculer/addon-context-factory.d.ts +3 -3
- package/dist/kernel/moleculer/event-bus-core.d.ts +54 -0
- package/dist/kernel/moleculer/event-bus.d.ts +34 -1
- package/dist/kernel/transport/local-child-registry.d.ts +23 -0
- package/dist/kernel/transport/uds-event-bridge.d.ts +12 -0
- package/dist/{manifest-python-deps-X00KVYHa.mjs → manifest-python-deps-Bp7nvTNF.mjs} +220 -5
- package/dist/{manifest-python-deps-PbdHKDpj.js → manifest-python-deps-Di_9ayDE.js} +237 -4
- package/package.json +1 -1
package/dist/addon-runner.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
2
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
2
|
+
const require_manifest_python_deps = require("./manifest-python-deps-Di_9ayDE.js");
|
|
3
3
|
const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
|
|
4
4
|
let node_fs = require("node:fs");
|
|
5
5
|
node_fs = require_chunk.__toESM(node_fs);
|
package/dist/addon-runner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I as createUdsLoggerWithControl, L as LocalChildClient, at as setWorkerNativeCapsChangeListener, bt as resolveAddonClass, i as createUdsAddonContext, nt as getWorkerNativeCapProvider, rt as getWorkerNativeCapSnapshot, st as validateProviderRegistrations, t as installManifestPythonDeps, yt as installManifestNativeDeps } from "./manifest-python-deps-Bp7nvTNF.mjs";
|
|
2
2
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
3
3
|
import { register } from "node:module";
|
|
4
4
|
import * as fs from "node:fs";
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ const require_builtins_local_auth_local_auth_addon = require("./builtins/local-a
|
|
|
20
20
|
require("./builtins/local-auth/index.js");
|
|
21
21
|
const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
|
|
22
22
|
require("./builtins/device-manager/index.js");
|
|
23
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
23
|
+
const require_manifest_python_deps = require("./manifest-python-deps-Di_9ayDE.js");
|
|
24
24
|
const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
|
|
25
25
|
let _camstack_types_node = require("@camstack/types/node");
|
|
26
26
|
let node_http = require("node:http");
|
|
@@ -93487,6 +93487,7 @@ Object.defineProperty(exports, "getFfmpegDownloadUrl", {
|
|
|
93487
93487
|
}
|
|
93488
93488
|
});
|
|
93489
93489
|
exports.getModelFilePath = require_model_download_service.getModelFilePath;
|
|
93490
|
+
exports.getMoleculerEventStats = require_manifest_python_deps.getMoleculerEventStats;
|
|
93490
93491
|
exports.getOrInitReadinessRegistry = require_manifest_python_deps.getOrInitReadinessRegistry;
|
|
93491
93492
|
exports.getOrInitReadinessRegistryForClient = require_manifest_python_deps.getOrInitReadinessRegistryForClient;
|
|
93492
93493
|
exports.getPidStats = require_resource_monitor.getPidStats;
|
|
@@ -93556,8 +93557,10 @@ Object.defineProperty(exports, "scopeKey", {
|
|
|
93556
93557
|
exports.scopesAllowDeviceCap = scopesAllowDeviceCap;
|
|
93557
93558
|
exports.serializeTypedArrays = require_manifest_python_deps.serializeTypedArrays;
|
|
93558
93559
|
exports.setHubConnected = require_manifest_python_deps.setHubConnected;
|
|
93560
|
+
exports.setNodeEventInterest = require_manifest_python_deps.setNodeEventInterest;
|
|
93559
93561
|
exports.stageFrameworkLockstep = stageFrameworkLockstep;
|
|
93560
93562
|
exports.stripCamstackDeps = stripCamstackDeps;
|
|
93563
|
+
exports.subscribePassthrough = require_manifest_python_deps.subscribePassthrough;
|
|
93561
93564
|
exports.udsChildLogToWorkerEntry = require_manifest_python_deps.udsChildLogToWorkerEntry;
|
|
93562
93565
|
exports.validateProviderRegistrations = require_manifest_python_deps.validateProviderRegistrations;
|
|
93563
93566
|
exports.writePendingRestart = writePendingRestart;
|
package/dist/index.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import { LocalAuthAddon, a as require_ms, c as __esmMin, d as __toCommonJS, f as
|
|
|
18
18
|
import "./builtins/local-auth/index.mjs";
|
|
19
19
|
import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
20
20
|
import "./builtins/device-manager/index.mjs";
|
|
21
|
-
import { A as
|
|
21
|
+
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as resolveHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as resolveAddonClass, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getMoleculerEventStats, dt as capBareAction, et as buildUdsNativeCapProxy, f as registerEventBusService, ft as capServiceName, g as createKernelHwAccel, gt as DeviceRegistry, h as AddonDepsManager, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as subscribePassthrough, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as setNodeEventInterest, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as getBrokerEventBus, ut as capActionSuffix, v as createHwAccelService, vt as CapabilityUnavailableError, w as buildLinkChain, x as getCapUsageRegistry, y as CapUsageRegistry, yt as installManifestNativeDeps, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-Bp7nvTNF.mjs";
|
|
22
22
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
23
23
|
import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
|
|
24
24
|
import { request } from "node:http";
|
|
@@ -93252,4 +93252,4 @@ async function stageFrameworkLockstep(input) {
|
|
|
93252
93252
|
return results;
|
|
93253
93253
|
}
|
|
93254
93254
|
//#endregion
|
|
93255
|
-
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FRAMEWORK_LOCKSTEP, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createHwAccelService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isClusterSecretMismatchError, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, stageFrameworkLockstep, stripCamstackDeps, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
|
|
93255
|
+
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FRAMEWORK_LOCKSTEP, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createHwAccelService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isClusterSecretMismatchError, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stageFrameworkLockstep, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -33,7 +33,8 @@ export { type AddonDeploySource, isAddonDeploySource } from './moleculer/addon-d
|
|
|
33
33
|
export { createAddonService, validateProviderRegistrations, } from './moleculer/addon-service-factory.js';
|
|
34
34
|
export { createCoreCapService, CORE_CAP_SERVICE_NAME } from './moleculer/core-cap-service.js';
|
|
35
35
|
export type { CoreCapAction, CoreCapServiceOptions } from './moleculer/core-cap-service.js';
|
|
36
|
-
export { createAddonContext, createUdsAddonContext, setHubConnected, adaptBrokerToCluster, registerEventBusService, getBrokerEventBus, EVENT_TOPIC_PREFIX, } from './moleculer/addon-context-factory.js';
|
|
36
|
+
export { createAddonContext, createUdsAddonContext, setHubConnected, adaptBrokerToCluster, registerEventBusService, setNodeEventInterest, getMoleculerEventStats, subscribePassthrough, getBrokerEventBus, EVENT_TOPIC_PREFIX, } from './moleculer/addon-context-factory.js';
|
|
37
|
+
export type { MoleculerEventStats } from './moleculer/addon-context-factory.js';
|
|
37
38
|
export { HubLogForwarder } from './moleculer/hub-log-forwarder.js';
|
|
38
39
|
export type { AddonContextOptions } from './moleculer/addon-context-factory.js';
|
|
39
40
|
export { createHubService } from './moleculer/hub-service.js';
|
|
@@ -5,7 +5,7 @@ import { CapabilityRegistry } from '../capability-registry.js';
|
|
|
5
5
|
import { CapCallInput } from '../transport/index.js';
|
|
6
6
|
import { LocalChildClient } from '../transport/local-child-client.js';
|
|
7
7
|
import { DataPlaneSink } from './addon-data-plane-facility.js';
|
|
8
|
-
import { getBrokerEventBus, registerEventBusService, clusterEventTopic, EVENT_TOPIC_PREFIX } from './event-bus.js';
|
|
8
|
+
import { getBrokerEventBus, registerEventBusService, setNodeEventInterest, getMoleculerEventStats, subscribePassthrough, clusterEventTopic, EVENT_TOPIC_PREFIX, MoleculerEventStats } from './event-bus.js';
|
|
9
9
|
import { createRunnerLogger, setHubConnected, ___resetHubConnectedForTests, ___createRemoteLoggerForTests } from './remote-logger.js';
|
|
10
10
|
import { withAddonScope, setPreferredProvider, ___resetBindingSubscriptionForTests } from './provider-registry.js';
|
|
11
11
|
/**
|
|
@@ -99,5 +99,5 @@ declare function createUdsAddonContext(client: LocalChildClient, nodeId: string,
|
|
|
99
99
|
* next addon instance loads.
|
|
100
100
|
*/
|
|
101
101
|
declare function drainWorkerDisposerChain(nodeId: string, addonId: string): Promise<void>;
|
|
102
|
-
export { createAddonContext, createUdsAddonContext, setHubConnected, adaptBrokerToCluster, drainWorkerDisposerChain, registerEventBusService, clusterEventTopic, EVENT_TOPIC_PREFIX, getBrokerEventBus, withAddonScope, setPreferredProvider, createRunnerLogger, __resetHubConnectedForTests, __resetBindingSubscriptionForTests, __createRemoteLoggerForTests, };
|
|
103
|
-
export type { AddonContextOptions };
|
|
102
|
+
export { createAddonContext, createUdsAddonContext, setHubConnected, adaptBrokerToCluster, drainWorkerDisposerChain, registerEventBusService, setNodeEventInterest, getMoleculerEventStats, subscribePassthrough, clusterEventTopic, EVENT_TOPIC_PREFIX, getBrokerEventBus, withAddonScope, setPreferredProvider, createRunnerLogger, __resetHubConnectedForTests, __resetBindingSubscriptionForTests, __createRemoteLoggerForTests, };
|
|
103
|
+
export type { AddonContextOptions, MoleculerEventStats };
|
|
@@ -77,6 +77,60 @@ export declare const RING_BUFFER_DENY_PATTERNS: readonly string[];
|
|
|
77
77
|
*/
|
|
78
78
|
export declare const MAX_RECENT_EVENTS = 1000;
|
|
79
79
|
export declare function isHighFrequencyCategory(category: string): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Fan-out mode for cross-node (Moleculer) event delivery, read from the
|
|
82
|
+
* `CAMSTACK_MOLECULER_EVENT_FANOUT` env. The inter-node analogue of the
|
|
83
|
+
* intra-host `CAMSTACK_UDS_EVENT_FANOUT` gate (`local-child-registry.ts`):
|
|
84
|
+
* - `filter` (default) — drop an inbound cross-node event whose category
|
|
85
|
+
* no local subscriber on THIS node wants (the union of its children's
|
|
86
|
+
* declared patterns).
|
|
87
|
+
* - `shadow` — compute the drop decision + count would-suppresses, but
|
|
88
|
+
* STILL deliver every event (burn-in: prove zero would-be-starved deliveries
|
|
89
|
+
* before flipping to `filter`).
|
|
90
|
+
* - `broadcast` — ignore the gate entirely (pre-D2 behaviour).
|
|
91
|
+
*
|
|
92
|
+
* ROLLBACK CONTRACT (operators, read this): this env governs ONLY the inter-node
|
|
93
|
+
* (Moleculer) gate. The intra-host UDS fan-out has a SEPARATE, independent
|
|
94
|
+
* kill-switch, `CAMSTACK_UDS_EVENT_FANOUT` (see `local-child-registry.ts`). A
|
|
95
|
+
* FULL rollback to pre-D2 / pre-#44 delivery therefore requires BOTH env vars
|
|
96
|
+
* set to `broadcast` AND a process restart on EVERY node (hub + all agents) —
|
|
97
|
+
* each is read ONCE at registration/construction, so a running process will not
|
|
98
|
+
* pick up a change. Flipping only one leg leaves the other filtering and yields
|
|
99
|
+
* inconsistent behaviour. Recommended first fleet-wide enable: `shadow` on both,
|
|
100
|
+
* watch the suppressed counters (`getMoleculerEventStats` /
|
|
101
|
+
* `getChildEventStats`), then flip to `filter` once burn-in shows zero
|
|
102
|
+
* would-be-starved deliveries.
|
|
103
|
+
*/
|
|
104
|
+
export type MoleculerEventFanoutMode = 'filter' | 'shadow' | 'broadcast';
|
|
105
|
+
export declare function readMoleculerFanoutMode(): MoleculerEventFanoutMode;
|
|
106
|
+
/**
|
|
107
|
+
* A node's inbound-interest snapshot used by {@link crossNodeAcceptsCategory}.
|
|
108
|
+
* - `retainRecent` — the receiving bus retains events for `getRecent`/audit
|
|
109
|
+
* (the hub main process). Such a bus genuinely wants EVERY category (its
|
|
110
|
+
* interest set is the admin-ui live stream + recent[] ring), so it always
|
|
111
|
+
* fails OPEN — it never filters inbound cross-node events.
|
|
112
|
+
* - `interest` — the union of this node's local subscribers' declared category
|
|
113
|
+
* patterns (aggregated from its UDS children). `null` = undeclared / unknown
|
|
114
|
+
* (a legacy child, or no oracle installed) → fail OPEN (accept everything).
|
|
115
|
+
* An EMPTY array is a *declared* "wants nothing" and drops every category.
|
|
116
|
+
*/
|
|
117
|
+
export interface CrossNodeInterestSnapshot {
|
|
118
|
+
readonly retainRecent: boolean;
|
|
119
|
+
readonly interest: readonly string[] | null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Does this node want to accept an inbound cross-node event in `category`?
|
|
123
|
+
* The receiving-side mirror of `LocalChildRegistry.childWantsEvent`:
|
|
124
|
+
* - `broadcast` mode → always (gate disabled).
|
|
125
|
+
* - a retaining bus (hub main) → always (it serves `getRecent` + admin-ui;
|
|
126
|
+
* its interest is genuinely everything).
|
|
127
|
+
* - undeclared interest (`null`) → always (fail-open).
|
|
128
|
+
* - else the declared union must match via `matchesPattern` — the SAME
|
|
129
|
+
* function the local subscriber map-key gate uses, giving delivery parity.
|
|
130
|
+
* `shadow` is handled by the caller (it counts the would-suppress but still
|
|
131
|
+
* delivers), exactly like the UDS fan-out.
|
|
132
|
+
*/
|
|
133
|
+
export declare function crossNodeAcceptsCategory(mode: MoleculerEventFanoutMode, snapshot: CrossNodeInterestSnapshot, category: string): boolean;
|
|
80
134
|
/**
|
|
81
135
|
* Deliver `event` to all matching local subscribers and — ONLY on a bus that
|
|
82
136
|
* opted into retention (`state.retainRecent`, i.e. the hub main process) and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IEventBus } from '@camstack/types';
|
|
1
|
+
import { IEventBus, SystemEvent } from '@camstack/types';
|
|
2
2
|
import { ServiceBroker } from 'moleculer';
|
|
3
3
|
/**
|
|
4
4
|
* Narrow interface for the Moleculer ServiceBroker surface used in this file.
|
|
@@ -28,6 +28,39 @@ export interface BrokerLike {
|
|
|
28
28
|
export declare const EVENT_TOPIC_PREFIX = "camstack.evt.";
|
|
29
29
|
/** Build the Moleculer broadcast topic for an event category. */
|
|
30
30
|
export declare function clusterEventTopic(category: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Subscribe a PASS-THROUGH relay handler to the broker's shared bus WITHOUT
|
|
33
|
+
* registering it in the local-interest surface. Used exclusively by the UDS
|
|
34
|
+
* event bridge for its cluster/parent-local → children fan-out subscription:
|
|
35
|
+
* the bridge must receive every event the gate lets through so it can relay to
|
|
36
|
+
* forked children, but it is not itself a terminal consumer, so it must not
|
|
37
|
+
* count toward this node's interest (a counted `*` would defeat the filter).
|
|
38
|
+
* Returns an unsubscribe function.
|
|
39
|
+
*/
|
|
40
|
+
export declare function subscribePassthrough(broker: ServiceBroker, handler: (event: SystemEvent) => void): () => void;
|
|
41
|
+
/** Cross-node inbound fan-out counters for a broker, `{ delivered, suppressed }`. */
|
|
42
|
+
export interface MoleculerEventStats {
|
|
43
|
+
readonly delivered: number;
|
|
44
|
+
readonly suppressed: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Install (or clear, with `null`) the per-node interest oracle consulted by the
|
|
48
|
+
* `$event-bus` inbound handler to decide whether an inbound cross-node event is
|
|
49
|
+
* wanted by any local subscriber on this node. The oracle is read PER-EVENT so a
|
|
50
|
+
* child (un)subscribing takes effect immediately with no re-registration.
|
|
51
|
+
*
|
|
52
|
+
* Only non-retaining nodes (agents) meaningfully filter — a retaining bus (hub
|
|
53
|
+
* main) always accepts every category (it serves `getRecent` + the admin-ui live
|
|
54
|
+
* stream). Installing the oracle on the hub too is therefore harmless and keeps
|
|
55
|
+
* the wiring uniform.
|
|
56
|
+
*/
|
|
57
|
+
export declare function setNodeEventInterest(broker: ServiceBroker, oracle: (() => readonly string[] | null) | null): void;
|
|
58
|
+
/**
|
|
59
|
+
* Cross-node inbound counters for `broker`, or `null` if no cross-node event has
|
|
60
|
+
* been processed yet. Exposed for the D2 shadow burn-in + operator debug —
|
|
61
|
+
* mirror of `LocalChildRegistry.getChildEventStats`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function getMoleculerEventStats(broker: ServiceBroker): MoleculerEventStats | null;
|
|
31
64
|
/**
|
|
32
65
|
* Register the `$event-bus` service on a broker. MUST be called BEFORE
|
|
33
66
|
* `broker.start()` — Moleculer announces a service's event
|
|
@@ -123,6 +123,29 @@ export declare class LocalChildRegistry {
|
|
|
123
123
|
* that explicitly subscribes to a ring-denied category must still RECEIVE it.
|
|
124
124
|
*/
|
|
125
125
|
private childWantsEvent;
|
|
126
|
+
/**
|
|
127
|
+
* D2: this node's aggregate cross-node event interest — the UNION of every
|
|
128
|
+
* connected child's declared category patterns. Consumed by the parent's
|
|
129
|
+
* `$event-bus` inbound gate (via `setNodeEventInterest`) so the node only
|
|
130
|
+
* accepts cross-node (Moleculer) categories at least one local child wants.
|
|
131
|
+
*
|
|
132
|
+
* Returns `null` (fail-open — accept everything) when:
|
|
133
|
+
* - NO child is currently connected (boot window before the first forked
|
|
134
|
+
* child completes its UDS handshake, or every child has disconnected): a
|
|
135
|
+
* node MUST NOT drop 100% of inbound cross-node events during that window,
|
|
136
|
+
* and a child may connect imminently. This is distinct from the
|
|
137
|
+
* declared-empty case below.
|
|
138
|
+
* - ANY connected child is UNDECLARED (`eventPatterns === null`, a legacy
|
|
139
|
+
* runner): a node cannot safely narrow its inbound set while a child's
|
|
140
|
+
* real interest is unknown. Mirrors the per-child fail-open in
|
|
141
|
+
* {@link childWantsEvent}, aggregated conservatively.
|
|
142
|
+
*
|
|
143
|
+
* Returns an EMPTY array only when ≥1 child is connected and EVERY connected
|
|
144
|
+
* child declared an explicit empty set — a genuine "wants nothing". Reads the
|
|
145
|
+
* live `children` map, so a child registering / disconnecting / sending
|
|
146
|
+
* `event-sub` is reflected on the next call with no extra bookkeeping.
|
|
147
|
+
*/
|
|
148
|
+
aggregateEventInterest(): readonly string[] | null;
|
|
126
149
|
private statsFor;
|
|
127
150
|
/** Deduped INFO line whenever a child's declared pattern set changes. */
|
|
128
151
|
private logPatternSet;
|
|
@@ -32,6 +32,18 @@ export interface UdsEventBridgeDeps {
|
|
|
32
32
|
readonly parentBus: IEventBus;
|
|
33
33
|
/** This process's Moleculer node ID (e.g. `'hub'` or `'agent-a1b2c3'`). */
|
|
34
34
|
readonly parentNodeId: string;
|
|
35
|
+
/**
|
|
36
|
+
* D2: subscribe the bridge's cluster/parent-local → children RELAY handler to
|
|
37
|
+
* the parent bus WITHOUT registering it in the node's local-interest surface
|
|
38
|
+
* (`subscribePassthrough` from `@camstack/system`). The bridge is a conduit to
|
|
39
|
+
* forked children, not a terminal local consumer — counting its wildcard `*`
|
|
40
|
+
* subscription would make every cross-node category appear "wanted" and defeat
|
|
41
|
+
* the inbound gate. When omitted (tests / legacy callers) the bridge falls
|
|
42
|
+
* back to `parentBus.subscribe({}, …)`, which is functionally correct but
|
|
43
|
+
* counts toward local interest — acceptable only where the D2 gate is not
|
|
44
|
+
* under test.
|
|
45
|
+
*/
|
|
46
|
+
readonly subscribePassthrough?: (handler: (event: SystemEvent) => void) => () => void;
|
|
35
47
|
}
|
|
36
48
|
/**
|
|
37
49
|
* Create the parent-side UDS ↔ Moleculer event bridge.
|
|
@@ -3459,6 +3459,29 @@ function isHighFrequencyCategory(category) {
|
|
|
3459
3459
|
for (const pattern of RING_BUFFER_DENY_PATTERNS) if (matchesPattern(pattern, category)) return true;
|
|
3460
3460
|
return false;
|
|
3461
3461
|
}
|
|
3462
|
+
function readMoleculerFanoutMode() {
|
|
3463
|
+
const raw = process.env.CAMSTACK_MOLECULER_EVENT_FANOUT;
|
|
3464
|
+
if (raw === "shadow" || raw === "broadcast") return raw;
|
|
3465
|
+
return "filter";
|
|
3466
|
+
}
|
|
3467
|
+
/**
|
|
3468
|
+
* Does this node want to accept an inbound cross-node event in `category`?
|
|
3469
|
+
* The receiving-side mirror of `LocalChildRegistry.childWantsEvent`:
|
|
3470
|
+
* - `broadcast` mode → always (gate disabled).
|
|
3471
|
+
* - a retaining bus (hub main) → always (it serves `getRecent` + admin-ui;
|
|
3472
|
+
* its interest is genuinely everything).
|
|
3473
|
+
* - undeclared interest (`null`) → always (fail-open).
|
|
3474
|
+
* - else the declared union must match via `matchesPattern` — the SAME
|
|
3475
|
+
* function the local subscriber map-key gate uses, giving delivery parity.
|
|
3476
|
+
* `shadow` is handled by the caller (it counts the would-suppress but still
|
|
3477
|
+
* delivers), exactly like the UDS fan-out.
|
|
3478
|
+
*/
|
|
3479
|
+
function crossNodeAcceptsCategory(mode, snapshot, category) {
|
|
3480
|
+
if (mode === "broadcast") return true;
|
|
3481
|
+
if (snapshot.retainRecent) return true;
|
|
3482
|
+
if (snapshot.interest === null) return true;
|
|
3483
|
+
return snapshot.interest.some((p) => matchesPattern(p, category));
|
|
3484
|
+
}
|
|
3462
3485
|
/**
|
|
3463
3486
|
* Deliver `event` to all matching local subscribers and — ONLY on a bus that
|
|
3464
3487
|
* opted into retention (`state.retainRecent`, i.e. the hub main process) and
|
|
@@ -3975,6 +3998,37 @@ var LocalChildRegistry = class {
|
|
|
3975
3998
|
if (entry.eventPatterns === null) return true;
|
|
3976
3999
|
return entry.eventPatterns.some((p) => matchesPattern(p, category));
|
|
3977
4000
|
}
|
|
4001
|
+
/**
|
|
4002
|
+
* D2: this node's aggregate cross-node event interest — the UNION of every
|
|
4003
|
+
* connected child's declared category patterns. Consumed by the parent's
|
|
4004
|
+
* `$event-bus` inbound gate (via `setNodeEventInterest`) so the node only
|
|
4005
|
+
* accepts cross-node (Moleculer) categories at least one local child wants.
|
|
4006
|
+
*
|
|
4007
|
+
* Returns `null` (fail-open — accept everything) when:
|
|
4008
|
+
* - NO child is currently connected (boot window before the first forked
|
|
4009
|
+
* child completes its UDS handshake, or every child has disconnected): a
|
|
4010
|
+
* node MUST NOT drop 100% of inbound cross-node events during that window,
|
|
4011
|
+
* and a child may connect imminently. This is distinct from the
|
|
4012
|
+
* declared-empty case below.
|
|
4013
|
+
* - ANY connected child is UNDECLARED (`eventPatterns === null`, a legacy
|
|
4014
|
+
* runner): a node cannot safely narrow its inbound set while a child's
|
|
4015
|
+
* real interest is unknown. Mirrors the per-child fail-open in
|
|
4016
|
+
* {@link childWantsEvent}, aggregated conservatively.
|
|
4017
|
+
*
|
|
4018
|
+
* Returns an EMPTY array only when ≥1 child is connected and EVERY connected
|
|
4019
|
+
* child declared an explicit empty set — a genuine "wants nothing". Reads the
|
|
4020
|
+
* live `children` map, so a child registering / disconnecting / sending
|
|
4021
|
+
* `event-sub` is reflected on the next call with no extra bookkeeping.
|
|
4022
|
+
*/
|
|
4023
|
+
aggregateEventInterest() {
|
|
4024
|
+
if (this.children.size === 0) return null;
|
|
4025
|
+
const union = /* @__PURE__ */ new Set();
|
|
4026
|
+
for (const entry of this.children.values()) {
|
|
4027
|
+
if (entry.eventPatterns === null) return null;
|
|
4028
|
+
for (const p of entry.eventPatterns) union.add(p);
|
|
4029
|
+
}
|
|
4030
|
+
return [...union];
|
|
4031
|
+
}
|
|
3978
4032
|
statsFor(childId) {
|
|
3979
4033
|
let s = this.childEventStats.get(childId);
|
|
3980
4034
|
if (s === void 0) {
|
|
@@ -4747,7 +4801,7 @@ var MAX_RECENT = 512;
|
|
|
4747
4801
|
* and clears the child-event handler. Call it on process shutdown.
|
|
4748
4802
|
*/
|
|
4749
4803
|
function createUdsEventBridge(deps) {
|
|
4750
|
-
const { registry, parentBus, parentNodeId } = deps;
|
|
4804
|
+
const { registry, parentBus, parentNodeId, subscribePassthrough } = deps;
|
|
4751
4805
|
/**
|
|
4752
4806
|
* In-memory set of event ids for events that originated from one of this
|
|
4753
4807
|
* bridge's UDS children and have already been fanned to siblings + the
|
|
@@ -4766,10 +4820,11 @@ function createUdsEventBridge(deps) {
|
|
|
4766
4820
|
}
|
|
4767
4821
|
parentBus.emit(event);
|
|
4768
4822
|
});
|
|
4769
|
-
const
|
|
4823
|
+
const relayHandler = (event) => {
|
|
4770
4824
|
if (recentlyFannedIds.has(event.id)) return;
|
|
4771
4825
|
registry.broadcastEventToChildren(event, parentNodeId, void 0);
|
|
4772
|
-
}
|
|
4826
|
+
};
|
|
4827
|
+
const unsubscribe = subscribePassthrough !== void 0 ? subscribePassthrough(relayHandler) : parentBus.subscribe({}, relayHandler);
|
|
4773
4828
|
return () => {
|
|
4774
4829
|
unsubscribe();
|
|
4775
4830
|
registry.onChildEvent(null);
|
|
@@ -5861,6 +5916,163 @@ function getSharedBusState(broker, retainRecent = false) {
|
|
|
5861
5916
|
var eventBusServiceInstalled = /* @__PURE__ */ new WeakSet();
|
|
5862
5917
|
var brokerBusWarnTimestamps = /* @__PURE__ */ new WeakMap();
|
|
5863
5918
|
/**
|
|
5919
|
+
* Per-broker node-interest oracle. Returns the FORKED-CHILD interest (the union
|
|
5920
|
+
* of this node's UDS children's declared category patterns), or `null` when it
|
|
5921
|
+
* is undeclared/unknown (a legacy child, or no forked child has connected yet)
|
|
5922
|
+
* → fail-open. Absent (no entry) is also fail-open: pre-D2 behaviour is
|
|
5923
|
+
* preserved until a node wires its interest via {@link setNodeEventInterest}.
|
|
5924
|
+
*
|
|
5925
|
+
* IMPORTANT: this oracle covers ONLY forked/UDS children. In-process
|
|
5926
|
+
* ('broker'-mode) subscribers on this same broker (e.g. each addon context's
|
|
5927
|
+
* `device.bindings-changed` cache-invalidation sub) are tracked SEPARATELY in
|
|
5928
|
+
* {@link brokerLocalInterest}. The gate unions BOTH so it can never starve a
|
|
5929
|
+
* live local subscriber of either kind.
|
|
5930
|
+
*/
|
|
5931
|
+
var brokerNodeInterest = /* @__PURE__ */ new WeakMap();
|
|
5932
|
+
/**
|
|
5933
|
+
* Per-broker IN-PROCESS subscriber interest: category pattern → live refcount.
|
|
5934
|
+
* Populated by `getBrokerEventBus(...).subscribe` (every in-process /
|
|
5935
|
+
* 'broker'-mode subscription) and decremented by its unsubscribe. Does NOT
|
|
5936
|
+
* include the UDS event bridge's pass-through relay subscription — that is a
|
|
5937
|
+
* conduit to forked children (whose real interest the oracle already reports),
|
|
5938
|
+
* not a genuine local consumer, so it registers via {@link subscribePassthrough}
|
|
5939
|
+
* which bypasses this surface. Keeping the bridge out is what lets the gate
|
|
5940
|
+
* actually filter (otherwise the bridge's `*` would make every category wanted).
|
|
5941
|
+
*/
|
|
5942
|
+
var brokerLocalInterest = /* @__PURE__ */ new WeakMap();
|
|
5943
|
+
function bumpLocalInterest(broker, pattern) {
|
|
5944
|
+
let m = brokerLocalInterest.get(broker);
|
|
5945
|
+
if (m === void 0) {
|
|
5946
|
+
m = /* @__PURE__ */ new Map();
|
|
5947
|
+
brokerLocalInterest.set(broker, m);
|
|
5948
|
+
}
|
|
5949
|
+
m.set(pattern, (m.get(pattern) ?? 0) + 1);
|
|
5950
|
+
}
|
|
5951
|
+
function dropLocalInterest(broker, pattern) {
|
|
5952
|
+
const m = brokerLocalInterest.get(broker);
|
|
5953
|
+
if (m === void 0) return;
|
|
5954
|
+
const next = (m.get(pattern) ?? 0) - 1;
|
|
5955
|
+
if (next <= 0) m.delete(pattern);
|
|
5956
|
+
else m.set(pattern, next);
|
|
5957
|
+
}
|
|
5958
|
+
/** Snapshot of the in-process subscriber category patterns for `broker`. */
|
|
5959
|
+
function localSubscriberPatterns(broker) {
|
|
5960
|
+
const m = brokerLocalInterest.get(broker);
|
|
5961
|
+
return m === void 0 ? [] : [...m.keys()];
|
|
5962
|
+
}
|
|
5963
|
+
/**
|
|
5964
|
+
* Subscribe a PASS-THROUGH relay handler to the broker's shared bus WITHOUT
|
|
5965
|
+
* registering it in the local-interest surface. Used exclusively by the UDS
|
|
5966
|
+
* event bridge for its cluster/parent-local → children fan-out subscription:
|
|
5967
|
+
* the bridge must receive every event the gate lets through so it can relay to
|
|
5968
|
+
* forked children, but it is not itself a terminal consumer, so it must not
|
|
5969
|
+
* count toward this node's interest (a counted `*` would defeat the filter).
|
|
5970
|
+
* Returns an unsubscribe function.
|
|
5971
|
+
*/
|
|
5972
|
+
function subscribePassthrough(broker, handler) {
|
|
5973
|
+
const state = getSharedBusState(broker);
|
|
5974
|
+
const entry = {
|
|
5975
|
+
filter: {},
|
|
5976
|
+
categoryPattern: "*",
|
|
5977
|
+
handler
|
|
5978
|
+
};
|
|
5979
|
+
const set = state.handlers.get("*") ?? /* @__PURE__ */ new Set();
|
|
5980
|
+
set.add(entry);
|
|
5981
|
+
state.handlers.set("*", set);
|
|
5982
|
+
return () => {
|
|
5983
|
+
state.handlers.get("*")?.delete(entry);
|
|
5984
|
+
};
|
|
5985
|
+
}
|
|
5986
|
+
/** Per-broker cross-node inbound counters (delivered / would-suppress). */
|
|
5987
|
+
var brokerCrossNodeStats = /* @__PURE__ */ new WeakMap();
|
|
5988
|
+
/**
|
|
5989
|
+
* Install (or clear, with `null`) the per-node interest oracle consulted by the
|
|
5990
|
+
* `$event-bus` inbound handler to decide whether an inbound cross-node event is
|
|
5991
|
+
* wanted by any local subscriber on this node. The oracle is read PER-EVENT so a
|
|
5992
|
+
* child (un)subscribing takes effect immediately with no re-registration.
|
|
5993
|
+
*
|
|
5994
|
+
* Only non-retaining nodes (agents) meaningfully filter — a retaining bus (hub
|
|
5995
|
+
* main) always accepts every category (it serves `getRecent` + the admin-ui live
|
|
5996
|
+
* stream). Installing the oracle on the hub too is therefore harmless and keeps
|
|
5997
|
+
* the wiring uniform.
|
|
5998
|
+
*/
|
|
5999
|
+
function setNodeEventInterest(broker, oracle) {
|
|
6000
|
+
if (oracle === null) brokerNodeInterest.delete(broker);
|
|
6001
|
+
else brokerNodeInterest.set(broker, oracle);
|
|
6002
|
+
}
|
|
6003
|
+
/**
|
|
6004
|
+
* Cross-node inbound counters for `broker`, or `null` if no cross-node event has
|
|
6005
|
+
* been processed yet. Exposed for the D2 shadow burn-in + operator debug —
|
|
6006
|
+
* mirror of `LocalChildRegistry.getChildEventStats`.
|
|
6007
|
+
*/
|
|
6008
|
+
function getMoleculerEventStats(broker) {
|
|
6009
|
+
const s = brokerCrossNodeStats.get(broker);
|
|
6010
|
+
return s === void 0 ? null : {
|
|
6011
|
+
delivered: s.delivered,
|
|
6012
|
+
suppressed: s.suppressed
|
|
6013
|
+
};
|
|
6014
|
+
}
|
|
6015
|
+
function crossNodeStatsFor(broker) {
|
|
6016
|
+
let s = brokerCrossNodeStats.get(broker);
|
|
6017
|
+
if (s === void 0) {
|
|
6018
|
+
s = {
|
|
6019
|
+
delivered: 0,
|
|
6020
|
+
suppressed: 0
|
|
6021
|
+
};
|
|
6022
|
+
brokerCrossNodeStats.set(broker, s);
|
|
6023
|
+
}
|
|
6024
|
+
return s;
|
|
6025
|
+
}
|
|
6026
|
+
/**
|
|
6027
|
+
* Compute this node's COMBINED cross-node interest snapshot for the gate:
|
|
6028
|
+
* - `retainRecent` — from the shared bus (hub main → accept everything).
|
|
6029
|
+
* - `interest` — union of (a) forked-child interest (the oracle) and (b) live
|
|
6030
|
+
* in-process subscriber patterns. `null` (fail-open) when the oracle reports
|
|
6031
|
+
* `null` (undeclared / no forked child yet / oracle threw) — we cannot
|
|
6032
|
+
* safely narrow while a forked child's real interest is unknown, and a boot
|
|
6033
|
+
* window with no children yet must not drop everything.
|
|
6034
|
+
*
|
|
6035
|
+
* The oracle invocation is wrapped in try/catch and fails OPEN on throw — it
|
|
6036
|
+
* sits in front of the per-handler try/catch, in the subsystem that previously
|
|
6037
|
+
* caused an OOM, so a throwing oracle must never break inbound delivery.
|
|
6038
|
+
*/
|
|
6039
|
+
function nodeInterestSnapshot(broker) {
|
|
6040
|
+
const state = getSharedBusState(broker);
|
|
6041
|
+
let childInterest;
|
|
6042
|
+
try {
|
|
6043
|
+
const oracle = brokerNodeInterest.get(broker);
|
|
6044
|
+
childInterest = oracle ? oracle() : null;
|
|
6045
|
+
} catch {
|
|
6046
|
+
childInterest = null;
|
|
6047
|
+
}
|
|
6048
|
+
if (childInterest === null) return {
|
|
6049
|
+
retainRecent: state.retainRecent,
|
|
6050
|
+
interest: null
|
|
6051
|
+
};
|
|
6052
|
+
const local = localSubscriberPatterns(broker);
|
|
6053
|
+
const interest = [...new Set([...local, ...childInterest])];
|
|
6054
|
+
return {
|
|
6055
|
+
retainRecent: state.retainRecent,
|
|
6056
|
+
interest
|
|
6057
|
+
};
|
|
6058
|
+
}
|
|
6059
|
+
/**
|
|
6060
|
+
* Decide + account for an inbound cross-node event on `broker`. Returns whether
|
|
6061
|
+
* the event should be delivered to the local bus. Honours the
|
|
6062
|
+
* `CAMSTACK_MOLECULER_EVENT_FANOUT` mode (`mode`): in `shadow` it still delivers
|
|
6063
|
+
* but records the would-suppress; in `filter` it drops unwanted categories.
|
|
6064
|
+
* The interest is the UNION of forked-child AND in-process subscribers — the
|
|
6065
|
+
* gate never starves a live local subscriber of either kind.
|
|
6066
|
+
*/
|
|
6067
|
+
function acceptInboundCrossNode(broker, mode, category) {
|
|
6068
|
+
const wants = crossNodeAcceptsCategory(mode, nodeInterestSnapshot(broker), category);
|
|
6069
|
+
const stats = crossNodeStatsFor(broker);
|
|
6070
|
+
if (!wants) stats.suppressed++;
|
|
6071
|
+
const deliver = wants || mode === "shadow";
|
|
6072
|
+
if (deliver) stats.delivered++;
|
|
6073
|
+
return deliver;
|
|
6074
|
+
}
|
|
6075
|
+
/**
|
|
5864
6076
|
* Register the `$event-bus` service on a broker. MUST be called BEFORE
|
|
5865
6077
|
* `broker.start()` — Moleculer announces a service's event
|
|
5866
6078
|
* subscriptions to remote nodes only during the discovery handshake;
|
|
@@ -5884,6 +6096,7 @@ function registerEventBusService(broker) {
|
|
|
5884
6096
|
if (eventBusServiceInstalled.has(broker)) return;
|
|
5885
6097
|
eventBusServiceInstalled.add(broker);
|
|
5886
6098
|
const bkr = broker;
|
|
6099
|
+
const fanoutMode = readMoleculerFanoutMode();
|
|
5887
6100
|
try {
|
|
5888
6101
|
bkr.createService({
|
|
5889
6102
|
name: "$event-bus",
|
|
@@ -5891,6 +6104,7 @@ function registerEventBusService(broker) {
|
|
|
5891
6104
|
const event = ctx.params;
|
|
5892
6105
|
if (!event) return;
|
|
5893
6106
|
if (event.sourceNodeId === bkr.nodeID) return;
|
|
6107
|
+
if (!acceptInboundCrossNode(broker, fanoutMode, event.category)) return;
|
|
5894
6108
|
deliverShared(getSharedBusState(broker), event);
|
|
5895
6109
|
} }
|
|
5896
6110
|
});
|
|
@@ -5951,8 +6165,9 @@ function getBrokerEventBus(broker, options) {
|
|
|
5951
6165
|
const set = state.handlers.get(pattern) ?? /* @__PURE__ */ new Set();
|
|
5952
6166
|
set.add(entry);
|
|
5953
6167
|
state.handlers.set(pattern, set);
|
|
6168
|
+
bumpLocalInterest(broker, pattern);
|
|
5954
6169
|
return () => {
|
|
5955
|
-
state.handlers.get(pattern)?.delete(entry);
|
|
6170
|
+
if (state.handlers.get(pattern)?.delete(entry) === true) dropLocalInterest(broker, pattern);
|
|
5956
6171
|
};
|
|
5957
6172
|
},
|
|
5958
6173
|
getRecent(filter, limit) {
|
|
@@ -6852,4 +7067,4 @@ async function installManifestPythonDeps(declaration, addonDir, deps, logger) {
|
|
|
6852
7067
|
await deps.installPythonRequirements(reqAbs);
|
|
6853
7068
|
}
|
|
6854
7069
|
//#endregion
|
|
6855
|
-
export {
|
|
7070
|
+
export { buildNativeCapProxy as $, createHubCapForwardService as A, AGENT_CAP_FWD_ACTION as B, brokerTransportLink as C, localProviderLink as D, ipcParentLink as E, createUdsLogger as F, callWithServiceDiscovery as G, CapRouteResolver as H, createUdsLoggerWithControl as I, UdsLocalTransportServer as J, createLocalTransport as K, LocalChildClient as L, createUdsEventBridge as M, createUdsEventBus as N, HUB_CAP_FWD_ACTION as O, udsChildLogToWorkerEntry as P, encodeFrame as Q, LocalChildRegistry as R, brokerCallForCap as S, ipcChildLink as T, CapRouteError as U, AGENT_CAP_FWD_SERVICE as V, classifyCapRoute as W, localEndpointPath as X, SocketChannel as Y, FrameDecoder as Z, resolveHwAccel as _, CapabilityHandle as _t, getWorkerDeviceRegistry as a, setWorkerNativeCapsChangeListener as at, __resetCapUsageRegistryForTests as b, resolveAddonClass as bt, setHubConnected as c, NATIVE_PROVIDER_SERVICE_INFIX as ct, getMoleculerEventStats as d, capBareAction as dt, buildUdsNativeCapProxy as et, registerEventBusService as f, capServiceName as ft, createKernelHwAccel as g, DeviceRegistry as gt, AddonDepsManager as h, serializeTypedArrays as ht, createUdsAddonContext as i, mountNativeCapService as it, createParentUnownedCallHandler as j, HUB_CAP_FWD_SERVICE as k, EVENT_TOPIC_PREFIX as l, capActionName as lt, subscribePassthrough as m, deserializeTypedArrays as mt, adaptBrokerToCluster as n, getWorkerNativeCapProvider as nt, getOrInitReadinessRegistry as o, createAddonService as ot, setNodeEventInterest as p, parseCapAction as pt, UdsLocalTransportClient as q, createAddonContext as r, getWorkerNativeCapSnapshot as rt, getOrInitReadinessRegistryForClient as s, validateProviderRegistrations as st, installManifestPythonDeps as t, createBrokerDeviceManagerApi as tt, getBrokerEventBus as u, capActionSuffix as ut, createHwAccelService as v, CapabilityUnavailableError as vt, buildLinkChain as w, getCapUsageRegistry as x, CapUsageRegistry as y, installManifestNativeDeps as yt, UDS_NO_ROUTE_PREFIX as z };
|
|
@@ -3461,6 +3461,29 @@ function isHighFrequencyCategory(category) {
|
|
|
3461
3461
|
for (const pattern of RING_BUFFER_DENY_PATTERNS) if (matchesPattern(pattern, category)) return true;
|
|
3462
3462
|
return false;
|
|
3463
3463
|
}
|
|
3464
|
+
function readMoleculerFanoutMode() {
|
|
3465
|
+
const raw = process.env.CAMSTACK_MOLECULER_EVENT_FANOUT;
|
|
3466
|
+
if (raw === "shadow" || raw === "broadcast") return raw;
|
|
3467
|
+
return "filter";
|
|
3468
|
+
}
|
|
3469
|
+
/**
|
|
3470
|
+
* Does this node want to accept an inbound cross-node event in `category`?
|
|
3471
|
+
* The receiving-side mirror of `LocalChildRegistry.childWantsEvent`:
|
|
3472
|
+
* - `broadcast` mode → always (gate disabled).
|
|
3473
|
+
* - a retaining bus (hub main) → always (it serves `getRecent` + admin-ui;
|
|
3474
|
+
* its interest is genuinely everything).
|
|
3475
|
+
* - undeclared interest (`null`) → always (fail-open).
|
|
3476
|
+
* - else the declared union must match via `matchesPattern` — the SAME
|
|
3477
|
+
* function the local subscriber map-key gate uses, giving delivery parity.
|
|
3478
|
+
* `shadow` is handled by the caller (it counts the would-suppress but still
|
|
3479
|
+
* delivers), exactly like the UDS fan-out.
|
|
3480
|
+
*/
|
|
3481
|
+
function crossNodeAcceptsCategory(mode, snapshot, category) {
|
|
3482
|
+
if (mode === "broadcast") return true;
|
|
3483
|
+
if (snapshot.retainRecent) return true;
|
|
3484
|
+
if (snapshot.interest === null) return true;
|
|
3485
|
+
return snapshot.interest.some((p) => matchesPattern(p, category));
|
|
3486
|
+
}
|
|
3464
3487
|
/**
|
|
3465
3488
|
* Deliver `event` to all matching local subscribers and — ONLY on a bus that
|
|
3466
3489
|
* opted into retention (`state.retainRecent`, i.e. the hub main process) and
|
|
@@ -3977,6 +4000,37 @@ var LocalChildRegistry = class {
|
|
|
3977
4000
|
if (entry.eventPatterns === null) return true;
|
|
3978
4001
|
return entry.eventPatterns.some((p) => matchesPattern(p, category));
|
|
3979
4002
|
}
|
|
4003
|
+
/**
|
|
4004
|
+
* D2: this node's aggregate cross-node event interest — the UNION of every
|
|
4005
|
+
* connected child's declared category patterns. Consumed by the parent's
|
|
4006
|
+
* `$event-bus` inbound gate (via `setNodeEventInterest`) so the node only
|
|
4007
|
+
* accepts cross-node (Moleculer) categories at least one local child wants.
|
|
4008
|
+
*
|
|
4009
|
+
* Returns `null` (fail-open — accept everything) when:
|
|
4010
|
+
* - NO child is currently connected (boot window before the first forked
|
|
4011
|
+
* child completes its UDS handshake, or every child has disconnected): a
|
|
4012
|
+
* node MUST NOT drop 100% of inbound cross-node events during that window,
|
|
4013
|
+
* and a child may connect imminently. This is distinct from the
|
|
4014
|
+
* declared-empty case below.
|
|
4015
|
+
* - ANY connected child is UNDECLARED (`eventPatterns === null`, a legacy
|
|
4016
|
+
* runner): a node cannot safely narrow its inbound set while a child's
|
|
4017
|
+
* real interest is unknown. Mirrors the per-child fail-open in
|
|
4018
|
+
* {@link childWantsEvent}, aggregated conservatively.
|
|
4019
|
+
*
|
|
4020
|
+
* Returns an EMPTY array only when ≥1 child is connected and EVERY connected
|
|
4021
|
+
* child declared an explicit empty set — a genuine "wants nothing". Reads the
|
|
4022
|
+
* live `children` map, so a child registering / disconnecting / sending
|
|
4023
|
+
* `event-sub` is reflected on the next call with no extra bookkeeping.
|
|
4024
|
+
*/
|
|
4025
|
+
aggregateEventInterest() {
|
|
4026
|
+
if (this.children.size === 0) return null;
|
|
4027
|
+
const union = /* @__PURE__ */ new Set();
|
|
4028
|
+
for (const entry of this.children.values()) {
|
|
4029
|
+
if (entry.eventPatterns === null) return null;
|
|
4030
|
+
for (const p of entry.eventPatterns) union.add(p);
|
|
4031
|
+
}
|
|
4032
|
+
return [...union];
|
|
4033
|
+
}
|
|
3980
4034
|
statsFor(childId) {
|
|
3981
4035
|
let s = this.childEventStats.get(childId);
|
|
3982
4036
|
if (s === void 0) {
|
|
@@ -4749,7 +4803,7 @@ var MAX_RECENT = 512;
|
|
|
4749
4803
|
* and clears the child-event handler. Call it on process shutdown.
|
|
4750
4804
|
*/
|
|
4751
4805
|
function createUdsEventBridge(deps) {
|
|
4752
|
-
const { registry, parentBus, parentNodeId } = deps;
|
|
4806
|
+
const { registry, parentBus, parentNodeId, subscribePassthrough } = deps;
|
|
4753
4807
|
/**
|
|
4754
4808
|
* In-memory set of event ids for events that originated from one of this
|
|
4755
4809
|
* bridge's UDS children and have already been fanned to siblings + the
|
|
@@ -4768,10 +4822,11 @@ function createUdsEventBridge(deps) {
|
|
|
4768
4822
|
}
|
|
4769
4823
|
parentBus.emit(event);
|
|
4770
4824
|
});
|
|
4771
|
-
const
|
|
4825
|
+
const relayHandler = (event) => {
|
|
4772
4826
|
if (recentlyFannedIds.has(event.id)) return;
|
|
4773
4827
|
registry.broadcastEventToChildren(event, parentNodeId, void 0);
|
|
4774
|
-
}
|
|
4828
|
+
};
|
|
4829
|
+
const unsubscribe = subscribePassthrough !== void 0 ? subscribePassthrough(relayHandler) : parentBus.subscribe({}, relayHandler);
|
|
4775
4830
|
return () => {
|
|
4776
4831
|
unsubscribe();
|
|
4777
4832
|
registry.onChildEvent(null);
|
|
@@ -5863,6 +5918,163 @@ function getSharedBusState(broker, retainRecent = false) {
|
|
|
5863
5918
|
var eventBusServiceInstalled = /* @__PURE__ */ new WeakSet();
|
|
5864
5919
|
var brokerBusWarnTimestamps = /* @__PURE__ */ new WeakMap();
|
|
5865
5920
|
/**
|
|
5921
|
+
* Per-broker node-interest oracle. Returns the FORKED-CHILD interest (the union
|
|
5922
|
+
* of this node's UDS children's declared category patterns), or `null` when it
|
|
5923
|
+
* is undeclared/unknown (a legacy child, or no forked child has connected yet)
|
|
5924
|
+
* → fail-open. Absent (no entry) is also fail-open: pre-D2 behaviour is
|
|
5925
|
+
* preserved until a node wires its interest via {@link setNodeEventInterest}.
|
|
5926
|
+
*
|
|
5927
|
+
* IMPORTANT: this oracle covers ONLY forked/UDS children. In-process
|
|
5928
|
+
* ('broker'-mode) subscribers on this same broker (e.g. each addon context's
|
|
5929
|
+
* `device.bindings-changed` cache-invalidation sub) are tracked SEPARATELY in
|
|
5930
|
+
* {@link brokerLocalInterest}. The gate unions BOTH so it can never starve a
|
|
5931
|
+
* live local subscriber of either kind.
|
|
5932
|
+
*/
|
|
5933
|
+
var brokerNodeInterest = /* @__PURE__ */ new WeakMap();
|
|
5934
|
+
/**
|
|
5935
|
+
* Per-broker IN-PROCESS subscriber interest: category pattern → live refcount.
|
|
5936
|
+
* Populated by `getBrokerEventBus(...).subscribe` (every in-process /
|
|
5937
|
+
* 'broker'-mode subscription) and decremented by its unsubscribe. Does NOT
|
|
5938
|
+
* include the UDS event bridge's pass-through relay subscription — that is a
|
|
5939
|
+
* conduit to forked children (whose real interest the oracle already reports),
|
|
5940
|
+
* not a genuine local consumer, so it registers via {@link subscribePassthrough}
|
|
5941
|
+
* which bypasses this surface. Keeping the bridge out is what lets the gate
|
|
5942
|
+
* actually filter (otherwise the bridge's `*` would make every category wanted).
|
|
5943
|
+
*/
|
|
5944
|
+
var brokerLocalInterest = /* @__PURE__ */ new WeakMap();
|
|
5945
|
+
function bumpLocalInterest(broker, pattern) {
|
|
5946
|
+
let m = brokerLocalInterest.get(broker);
|
|
5947
|
+
if (m === void 0) {
|
|
5948
|
+
m = /* @__PURE__ */ new Map();
|
|
5949
|
+
brokerLocalInterest.set(broker, m);
|
|
5950
|
+
}
|
|
5951
|
+
m.set(pattern, (m.get(pattern) ?? 0) + 1);
|
|
5952
|
+
}
|
|
5953
|
+
function dropLocalInterest(broker, pattern) {
|
|
5954
|
+
const m = brokerLocalInterest.get(broker);
|
|
5955
|
+
if (m === void 0) return;
|
|
5956
|
+
const next = (m.get(pattern) ?? 0) - 1;
|
|
5957
|
+
if (next <= 0) m.delete(pattern);
|
|
5958
|
+
else m.set(pattern, next);
|
|
5959
|
+
}
|
|
5960
|
+
/** Snapshot of the in-process subscriber category patterns for `broker`. */
|
|
5961
|
+
function localSubscriberPatterns(broker) {
|
|
5962
|
+
const m = brokerLocalInterest.get(broker);
|
|
5963
|
+
return m === void 0 ? [] : [...m.keys()];
|
|
5964
|
+
}
|
|
5965
|
+
/**
|
|
5966
|
+
* Subscribe a PASS-THROUGH relay handler to the broker's shared bus WITHOUT
|
|
5967
|
+
* registering it in the local-interest surface. Used exclusively by the UDS
|
|
5968
|
+
* event bridge for its cluster/parent-local → children fan-out subscription:
|
|
5969
|
+
* the bridge must receive every event the gate lets through so it can relay to
|
|
5970
|
+
* forked children, but it is not itself a terminal consumer, so it must not
|
|
5971
|
+
* count toward this node's interest (a counted `*` would defeat the filter).
|
|
5972
|
+
* Returns an unsubscribe function.
|
|
5973
|
+
*/
|
|
5974
|
+
function subscribePassthrough(broker, handler) {
|
|
5975
|
+
const state = getSharedBusState(broker);
|
|
5976
|
+
const entry = {
|
|
5977
|
+
filter: {},
|
|
5978
|
+
categoryPattern: "*",
|
|
5979
|
+
handler
|
|
5980
|
+
};
|
|
5981
|
+
const set = state.handlers.get("*") ?? /* @__PURE__ */ new Set();
|
|
5982
|
+
set.add(entry);
|
|
5983
|
+
state.handlers.set("*", set);
|
|
5984
|
+
return () => {
|
|
5985
|
+
state.handlers.get("*")?.delete(entry);
|
|
5986
|
+
};
|
|
5987
|
+
}
|
|
5988
|
+
/** Per-broker cross-node inbound counters (delivered / would-suppress). */
|
|
5989
|
+
var brokerCrossNodeStats = /* @__PURE__ */ new WeakMap();
|
|
5990
|
+
/**
|
|
5991
|
+
* Install (or clear, with `null`) the per-node interest oracle consulted by the
|
|
5992
|
+
* `$event-bus` inbound handler to decide whether an inbound cross-node event is
|
|
5993
|
+
* wanted by any local subscriber on this node. The oracle is read PER-EVENT so a
|
|
5994
|
+
* child (un)subscribing takes effect immediately with no re-registration.
|
|
5995
|
+
*
|
|
5996
|
+
* Only non-retaining nodes (agents) meaningfully filter — a retaining bus (hub
|
|
5997
|
+
* main) always accepts every category (it serves `getRecent` + the admin-ui live
|
|
5998
|
+
* stream). Installing the oracle on the hub too is therefore harmless and keeps
|
|
5999
|
+
* the wiring uniform.
|
|
6000
|
+
*/
|
|
6001
|
+
function setNodeEventInterest(broker, oracle) {
|
|
6002
|
+
if (oracle === null) brokerNodeInterest.delete(broker);
|
|
6003
|
+
else brokerNodeInterest.set(broker, oracle);
|
|
6004
|
+
}
|
|
6005
|
+
/**
|
|
6006
|
+
* Cross-node inbound counters for `broker`, or `null` if no cross-node event has
|
|
6007
|
+
* been processed yet. Exposed for the D2 shadow burn-in + operator debug —
|
|
6008
|
+
* mirror of `LocalChildRegistry.getChildEventStats`.
|
|
6009
|
+
*/
|
|
6010
|
+
function getMoleculerEventStats(broker) {
|
|
6011
|
+
const s = brokerCrossNodeStats.get(broker);
|
|
6012
|
+
return s === void 0 ? null : {
|
|
6013
|
+
delivered: s.delivered,
|
|
6014
|
+
suppressed: s.suppressed
|
|
6015
|
+
};
|
|
6016
|
+
}
|
|
6017
|
+
function crossNodeStatsFor(broker) {
|
|
6018
|
+
let s = brokerCrossNodeStats.get(broker);
|
|
6019
|
+
if (s === void 0) {
|
|
6020
|
+
s = {
|
|
6021
|
+
delivered: 0,
|
|
6022
|
+
suppressed: 0
|
|
6023
|
+
};
|
|
6024
|
+
brokerCrossNodeStats.set(broker, s);
|
|
6025
|
+
}
|
|
6026
|
+
return s;
|
|
6027
|
+
}
|
|
6028
|
+
/**
|
|
6029
|
+
* Compute this node's COMBINED cross-node interest snapshot for the gate:
|
|
6030
|
+
* - `retainRecent` — from the shared bus (hub main → accept everything).
|
|
6031
|
+
* - `interest` — union of (a) forked-child interest (the oracle) and (b) live
|
|
6032
|
+
* in-process subscriber patterns. `null` (fail-open) when the oracle reports
|
|
6033
|
+
* `null` (undeclared / no forked child yet / oracle threw) — we cannot
|
|
6034
|
+
* safely narrow while a forked child's real interest is unknown, and a boot
|
|
6035
|
+
* window with no children yet must not drop everything.
|
|
6036
|
+
*
|
|
6037
|
+
* The oracle invocation is wrapped in try/catch and fails OPEN on throw — it
|
|
6038
|
+
* sits in front of the per-handler try/catch, in the subsystem that previously
|
|
6039
|
+
* caused an OOM, so a throwing oracle must never break inbound delivery.
|
|
6040
|
+
*/
|
|
6041
|
+
function nodeInterestSnapshot(broker) {
|
|
6042
|
+
const state = getSharedBusState(broker);
|
|
6043
|
+
let childInterest;
|
|
6044
|
+
try {
|
|
6045
|
+
const oracle = brokerNodeInterest.get(broker);
|
|
6046
|
+
childInterest = oracle ? oracle() : null;
|
|
6047
|
+
} catch {
|
|
6048
|
+
childInterest = null;
|
|
6049
|
+
}
|
|
6050
|
+
if (childInterest === null) return {
|
|
6051
|
+
retainRecent: state.retainRecent,
|
|
6052
|
+
interest: null
|
|
6053
|
+
};
|
|
6054
|
+
const local = localSubscriberPatterns(broker);
|
|
6055
|
+
const interest = [...new Set([...local, ...childInterest])];
|
|
6056
|
+
return {
|
|
6057
|
+
retainRecent: state.retainRecent,
|
|
6058
|
+
interest
|
|
6059
|
+
};
|
|
6060
|
+
}
|
|
6061
|
+
/**
|
|
6062
|
+
* Decide + account for an inbound cross-node event on `broker`. Returns whether
|
|
6063
|
+
* the event should be delivered to the local bus. Honours the
|
|
6064
|
+
* `CAMSTACK_MOLECULER_EVENT_FANOUT` mode (`mode`): in `shadow` it still delivers
|
|
6065
|
+
* but records the would-suppress; in `filter` it drops unwanted categories.
|
|
6066
|
+
* The interest is the UNION of forked-child AND in-process subscribers — the
|
|
6067
|
+
* gate never starves a live local subscriber of either kind.
|
|
6068
|
+
*/
|
|
6069
|
+
function acceptInboundCrossNode(broker, mode, category) {
|
|
6070
|
+
const wants = crossNodeAcceptsCategory(mode, nodeInterestSnapshot(broker), category);
|
|
6071
|
+
const stats = crossNodeStatsFor(broker);
|
|
6072
|
+
if (!wants) stats.suppressed++;
|
|
6073
|
+
const deliver = wants || mode === "shadow";
|
|
6074
|
+
if (deliver) stats.delivered++;
|
|
6075
|
+
return deliver;
|
|
6076
|
+
}
|
|
6077
|
+
/**
|
|
5866
6078
|
* Register the `$event-bus` service on a broker. MUST be called BEFORE
|
|
5867
6079
|
* `broker.start()` — Moleculer announces a service's event
|
|
5868
6080
|
* subscriptions to remote nodes only during the discovery handshake;
|
|
@@ -5886,6 +6098,7 @@ function registerEventBusService(broker) {
|
|
|
5886
6098
|
if (eventBusServiceInstalled.has(broker)) return;
|
|
5887
6099
|
eventBusServiceInstalled.add(broker);
|
|
5888
6100
|
const bkr = broker;
|
|
6101
|
+
const fanoutMode = readMoleculerFanoutMode();
|
|
5889
6102
|
try {
|
|
5890
6103
|
bkr.createService({
|
|
5891
6104
|
name: "$event-bus",
|
|
@@ -5893,6 +6106,7 @@ function registerEventBusService(broker) {
|
|
|
5893
6106
|
const event = ctx.params;
|
|
5894
6107
|
if (!event) return;
|
|
5895
6108
|
if (event.sourceNodeId === bkr.nodeID) return;
|
|
6109
|
+
if (!acceptInboundCrossNode(broker, fanoutMode, event.category)) return;
|
|
5896
6110
|
deliverShared(getSharedBusState(broker), event);
|
|
5897
6111
|
} }
|
|
5898
6112
|
});
|
|
@@ -5953,8 +6167,9 @@ function getBrokerEventBus(broker, options) {
|
|
|
5953
6167
|
const set = state.handlers.get(pattern) ?? /* @__PURE__ */ new Set();
|
|
5954
6168
|
set.add(entry);
|
|
5955
6169
|
state.handlers.set(pattern, set);
|
|
6170
|
+
bumpLocalInterest(broker, pattern);
|
|
5956
6171
|
return () => {
|
|
5957
|
-
state.handlers.get(pattern)?.delete(entry);
|
|
6172
|
+
if (state.handlers.get(pattern)?.delete(entry) === true) dropLocalInterest(broker, pattern);
|
|
5958
6173
|
};
|
|
5959
6174
|
},
|
|
5960
6175
|
getRecent(filter, limit) {
|
|
@@ -7154,6 +7369,12 @@ Object.defineProperty(exports, "getCapUsageRegistry", {
|
|
|
7154
7369
|
return getCapUsageRegistry;
|
|
7155
7370
|
}
|
|
7156
7371
|
});
|
|
7372
|
+
Object.defineProperty(exports, "getMoleculerEventStats", {
|
|
7373
|
+
enumerable: true,
|
|
7374
|
+
get: function() {
|
|
7375
|
+
return getMoleculerEventStats;
|
|
7376
|
+
}
|
|
7377
|
+
});
|
|
7157
7378
|
Object.defineProperty(exports, "getOrInitReadinessRegistry", {
|
|
7158
7379
|
enumerable: true,
|
|
7159
7380
|
get: function() {
|
|
@@ -7262,12 +7483,24 @@ Object.defineProperty(exports, "setHubConnected", {
|
|
|
7262
7483
|
return setHubConnected;
|
|
7263
7484
|
}
|
|
7264
7485
|
});
|
|
7486
|
+
Object.defineProperty(exports, "setNodeEventInterest", {
|
|
7487
|
+
enumerable: true,
|
|
7488
|
+
get: function() {
|
|
7489
|
+
return setNodeEventInterest;
|
|
7490
|
+
}
|
|
7491
|
+
});
|
|
7265
7492
|
Object.defineProperty(exports, "setWorkerNativeCapsChangeListener", {
|
|
7266
7493
|
enumerable: true,
|
|
7267
7494
|
get: function() {
|
|
7268
7495
|
return setWorkerNativeCapsChangeListener;
|
|
7269
7496
|
}
|
|
7270
7497
|
});
|
|
7498
|
+
Object.defineProperty(exports, "subscribePassthrough", {
|
|
7499
|
+
enumerable: true,
|
|
7500
|
+
get: function() {
|
|
7501
|
+
return subscribePassthrough;
|
|
7502
|
+
}
|
|
7503
|
+
});
|
|
7271
7504
|
Object.defineProperty(exports, "udsChildLogToWorkerEntry", {
|
|
7272
7505
|
enumerable: true,
|
|
7273
7506
|
get: function() {
|