From 62b1ba50432e35a31b5cffd36d726d9b8b86283b Mon Sep 17 00:00:00 2001 From: Ryan Lubke Date: Mon, 3 Feb 2025 19:43:28 -0800 Subject: [PATCH] - Fix copyrights - Add docs for nameservice feature - Updated docs and error message produced when invalid address string is provided to a session --- .github/workflows/build.yml | 2 +- .github/workflows/discovery.yml | 2 +- README.md | 38 +++++++++++++++++++++++++++------ src/session.ts | 8 +++---- test/session-tests.js | 4 +++- 5 files changed, 40 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 293ccec..52bc3d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -# Copyright 2020, 2023, Oracle Corporation and/or its affiliates. All rights reserved. +# Copyright 2020, 2025, Oracle Corporation and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at # https://oss.oracle.com/licenses/upl. diff --git a/.github/workflows/discovery.yml b/.github/workflows/discovery.yml index 1c16c47..89e1304 100644 --- a/.github/workflows/discovery.yml +++ b/.github/workflows/discovery.yml @@ -1,4 +1,4 @@ -# Copyright 2020, 2023, Oracle Corporation and/or its affiliates. All rights reserved. +# Copyright 2025, Oracle Corporation and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at # https://oss.oracle.com/licenses/upl. diff --git a/README.md b/README.md index 3d59f40..def17b5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ the network transport. * Registration of listeners to be notified of map mutations ### Requirements -* Coherence CE `22.06` or later (or equivalent non-open source editions) with a configured [gRPC Proxy](https://docs.oracle.com/en/middleware/standalone/coherence/14.1.1.2206/develop-remote-clients/using-coherence-grpc-server.html) +* Coherence CE versions `22.06`, `14.1.2-0-0`, `24.09` or later (or equivalent non-open source editions) with a configured [gRPC Proxy](https://docs.oracle.com/en/middleware/standalone/coherence/14.1.1.2206/develop-remote-clients/using-coherence-grpc-server.html) * Node `18.15.x` or later * NPM `9.x` or later @@ -40,7 +40,7 @@ For more details on the image, see the [documentation](https://github.com/oracle ### Declare Your Dependency -To use the Coherence gRPC JavaScript Client, simply declare it as a dependency in your +To use the JavaScript Client for Oracle Coherence, simply declare it as a dependency in your project's `package.json`: ``` ... @@ -52,8 +52,8 @@ project's `package.json`: ### Compatibility with Java Types The following table provides a listing of mappings between Java types and Javascript types when working with -Coherence `23.09` or later. If using Coherence `22.06.x`, these types will be returned as Number. It is recommended -using `23.09` if intentionally using `java.math.BigInteger` or `java.math.BigDecimal` as part of your application. +Coherence `24.09` or later. If using Coherence `22.06.x`, these types will be returned as Number. It is recommended +using `24.09` if intentionally using `java.math.BigInteger` or `java.math.BigDecimal` as part of your application. | Java Type | JavascriptType | |----------------------|------------------------| @@ -68,7 +68,7 @@ using `23.09` if intentionally using `java.math.BigInteger` or `java.math.BigDec #### Establishing a Session The Coherence uses the concept of a `Session` to manage a set of related Coherence resources, -such as maps and/or caches. When using the Coherence JavaScript Client, a `Session` connects to a specific +such as maps and/or caches. When using the JavaScript Client for Oracle Coherence, a `Session` connects to a specific gRPC endpoint and uses a specific serialization format to marshal requests and responses. This means that different sessions using different serializers may connect to the same server endpoint. Typically, for efficiency the client and server would be configured to use matching serialization formats to avoid @@ -76,7 +76,7 @@ deserialization of data on the server, but this does not have to be the case. If serializer for the server-side caches, it must be able to deserialize the client's requests, so there must be a serializer configured on the server to match that used by the client. -> NOTE: Currently, the Coherence JavaScript client only supports JSON serialization +> NOTE: Currently, the JavaScript Client for Oracle Coherence only supports JSON serialization A `Session` is constructed using an `Options` instance, or a generic object with the same keys and values. @@ -126,6 +126,32 @@ const opts = new Options({address: 'example.com:4444'}) let session = new Session(opts) ``` +As of v1.2.3 of the JavaScript Client for Oracle Coherence, it's now possible to use the Coherence +NameService to lookup gRPC Proxy endpoints. The format to enable this feature is +`coherence:([:port]|[:cluster-name]|[:port:cluster-name])` + +For example: + * `coherence:localhost` will connect to the name service bound to a local coherence cluster on port `7574` (the default Coherence cluster port). + * `coherence:localhost:8000` will connect to the name service bound to a local coherence cluster on port `8000`. + * `coherence:localhost:remote-cluster` will connect to the name service bound to a local coherence cluster on port `7574` (the default Coherence cluster port) and look up the name service for the given cluster name. Note: this typically means both clusters have a local member sharing a cluster port. + * `coherence:localhost:8000:remote-cluster` will connect to the name service bound to a local coherence cluster on port `8000` and look up the name service for the given cluster name. Note: this typically means both clusters have a local member sharing a cluster port. + +While this is useful for local development, this may have limited uses in a production environment. For example, +Coherence running within a container with the cluster port (`7574`) exposed so external clients may connect. The +lookup will fail to work for the client as the Coherence name service return a private network address which +won't resolve. Lastly, if connecting to a cluster that has multiple proxies bound to different ports, gRPC, by default, +will use the first address returned by the resolver. It is possible to enable round-robin load balancing by including +a custom channel option when creating the session: + +```typescript +const { Session } = require('@oracle/coherence') + +const opts = new Options({address: 'example.com:4444', + channelOptions: {'grpc.service_config': JSON.stringify({ loadBalancingConfig: [{ round_robin: {} }], })}}) + +let session = new Session(opts) +``` + It's also possible to control the default address the session will bind to by providing an address via the `COHERENCE_SERVER_ADDRESS` environment variable. The format of the value would be the same as if you configured it programmatically as the above example shows. diff --git a/src/session.ts b/src/session.ts index 3aee15e..278f891 100644 --- a/src/session.ts +++ b/src/session.ts @@ -110,7 +110,8 @@ export class Options { * `coherence:[host]:[port]`. * * @param address the IPv4 host address and port in the format of `[host]:[port]` - * or the Coherence name service format of `coherence:[host]:[port]` + * or the Coherence name service format of + * `coherence:([:port]|[:cluster-name]|[:port:cluster-name])` */ set address (address: string) { if (this.locked) { @@ -118,7 +119,7 @@ export class Options { } // ensure address is sane if (!Options.ADDRESS_REGEXP.test(address)) { - throw new Error('Expected address format is \':\' || \'coherence::\'. Configured: ' + address) + throw new Error('Expected address format is \':\' or \'coherence:([:port]|[:cluster-name]|[:port:cluster-name])\'. Configured: ' + address) } this._address = address @@ -918,7 +919,6 @@ export class CoherenceResolver implements experimental.Resolver { private readonly target: experimental.GrpcUri private readonly listener: experimental.ResolverListener - private lastResolve?: Endpoint[] constructor ( target: experimental.GrpcUri, @@ -1003,10 +1003,8 @@ export class CoherenceResolver implements experimental.Resolver { let socket: net.Socket = this.createSocket(state) socket.connect(port, host) state.waitResolve.then(() => { - setTimeout(() => { this.lastResolve = undefined }, 5000) let ep: Endpoint[] = this.parseLookupResult(state) if (ep.length > 0) { - this.lastResolve = ep this.listener.onSuccessfulResolution(ep, null, null, null, {}) } else { this.listener.onError({ diff --git a/test/session-tests.js b/test/session-tests.js index ec1d6db..f7579ff 100644 --- a/test/session-tests.js +++ b/test/session-tests.js @@ -96,7 +96,9 @@ describe('Session Tests Suite (unit/IT)', () => { }) it('should have active sessions after getCache() is called', async () => { - const sess = new Session() + const sess = new Session({ + address: 'example.com:4444', + channelOptions: {'grpc.service_config': JSON.stringify({ loadBalancingConfig: [{ round_robin: {} }], })}}) sess.getCache('sess-cache') assert.equal(sess.activeCacheCount, 1)