question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[RFC] Node.js v16 Upgrade Plan

See original GitHub issue

Overview

OpenSearch Dashboards is currently running an EOL Node.js version, Node.js v10.24.1. This current version of Node carries with it several high severity security vulnerabilities, as well as forces us to use older version of critical dependencies that carry their own share security vulnerabilities. The intent of the core Dashboards team is to upgrade to Node.js v16.9.1 which goes into LTS support in October 2021. The OpenSearch project is following the SemVer standard for versioning; therefore, the Node.js v16 upgrade is considered a breaking change and will require a version bump of Dashboards to 2.0.0

Scope

The scope of the Node 16 upgrade is to do the minimum amount of dependency, code, and testing changes to allow for the core Dashboards team to address many of the CVEs that are present currently and blocked by our current Node.js version. While there may be many opportunities to make changes or upgrade packages because of the new version of Node, they would be out of scope of the work done to upgrade Dashboards to Node.js v16.

Upgrade Proposal

The Node.js v16 upgrade will take the form of 3 phases that will be cycled through for each new plugin and developer wanting to upgrade. The 3 phases are somewhat coupled which makes working on the phases asynchronously difficult.

Phase 1: Dependency Version Parity

This phase consists primarily of bringing all of Dashboards’ dependencies up to parity with what Node.js v16 expects/requires. Node v16 is many major versions higher than what we were working with before and will require upgrades to several dependencies. These changes will introduce cascading breaking changes to other dependencies, as well as to some code implementations in Dashboards.

Below is a table of dependencies that are required to upgrade to Node.js v16 for core Dashboards:

Dependencies Current Version Upgrade Version Notes Function in Dashboards
lmdb-store 0.6.10 1.6.7 The primary issue introduced by Node.js v16 upgrade is that the sub-dependency msgpackr-extract is not supported by Node 16 and requires lmdb-store to be bumped to latest. lmdb-store is a key-value store library being used by our osd-optimizer package for cluster caching
node-sass v5 6.0.1 node-sass is deprecated and should be changed to dart-sass; however, there was a version of node-sass that was supported by Node.js v16 and that was version 6.0.1. Bumping node-sass rather than swapping out to dart-sass seems to be less work and there are other open questions surrounding the use of dart-sass with regards to EUI. node-sass is the primary library for using Sass. Currently deprecated in favor of dart-sass
sass-loader 8.0.2 10.2.0 Bumping node-sass up to v6.0.1 causes the need to upgrade sass-loader to a newer version that supports both node-sass v6.0.1 and node.js v16.9.1. helper library for all things Sass
@types/webpack-env 1.15.2 1.15.3 This version bump was required because of a bug with Node.js interfacing with webpack. The error was: error TS2430: Interface 'NodeJS.Module' incorrectly extends interface '__WebpackModuleApi.Module Type definitions for typescript that correspond to webpack and are to be used in conjunction with webpack
tslib N/A 2.0.0 The tslib module is explicitly required for Node.js v16 and was not added in our package.json runtime library for typescript that contains all of the typescript helper functions
@types/node >=10.17.17 <10.20.0 16.9.1 It’s required to update to the latest type definition package for node that corresponds to the Node.js major version being used Type definitions for typescript that correspond to Node major versions

The majority of the errors pertaining to dependency version errors and version mismatches will manifest themselves as build errors and package compatibility errors. Some of the errors will manifest as type/code logical errors but those will be handled in the next phase.

Phase 2: Breaking code changes

The next major obstacle is the plethora of breaking code changes introduced both by the new version of Node.js itself and the new versions of other dependencies. This phase requires a good amount of familiarity with breaking changes across major versions of dependencies. The three major types of code changes are listed below:

  1. Syntax strictness with regards to null and undefined behavior
    1. Node.js v16 has become much more strict with the handling of possible null and undefined behaviors.
    2. The majority of these types of errors are fixed by passing the non-null assertion operator if you are sure that the value being passed in code is not going to be null
      1. e.g.
      2. childProcess.stdin!.end(stdin, ‘utf8’); // TypeScript note: As long as the proc stdio[1] is ‘pipe’, then stdin will not be null
      3. Node has an issue with stdin and stderr null possibilities and requires the non-null assertion operator to no longer break the build
  2. Type mismatches and type strictness
    1. There are lambdas throughout the code base that are using variables with no explicit type
    2. Variables being typed as unknown so they break type definitions for certain interfaces
    3. Generally the error messages take the form of Type<unknown> cannot be assigned to Type<type>
    4. There are cases of the type definitions expected by @types/node not matching the actual types
      1. E.g.
      2. urlUtils.encodeQuery expects key/value pairs with values of type string | string[] | null,
        however @types/node says that url.query has values of type string | string[] | undefined.
        After investigating this, it seems that no matter what the values will be of type string | string[]
  3. Feature deprecation and new data interfaces
    1. Webpack config file has deprecated an object property in favor of another in newer versions
      1. webpack-config: prependData changed to additionalData
      2. The additionalData property requires an additional content parameter
    2. The lmdb-store version bump leads to a required rewrite of our cache.ts file in the osd-optimizer package
      1. This is required because in v0.6.10, there was no data interface for the store. This lead to elastic creating their own data interface abstraction
      2. interface Lmdb<T> {
        get(key: string): T | undefined;
        put(key: string, value: T, version?: number, ifVersion?: number): Promise<boolean>;
        remove(key: string, ifVersion?: number): Promise<boolean>;
        openDB<T>(options: { name: string; encoding: ‘msgpack’ | ‘string’ | ‘json’ | ‘binary’ }): Lmdb<T>;
        getRange(options?: {
        start?: T;
        end?: T;
        reverse?: boolean;
        limit?: number;
        versions?: boolean;
        }): Iterable<{ key: string; value: T }>;
        }
      3. In lmdb-store v1.6.7, they have introduced new interfaces that must be used in our caching implementation.
      4. The lmdb-store types are:
        1. LmdbStore.RootDatabase
        2. LmdbStore.Database
      5. A rewrite of some of the member methods of the Cache class is required to satisfy the more strict exception handling requirements of Node

