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

feat: add ipc wrappers #261

Merged
merged 31 commits into from
Sep 21, 2023
Merged

feat: add ipc wrappers #261

merged 31 commits into from
Sep 21, 2023

Conversation

achou11
Copy link
Member

@achou11 achou11 commented Sep 12, 2023

Closes #259

Adds IPC wrappers to allow usage where there are separate processes for the "client" and "server" side code such as React Native (via NodeJS Mobile) and Electron. These platforms typically provide some kind of channeling API that sets communication over an IPC layer, but plain usage of these APIs usually requires a decent amount of boilerplate code that matches client IPC requests to the desired server function calls and then communicating results back to the client. Using rpc-reflector, these wrappers bypass the boilerplate and allow normal usage of the server side API to occur on the client side.

// On the server (e.g. NodeJS process)

const server = createMapeoServer(manager, serverPort)
// On the client (e.g. browser window, react native's runtime, etc)

const client = createMapeoClient(clientPort)

const projectId = await client.createProject({ name: 'mapeo' })

const project = await client.getProject(projectId)

const projectSettings =. await project.$getProjectSettings()

@achou11
Copy link
Member Author

achou11 commented Sep 12, 2023

@gmaclennan requesting review as in "I need help with figuring out the bugs" 😄

src/ipc-wrapper/server.js Outdated Show resolved Hide resolved
@achou11 achou11 changed the title WIP: add ipc wrappers feat: add ipc wrappers Sep 13, 2023
test for this is currently failing. case with client.getProject is not
behaving as expected
@achou11
Copy link
Member Author

achou11 commented Sep 13, 2023

running into what seems like race condition in the second test related to client.getProject(). think there's still more work to be done in terms of properly closing rpc things, so maybe that would fix it

src/ipc-wrapper/client.js Outdated Show resolved Hide resolved
src/ipc-wrapper/client.js Outdated Show resolved Hide resolved
src/ipc-wrapper/client.js Show resolved Hide resolved
src/ipc-wrapper/server.js Outdated Show resolved Hide resolved
/**
* @extends {TypedEmitter<Events>}
*/
export class SubChannel extends TypedEmitter {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wondering if i should avoid using TypedEmitter for this so that this can run in a browser environment as well (it's used for both server and client).

I havea local implementation that works using EventTarget based on this helpful post.

one of the main differences is the spec for the dispatchEvent() method:

The dispatchEvent() method of the EventTarget sends an Event to the object, (synchronously) invoking the affected event listeners in the appropriate order. The normal event processing rules (including the capturing and optional bubbling phase) also apply to events dispatched manually with dispatchEvent().

Most notably the part about synchronously invoking listeners. Not sure if the Node implementation adheres to this or if it still behaves similar to an event emitter, but wondering if this specific detail could cause problems in our case or not.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess the simpler option would be using https://github.com/primus/eventemitter3, which is what rpc-reflector uses.

it's cool that the EventTarget approach works for our use case though!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed via e067dc3 (using eventemitter3)

@achou11 achou11 marked this pull request as ready for review September 14, 2023 18:09
Copy link
Member

@gmaclennan gmaclennan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this, this is tricky code and you've solved it really well. I realised reading through this that we need to handle the case of a project not being found, or an error when doing manager.getProject(). I have given a suggestion about how to do this. We don't need a whole SubChannel for this, we just need to pass a message somehow to the client.

src/ipc-wrapper/client.js Outdated Show resolved Hide resolved
src/ipc-wrapper/client.js Outdated Show resolved Hide resolved
src/ipc-wrapper/client.js Show resolved Hide resolved
* @param {import('../types.js').ProjectPublicId} projectPublicId
* @returns {Promise<import('rpc-reflector/client.js').ClientApi<import('../mapeo-project.js').MapeoProject>>}
*/
function createProjectClient(projectPublicId) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this out of the scope of get(), into the createMapeoClient() scope.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed via fd58298

src/ipc-wrapper/server.js Outdated Show resolved Hide resolved
src/ipc-wrapper/server.js Show resolved Hide resolved
case 'active': {
const { id, message } = value

if (this.#id !== id) return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a huge deal, but maybe better to put this above the switch statement (small edge case - if a subchannel was created and never started, it would accummulate a queue of all messages to all other subchannels).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed via 612f068

test-e2e/ipc-wrapper.js Show resolved Hide resolved
src/ipc-wrapper/client.js Show resolved Hide resolved
src/ipc-wrapper/server.js Outdated Show resolved Hide resolved
@achou11 achou11 deleted the 259/ipc-wrapper branch September 21, 2023 14:14
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.

Implement client wrapper for MapeoManager with IPC communication
2 participants