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

Service Daemon Application #88

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Service Daemon Application #88

wants to merge 17 commits into from

Conversation

jonah-iden
Copy link
Contributor

This is a small node application, encapsulating the open-collaboration-protocol and yjs libraries and making them available to other non js based environments.
The application communicates through JSON based message on stdout. For the most part it just forwards messages from or to the application/open collaboration protocol library. But for the initial login, room join/create and yjs it has some special messages. A question here is still if they should also use the parameter array patter instead of wrapping the arguments into json data.

There is a test (service.process.test.ts) that shows a little bit how this should be used.
I would love some feedback on this.

@jonah-iden
Copy link
Contributor Author

Current plan for restructuring the message format for custom messages is to move properties to a params array and change the method names to be more method like and more similiar to the format that the oc server uses

Copy link
Contributor

@spoenemann spoenemann left a comment

Choose a reason for hiding this comment

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

Thanks!

We could consider using JSON-RPC between the service process and the host IDE.

About the terminology: if we call it a service daemon, it should run as an independent process to which the IDE can connect, right? If the background process lifecycle is fully controlled by the IDE, strictly speaking it's not a daemon.

const args = parseArgs({options: {
'server-address': {type: 'string'},
'auth-token': {type: 'string'},
}});
Copy link
Contributor

Choose a reason for hiding this comment

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

Shall we use a full CLI library like commander?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think thats neccessary right now. In my opinion we can think about that when we need to add more arguments. Or what benefit would you see in changing this right now?

Copy link
Contributor

Choose a reason for hiding this comment

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

If you introduce it later, it might break the usage; for example, options might be prefixed like --auth-token

@jonah-iden
Copy link
Contributor Author

jonah-iden commented Jan 29, 2025

Regarding jsonRPC I'm thinking about using the same format as OCP already does with wrapper messages containing the json rpc messages like

{
type: 'request'
id: 1
content: {
  method: 'someMethod:
  params: ['someParam']
  }
}

But i would not go full json rpc so that the compatibility with OCP is still given and the user can send arbitrary messages as if communicating with the open collab server directly

Your right i'll change the name.

Copy link
Contributor

@kaisalmen kaisalmen left a comment

Choose a reason for hiding this comment

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

Thank you very much. I left a couple of comments. This is a good starting point to start connecting other languages.

"open-collaboration-protocol": "0.2.0",
"async-mutex": "^0.5.0"
},
"devDependencies": {
Copy link
Contributor

Choose a reason for hiding this comment

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

Because this is a workspace project it makes sense to move devDependencies to the root as they are irrelevant to the individual npm packages. This is true for any other package as well, of course.

"program": "${workspaceFolder}/packages/open-collaboration-service-daemon/lib/process.js",
"args": [
"--server-address=http://localhost:8100",
"--auth-token=eyJhbGciOiJIUzI1NiJ9.eyJpZCI6ImZlYTBySW5BU1phWkVDUE9IcXRsZ0lmNSIsIm5hbWUiOiJUZXN0IiwiZW1haWwiOiIiLCJhdXRoUHJvdmlkZXIiOiJVbnZlcmlmaWVkIiwiaWF0IjoxNzMxMzI3MjQzfQ.glt-hv5QtHYzRp2K2uILsNJjPLWJSrWlRVPMOuG8cQI"
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this token still correct?

protected handlers = new Map<string, (message: unknown) => MaybePromise<void | unknown>>(
[
['login', () => this.login()],
['room/joinRoom', message => this.joinRoom(message as JoinRoomRequest)],
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it make sense to declare those strings as accessible values in the protocol, so they can be referenced in the protocol itself and externally like here? Something like a protocol command index.

host.process?.kill();
guest.process?.kill();
});
test('test service processes without login', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you this is very helpful we could introduce a passive containerized Java client for another test (not in the scope of this PR) that answers what a test expects.

userToken: args.values['auth-token']
});

new MessageHandler(connectionProvider, communicationHandler);
Copy link
Contributor

Choose a reason for hiding this comment

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

A general idea. Should we have command messages that allow to change behaviour of the process via stdin/out that allows a client like an idea to change the runtime behaviour or trigger a re-connect to another oct server.

Copy link
Contributor

@msujew msujew left a comment

Choose a reason for hiding this comment

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

As an additional test case for the API: Can we migrate the existing VS Code client to the API exposed by the open-collaboration-service-daemon?

Comment on lines +25 to +27
onUnhandledRequest(handler: UnhandledMessageHandler): void;
onUnhandledNotification(handler: UnhandledMessageHandler): void;
onUnhandledBroadcast(handler: UnhandledMessageHandler): void;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: Instead of having onUnhandled*, we could provide an override for onBroadcast, etc that simply accepts a handler that acts as the generic handler in case no specific handler has been found. The vscode-languageserver library uses a very similar API.

Comment on lines +1 to +3
const execSync = require('child_process').execSync;
const fs = require('fs');
const inject = require('postject').inject
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: Can we make this into a .mjs file? Then we can use import instead of require. Alternatively, make this into an .ts file and execute it with tsx.

Comment on lines +12 to +13
const authTokenHost: string = 'eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IkF2S2JlczliU1hDZ0FxSHhwa0xqYVRBcyIsIm5hbWUiOiJob3N0IiwiZW1haWwiOiIiLCJhdXRoUHJvdmlkZXIiOiJVbnZlcmlmaWVkIiwiaWF0IjoxNzM4MjQxNTcwfQ.IWetdyBTAo2DswcYKs5Jzxl3AzuKGccFnGsc5A9XE8s';
const authTokenGuest: string = 'eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IlBrQmN4blBJc1Qzenl5YVlLUEpGWXRxViIsIm5hbWUiOiJndWVzdCIsImVtYWlsIjoiIiwiYXV0aFByb3ZpZGVyIjoiVW52ZXJpZmllZCIsImlhdCI6MTczODI0MTY0Nn0.ABHj54q5u_z1Cd57Mscryp4rMPPiwxLLfSl-anCtD1E';
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: Can we not hardcode the tokens into the test? :D It shouldn't be too difficult to go through the unverified/anonymous login process.

@jonah-iden
Copy link
Contributor Author

@msujew regarding migrating the vscode client, I would keep typescript/js integrations using the library since that brings typesafety with it which the service process does not have. The service process just wraps the libraries so there is not alot to gain here by migrating.

@msujew
Copy link
Contributor

msujew commented Feb 21, 2025

@jonah-iden What I mean is that I would like to abstract away the yjs integration. I feel like I've duplicated a lot of yjs related code between the Theia and VS Code integration and the daemon process is also duplicating a lot of code. Having one source that abstracts away the yjs integration logic would we great :)

@jonah-iden
Copy link
Contributor Author

jonah-iden commented Feb 21, 2025

@msujew ok i see. That makes sense. But maybe there should rather be some helper class in the yjs library instead that can be used by all js integration without the service process. Then the monaco integration could benefit from it as well

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.

4 participants