Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: createNodeConnector API returns ready to use node connector instead of promise #1242

Merged
merged 6 commits into from
Dec 16, 2023

Conversation

abose
Copy link
Member

@abose abose commented Dec 16, 2023

NodeConnector

Node Connector Communication Module

This module simplifies communication between Node.js and Phoenix (phcode). A NodeConnector acts as an intermediary,
allowing you to execute functions in Node.js from Phoenix and vice versa. You can use the execPeer method to call
functions on the other side and handle communication seamlessly. Use triggerPeer to trigger events
on the other side.

Setting Up a NodeConnector

To establish communication between two modules, such as x.js in Phoenix and y.js in Node.js, follow these steps:

Create NodeConnector in Phoenix (x.js)

const NodeConnector = require('NodeConnector');
const XY_NODE_CONNECTOR_ID = 'ext_x_y'; // Use a unique ID
let nodeConnector = NodeConnector.createNodeConnector(XY_NODE_CONNECTOR_ID, exports);

exports.modifyImage = async function(imageName, imageArrayBuffer) {
  // Perform image operations with the imageArrayBuffer
  // To return an ArrayBuffer, return an object with a `buffer` key.
  return {
    operationDone: 'colored, cropped',
    buffer: imageArrayBuffer,
  };
};

Create NodeConnector in Node.js (y.js)

const XY_NODE_CONNECTOR_ID = 'ext_x_y'; // Use the same unique ID
let nodeConnector = global.createNodeConnector(XY_NODE_CONNECTOR_ID, exports);

exports.getPWDRelative = async function(subPath) {
  return process.cwd + '/' + subPath;
};

With these steps, a NodeConnector is set up, enabling two-way communication.

Executing Functions

To call a Node.js function from Phoenix, use the execPeer method.

// In `x.js` (Phoenix)
const fullPath = await nodeConnector.execPeer('getPWDRelative', 'sub/path.html');

To execute a Phoenix function from Node.js and transfer binary data, pass an optional ArrayBuffer.

// In `y.js` (Node.js)
const { operationDone, buffer } = await nodeConnector.execPeer('modifyImage', {name:'theHills.png'}, imageAsArrayBuffer);

Event Handling

The NodeConnector object implements all the APIs supported by utils/EventDispatcher. You can trigger and listen
to events between Node.js and Phoenix using the triggerPeer and (on, one or off) methods.

// In `y.js` (Node.js)
nodeConnector.on('phoenixProjectOpened', (_event, projectPath) => {
  console.log(projectPath);
});

nodeConnector.one('phoenixProjectOpened', (_event, projectPath) => {
  console.log(projectPath + "will be received only once");
});

To raise an event from Phoenix to Node.js:

// In `x.js` (Phoenix)
nodeConnector.triggerPeer('phoenixProjectOpened', '/x/project/folder');

To Switch off events

nodeConnector.off('phoenixProjectOpened'); // will switch off all event handlers of that name.

By Default, all events handlers with the eventName is removed when you call nodeConnector.off(eventName) fn.
To selectively switch off event handlers, please see reference for utils/EventDispatcher module.

Handling ArrayBuffer Data in Function Execution

When executing functions that send or receive binary data, ensure that the functions are asynchronous and accept an
optional ArrayBuffer as a parameter. To return binary data, use an object with a buffer key.

Example of calling a function in Node.js with binary data transfer:

// In `y.js` (Node.js)
const { operationDone, buffer } = await nodeConnector.execPeer('modifyImage', {name:'name.png'}, imageArrayBuffer);

Handling ArrayBuffer Data in Event Handling

Use the triggerPeer method to send binary data in events. Include the ArrayBuffer as an optional parameter.

Example of sending binary data in an event from Phoenix to Node.js:

// In `x.js` (Phoenix)
const imageArrayBuffer = getSomeImageArrayBuffer(); // Get the ArrayBuffer
nodeConnector.triggerPeer('imageEdited', 'name.png', imageArrayBuffer);
  • Caveats

  • Be cautious when sending large binary data, as it may affect performance and memory usage. Transferring large
    data is fully supported, but be mindful of performance.
  • Functions called with execPeer and triggerPeer must be asynchronous and accept a single argument. An optional
    second argument can be used to transfer large binary data as an ArrayBuffer.

For more event handling operations and details, refer to the documentation for the utils/EventDispatcher module.

createNodeConnector

Creates a new node connector with the specified ID and module exports.

Returns a NodeConnector Object (which is an EventDispatcher with
additional execPeer and triggerPeer methods. peer here means, if you are executing execPeer
in Phoenix, it will execute the named function in node side, and vice versa. You can right away start
using execPeer, triggerPeer(to send/receive events) APIs without waiting to check if the
other side nodeConnector is created.

Note: If the NodeConnector has not been created on the other end, requests made with execPeer or
triggerPeer will be temporarily queued for up to 10 seconds to allow time for the connector to be created.
If the connector is not created within this timeout period, all queued execPeer requests will be rejected,
and all queued events will be dropped. It is recommended to call the createNodeConnector API on both ends
within a timeframe of less than 10 seconds(ideally same time) for seamless communication.

  • execPeer: A function that executes a peer function with specified parameters.
  • triggerPeer: A function that triggers an event to be sent to a peer.
  • Also contains all the APIs supported by utils/EventDispatcher module.

Parameters

  • nodeConnectorID string The unique identifier for the new node connector.
  • moduleExports Object The exports of the module that contains the functions to be executed on the other side.
  • Throws Error If a node connector with the same ID already exists/invalid args passed.

Returns {execPeer: function, triggerPeer: function, trigger: function, on: function, off: function, one: function} A NodeConnector Object. Also contains all the APIs supported by utils/EventDispatcher module.

isNodeAvailable

Checks if Node.js Engine is available.

Returns boolean Returns true if Node.js Engine is available.

@phoenixide
Copy link
Member

Thank You for making this pull request.

@phoenixide
Copy link
Member

Thank You for making this pull request.

Copy link

Quality Gate Passed Quality Gate passed

Kudos, no new issues were introduced!

0 New issues
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

@phoenixide
Copy link
Member

Thank You for making this pull request.

@abose abose merged commit 6cb36dd into main Dec 16, 2023
16 checks passed
@abose abose deleted the nc branch December 16, 2023 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants