tinkerpop icon indicating copy to clipboard operation
tinkerpop copied to clipboard

feat: `gremlin-javascript` browser support

Open tien opened this issue 1 year ago • 9 comments

  • Replace node APIs that have cross runtime equivalent
  • For those that can't be replaced, use node: prefix so that environment that does polyfill automatically can easily do so
  • Remove manual ping/pong logic, this is already handled internally by browser or ws library + WhatWG WebSocket API doesn't have ability to do manual ping/pong

tien avatar Feb 26 '24 04:02 tien

Hey guys, would love to get this working in an environment outside of Node.js.

I think this would boost adoption greatly, as a lot of serverless runtimes (i.e. Cloudflare Worker, Vercel, etc) now utilise standard Web APIs.

This is just something I draft quickly together with the limited knowledge that I have. Would appreciate any helps & guidances. 🙏

tien avatar Feb 26 '24 04:02 tien

Thanks for you interest in contributing. There has been a lot of interest around adding this support in the past. This is the open Jira issue for reference https://issues.apache.org/jira/browse/TINKERPOP-2143. The past attempts seem to have run into some issues with tests https://github.com/apache/tinkerpop/pull/1070 and https://github.com/apache/tinkerpop/pull/1291. I'm not familiar with JavaScript so I'll try to have someone that is look into this.

Thanks again.

kenhuuu avatar Feb 26 '24 17:02 kenhuuu

@kenhuuu thanks for getting back & reminding me about the integration test, I was able to run it locally and have all tests passed. For actually running in a browser API compatible environment, I've tested this on my application running on Cloudflare Worker & everything so far works as expected.

tien avatar Feb 26 '24 21:02 tien

Have also just tested & fix bugs when running this in an actual browser. Everything seems okay so far.

tien avatar Feb 27 '24 01:02 tien

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 76.49%. Comparing base (9b46b67) to head (7c1d5ec). Report is 35 commits behind head on 3.7-dev.

Additional details and impacted files
@@              Coverage Diff              @@
##             3.7-dev    #2506      +/-   ##
=============================================
+ Coverage      76.14%   76.49%   +0.35%     
- Complexity     13152    13170      +18     
=============================================
  Files           1084     1059      -25     
  Lines          65160    61270    -3890     
  Branches        7285     7295      +10     
=============================================
- Hits           49616    46869    -2747     
+ Misses         12839    11888     -951     
+ Partials        2705     2513     -192     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov-commenter avatar Feb 27 '24 08:02 codecov-commenter

Forgot that globalThis.crypto is not available on Node 18, only 19+ (hence the failing test on CI), so I have made a change to use uuid instead.

But optionally we can change the supported node version to LTS, which is 20 right now if you guys think that is best.

tien avatar Feb 27 '24 09:02 tien

Hmm, looks like the .nvmrc file was picked up by the license checker. .nvmrc files can't contain comment, so I have added it to the list of ignored files.

tien avatar Feb 27 '24 19:02 tien

But optionally we can change the supported node version to LTS, which is 20 right now if you guys think that is best.

It's against our current runtime policy (https://tinkerpop.apache.org/docs/current/dev/developer/#runtimes) to upgrade unless the supported runtime has reached end of life. If you feel that it would really be worth it to upgrade to Node 20 then it's a conversation you could start on the dev-list.

Hmm, looks like the .nvmrc file was picked up by the license checker. .nvmrc files can't contain comment, so I have added it to the list of ignored files.

I think that makes sense to ignore it then.

kenhuuu avatar Feb 27 '24 21:02 kenhuuu

@kenhuuu Regarding the Node version, whatever make sense to you guys, of course. It's not a major deal.

But I think the wording in the link that you shared could be a bit better:

Each programming language has a runtime that TinkerPop supports. In general, TinkerPop will attempt to support the current LTS version for a particular major version for the lifetime of its minor and patch releases.

It's not clear whether that mean supporting the current LTS version, which is 20. Or supporting previous version that hasn't reached end of life yet, which is 18.

tien avatar Feb 27 '24 21:02 tien

I've reviewed through the code and it looks great overall. Nice work @tien.

I called out a few areas of potential concern that could use some attention.

It would also be nice to have some automated tests that execute within the context of a browser to ensure we don't regress in the future. Perhaps Playwright can help with this. This is likely to be a large task, so we might want to do it as a separate set of work.

kmcginnes avatar Feb 29 '24 00:02 kmcginnes

@kmcginnes Thanks for taking a look at this, regarding testing in a browser env, yes that would potentially be a much bigger change than this PR 😅, so I think it's best done as a separate task.

tien avatar Feb 29 '24 00:02 tien

You are targetting this PR against the master branch which is currently for the next major release (4.0). The way our branching system works is that you target the lowest version that you want the change to go into. Then when your PR gets merged, the committer will merge your changes all the way up to the latest master branch. It's a bit difficult to explain so I'll use an example. If you want your changes to go into the next 3.6.x, 3.7.x and 4.x release, then you would target the 3.6-dev branch and it will get merged up for you. If you target master then it will only go into the next 4.x release.

I say this because I believe that currently there is no timeline for releasing 4.0 as we are doing releases for 3.6.x and 3.7.x. So if you were to target master then you may need to wait for a while for this change to get released. However, because its currently targetting an unreleased branch, you are technically allowed to upgrade the Node version and ES version.

So, do you prefer to wait for this change to arrive in 4.x? In which case, you can make Node and ES version changes. Or, if you want it released sooner then you will probably have to undo your changes to ESLint and target the 3.7-dev branch as some of those changes could be considered breaking.

kenhuuu avatar Mar 01 '24 00:03 kenhuuu

@kenhuuu Node 18 is compatible with all ES2022 features, so the changes to ESLint should be good.

Regarding the Node version, I'm okay with keeping it 18 now. Since it would be beneficial for me if this is available before 4.0.

I'm integrating gremlin with some of the things at my work & it's easier to justify installing a dependency from an official source, rather than my fork :))

UPDATE: I've updated the target branch to 3.7-dev

tien avatar Mar 01 '24 01:03 tien

Is there way to simply test these changes in different browsers?

@tien maybe you have a simple application that can be put into examples and run to check the basic functionality of the driver? This can also be used as an example for users

vkagamlyk avatar Mar 01 '24 01:03 vkagamlyk

@vkagamlyk the proper way would be to actually run the unit tests in the browser, like @kmcginnes mentioned.

But that could potentially be a huge change to the current test suite.

Another way would be to inject a browser WebSocket polyfill into the current test suite using jsdom. It's not perfect but would require a lot less changes.

tien avatar Mar 01 '24 01:03 tien

@vkagamlyk also, because the API signature is the exact same, those existing examples can be run just fine in a browser environment.

tien avatar Mar 01 '24 04:03 tien

@vkagamlyk or are you suggesting I should create like a simple html page that simply run all the stuffs under examples?

tien avatar Mar 01 '24 06:03 tien

@vkagamlyk or are you suggesting I should create like a simple html page that simply run all the stuffs under examples?

I thought about something more simple, like html page which runs single query like g.V().group().by(label).by(count()) and show results. This will be useful for those who want to use Gremlin from the browser, and it will allow developers to relatively easily check the functionality of the driver after changes.

vkagamlyk avatar Mar 01 '24 06:03 vkagamlyk

Okay I'll add a simple webpage. There's some flaky test that is failing randomly on GitHub Action it seems btw.

tien avatar Mar 01 '24 08:03 tien

@vkagamlyk have added a simple webpage that just display your graph running on localhost on the screen.

tien avatar Mar 02 '24 05:03 tien

Modified the README a bit to say this is also compatible with Web APIs compatible runtimes (browsers, WinterCG runtimes, etc)

tien avatar Mar 03 '24 01:03 tien

@tien I got an error index.js:22 Uncaught SyntaxError: The requested module '/@fs/C:/_Projects/tinkerpop-tien/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js' does not provide an export named 'default' (at index.js:22:8) in Chrome.

vkagamlyk avatar Mar 04 '24 17:03 vkagamlyk

@tien I got an error index.js:22 Uncaught SyntaxError: The requested module '/@fs/C:/_Projects/tinkerpop-tien/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js' does not provide an export named 'default' (at index.js:22:8) in Chrome.

Is this from running the example? To run the example, you need to do this at tinkerpop/gremlin-javascript/examples/browser:

yarn
yarn dev

tien avatar Mar 04 '24 18:03 tien

@tien I got an error index.js:22 Uncaught SyntaxError: The requested module '/@fs/C:/_Projects/tinkerpop-tien/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js' does not provide an export named 'default' (at index.js:22:8) in Chrome.

Is this from running the example? To run the example, you need to do this at tinkerpop/gremlin-javascript/examples/browser:

yarn
yarn dev

ahh, I tried with npm. Looks nice image

vkagamlyk avatar Mar 04 '24 19:03 vkagamlyk

VOTE +1

vkagamlyk avatar Mar 04 '24 21:03 vkagamlyk

VOTE +1

Thanks 🙏, just made a small change, updating the browser example package.json description.

tien avatar Mar 04 '24 23:03 tien

@kenhuuu regarding the user agent header used by Gremlin server

This is likely a separate discussion, but User-Agent header might not be the best way to identify client supported GLV version. Since browser environment for example doesn't allow you to set or modify this for web socket connection.

What might be better is using the Sec-WebSocket-Protocol header instead. Which is designed to specify the sub-protocol requested by client & can be set in the browser by doing:

new WebSocket("ws://localhost:8182", "glv3.7");

The sub-protocol can even be registered here if needed :))

tien avatar Mar 05 '24 04:03 tien

@kenhuuu regarding the user agent header used by Gremlin server

This is likely a separate discussion, but User-Agent header might not be the best way to identify client supported GLV version. Since browser environment for example doesn't allow you to set or modify this for web socket connection.

What might be better is using the Sec-WebSocket-Protocol header instead. Which is designed to specify the sub-protocol requested by client & can be set in the browser by doing:

new WebSocket("ws://localhost:8182", "glv3.7");

The sub-protocol can even be registered here if needed :))

Thanks for the information. As I mentioned above, we'll be moving to HTTP only in 4.x so its probably best to keep the 3.x WebSocket behavior the same for now.

kenhuuu avatar Mar 05 '24 05:03 kenhuuu

VOTE +1. Thanks again for your willingness to contribute. It is much appreciated.

I'm not sure if you are familiar with our policy but it takes a VOTE+1 from three different committers to allow a PR to get merged immediately. Otherwise, if you get at least one of them (you have two right now), then the PR can be merged one week after the first VOTE +1. So at the latest this PR will be eligible for merging on Monday of next week.

kenhuuu avatar Mar 05 '24 05:03 kenhuuu

@kenhuuu thanks for this. I'll try to find another VOTE +1 if possible. Would be beneficial for me to get this in early because there's a work project I'm on that's currently using this.

tien avatar Mar 05 '24 05:03 tien