Frontmatter
| id | 9544 |
| title | Enhance RemoteMethodAccess to Support Instance-to-Instance Routing |
| state | Closed |
| labels | enhancementaiarchitecturecore |
| assignees | tobiu |
| createdAt | Mar 24, 2026, 8:31 PM |
| updatedAt | Mar 25, 2026, 9:38 AM |
| githubUrl | https://github.com/neomjs/neo/issues/9544 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | 9449 |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Mar 24, 2026, 8:44 PM |
Enhance RemoteMethodAccess to Support Instance-to-Instance Routing

Input from Gemini 3.1 Pro:
✦ I have successfully implemented and merged the enhancement to the
RemoteMethodAccess(RMA) mixin.Architectural Briefing: Instance-to-Instance IPC
For future developers and AI agents reviewing this architecture, it is critical to understand how RMA now bridges the isolated memory spaces of different worker threads.
The Challenge: Each worker thread (App Worker, Data Worker, etc.) has its own completely isolated Javascript memory space, its own
idCounter, and its ownNeo.manager.Instanceregistry. Because of this, an ID likepipeline-1might exist in both the App Worker and the Data Worker simultaneously, but they refer to completely different objects in their respective memory spaces.The Solution: The Illusion of Global IDs & The Handshake We bypass this limitation not by creating truly global IDs, but by exchanging local IDs between threads in a "Handshake":
The Handshake (Exchange of Local IDs): When an instance in the App Worker (e.g., App-Pipeline, local ID:
app-pipe-1) wants to spawn a counterpart in the Data Worker, it sends acreateInstanceIPC message. Crucially, it includes its own ID in the config payload sent over the wire:{ appPipelineId: 'app-pipe-1' }. The Data Worker receives this, creates its own local instance (e.g., Data-Pipeline, local ID:data-pipe-4), and replies with its newly generated ID. Now, both instances know the local ID of their counterpart in the other thread's memory space.The Execution (Bi-Directional RMA): We enhanced
src/worker/mixin/RemoteMethodAccess.mjsto recognize a newremoteIdproperty in IPC messages.
- App -> Data: When the App Worker wants to execute
read()remotely, it callsthis.generateRemote({ origin: 'data', id: 'data-pipe-4' }, 'read'). When this message arrives in the Data Worker, RMA intercepts it, seesremoteId: 'data-pipe-4', and successfully looks it up in the Data Worker's localInstancemanager.- Data -> App: When the Data Worker needs to push streaming data back, it uses the ID it received during the handshake:
this.generateRemote({ origin: 'app', id: 'app-pipe-1' }, 'onParserData'). This message arrives in the App Worker, and RMA finds it in the App Worker's local registry.Summary By adding
msg.remoteIdto the RMA mixin, we have created a decoupled, bidirectional IPC layer for instances. The RMA mixin does not care how you acquired the ID; it trusts that if you provide adestinationworker and aremoteId, it will route the method call directly to that instance within the target worker's isolated registry. This elegant mechanism powers the entire cross-worker Unified Data Pipeline.
Goal
Upgrade the
RemoteMethodAccess(RMA) mixin to support routing messages to specific class instances across worker boundaries, rather than being limited to static Singletons.Context
Currently, the RMA mixin (
src/worker/mixin/RemoteMethodAccess.mjs) resolves remote method targets exclusively via static namespaces (e.g.,let pkg = Neo.ns(msg.remoteClassName)). This works perfectly for Singletons like Managers or Main Thread Addons.However, to support the new
Neo.data.Pipelinearchitecture (Epic #9449) where an App Worker Pipeline dynamically spawns and communicates with a counterpart Pipeline instance in the Data Worker, we need a generic way to target instances by theirid.Instead of hardcoding domain-specific routers (like an
onPipelineExecutehandler) insideNeo.worker.Data, we should elevate RMA to be a universal, bi-directional instance-to-instance communication layer.Acceptance Criteria
onRemoteMethodinsrc/worker/mixin/RemoteMethodAccess.mjsto check the incomingmsgpayload for a target instance ID (e.g.,msg.instanceId).instanceIdis provided, resolve the target object usingNeo.manager.Instance.get(msg.instanceId).Neo.ns(className)) to maintain backward compatibility for all existing Singletons.