Phase 3: Runtime Errors

Runtime errors tend to be the hardest types of errors to track down in this process and they usually occur either as you attempt to run Dashboards using yarn start or they crop up while Dashboards is running itself.

Node 16 Cluster error:

There seems to be an issue with importing the cluster module in the worker.ts file in core.

 log   [16:54:15.757] [fatal][root] TypeError: _cluster.default.setupPrimary is not a function
When switching the import from import cluster from ‘cluster’ to import * as cluster from ‘cluster’ we get the following error.
Unhandled Promise rejection detected:

TypeError: Cannot read properties of undefined (reading ‘apply’)
at BinderFor.on (/home/ubuntu/OpenSearch-Dashboards/src/cli/cluster/binder.ts:47:8)
at BinderFor.on (/home/ubuntu/OpenSearch-Dashboards/src/cli/cluster/binder_for.ts:41:11)
at Worker.start (/home/ubuntu/OpenSearch-Dashboards/src/cli/cluster/worker.ts:228:24)
at ClusterManager.startCluster (/home/ubuntu/OpenSearch-Dashboards/src/cli/cluster/cluster_manager.ts:181:14)
at FSWatcher.<anonymous> (/home/ubuntu/OpenSearch-Dashboards/src/cli/cluster/cluster_manager.ts:249:12)

API Error:

The following 2 errors occur when starting dashboards with yarn start after upgrading lmdb-store, node-sass, and sass-loader. It stops Dashboards from loading the home app because the capabilities api call never succeeds.
NetworkError when attempting to fetch resource.
Version
: 1.1.0
Build: 9007199254740991
Error: NetworkError when attempting to fetch resource.
HttpFetchError@http://localhost:5603/ime/9007199254740991/bundles/core/core.entry.js:18398:5
fetchResponse@http://localhost:5603/ime/9007199254740991/bundles/core/core.entry.js:18274:13
Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource.
HttpFetchError http_fetch_error.ts:38
fetchResponse fetch.ts:156
osdBootstrap osd_bootstrap.ts:57
AsyncFunctionThrow self-hosted:697
Looks like the above errors pertain to the api/core/capabilities API request
POST http://localhost:5603/azc/api/core/capabilities net::ERR_EMPTY_RESPONSE

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:15 (14 by maintainers)

github_iconTop GitHub Comments

4reactions
stockholmuxcommented, Oct 14, 2021

@AMoo-Miki So, v16 will be Active LTS on 2021-10-26 which will be before the time we follow through on this RFC. If an organization wants to disallow active LTS, that seems like their problem, not ours.

Every time Dashboard’s adopts a new version of Node it’s a new major version (according to SemVer). Every new major can cause heartburn for our users and those who want to develop plugins for Dashboards. The least we can do is give them the longest interval between needing to take TUMS.

3reactions
dblockcommented, Oct 1, 2021

Please make sure to include changes to https://github.com/opensearch-project/opensearch-build when node is upgraded. It likely means building different docker images.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Node v16.15.0 (LTS)
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
Read more >
Node.js v19.3.0 Documentation
Enabling the feature; Configuring a package; Upgrading the global versions; Offline workflow. Supported package managers; Common questions.
Read more >
Node v17.5.0 (Current)
Adds experimental support to the fetch API. This adds a --experimental-fetch flag that installs the fetch , Request , Response and Headers ...
Read more >
The Difference Between Node.js 10 LTS and Node.js 12 LTS
Upgrade npm to v6.5.0 (Jordan Harband) #25234. fs: Use internalBinding('fs') internally instead of process.binding('fs') ...
Read more >
Errors | Node.js v19.3.0 Documentation
mjs:line:column , if the frame represents a call in a user program (using ES module system), or its dependencies. The string representing the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found