Skip to content

Commit

Permalink
Merge pull request #265 from DavidVujic/container-nodes-pr-from-dreusel
Browse files Browse the repository at this point in the history
Add support for Container and TTL nodes
  • Loading branch information
DavidVujic committed Jan 31, 2021
2 parents 9be8293 + 977bdd9 commit f750d93
Show file tree
Hide file tree
Showing 19 changed files with 116 additions and 37 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#### v 4.8.0 (2021-01-31)
* feat: add support for TTL and Container nodes. Pull request [255](https://github.com/yfinkelstein/node-zookeeper/pull/255) by @dreusel
* fix: Example code: use one client, use only when connected Pull request [264](https://github.com/yfinkelstein/node-zookeeper/pull/264) by @davidvujic

#### v 4.7.1 (2020-12-27)
* fix: build an AddOn from the ZooKeeper C Client v3.5.8 in all platforms (Linux, Mac OS X and Windows). Pull request [260](https://github.com/yfinkelstein/node-zookeeper/pull/260) by @davidvujic

Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ And you're done!
(note the name `zookeeper` in lowercase)

#### News
:rocket: __New since version 4.8.0__ Support for the new node types introduced in Apache ZooKeeper server v3.5.5: `Container` and `TTL` :rocket:

:tada: __New since version 4.7.0__ :tada: The install process is faster than ever. If you are a Mac OS X or Windows user, there is no longer a need to build an AddOn during the install process.
Everything is already included in the package. Linux user? Don't worry, the installer will quickly build a `Native Node.js AddOn` for the Linux flavor you are running.


#### Next release (work in progress)
:rocket: Adding support for the new node types introduced in Apache ZooKeeper server v3.5.5: `Container` and `TTL` :rocket:

## Examples

```javascript
Expand Down Expand Up @@ -97,7 +95,8 @@ Have a look at the code in the [examples](./examples) folder: with __master__, _
* `init(options)`
* `connect(options, connect_cb)`
* `close()`
* `path = await create(path, data, flags)`
* `path = await create(path, data, flags, ttl)`
* `ttl` is optional. Must be positive if a TTL flag is used. See [Input parameters](#input-parameters)
* `mkdirp(path, callback(Error))`
* `stat = await exists(path, watch)`
* rejects if node does not exist
Expand Down Expand Up @@ -132,6 +131,7 @@ Have a look at the code in the [examples](./examples) folder: with __master__, _
* `connect(options, connect_cb)`
* `close()`
* `a_create(path, data, flags, path_cb)`
* `a_createTtl(path, data, flags, ttl, pathCb)`
* `mkdirp(path, callback(Error))`
* `a_exists(path, watch, stat_cb)`
* `a_get(path, watch, data_cb)`
Expand Down Expand Up @@ -171,9 +171,17 @@ Have a look at the code in the [examples](./examples) folder: with __master__, _
* options : object. valid keys: { connect, timeout, debug_level, host_order_deterministic, data_as_buffer}
* path : string
* data : string or Buffer
* flags : int32
* version : int32
* flags : int32. Supported:
- `ZOO_PERSISTENT`
- `ZOO_EPHEMERAL`
- `ZOO_PERSISTENT_SEQUENTIAL`
- `ZOO_EPHEMERAL_SEQUENTIAL`
- `ZOO_CONTAINER`
- `ZOO_PERSISTENT_WITH_TTL`
- `ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL`
* version : int32. `null` or `undefined` will skip version checking.
* watch : boolean
* ttl: int32. TTL in milliseconds. Must be positive if any of the TTL modes is used; otherwise `undefined`.
* scheme : authorisation scheme (digest, auth)
* auth : authorisation credentials (username:password)
* acl : acls list (same as output parameter, look below) - read only
Expand Down
4 changes: 2 additions & 2 deletions examples/addtask.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const { constants } = require('./wrapper.js');
const notifier = require('./notifier.js');
const { createNode, persistentNode } = require('./createnode.js');
const { createNode } = require('./createnode.js');

async function createTask(client, data) {
// eslint-disable-next-line no-bitwise
const message = await createNode(client, '/tasks/task-', persistentNode | constants.ZOO_SEQUENCE, data);
const message = await createNode(client, '/tasks/task-', constants.ZOO_PERSISTENT | constants.ZOO_PERSISTENT_SEQUENTIAL, data);
notifier.emit('addTask', message);
}

Expand Down
8 changes: 3 additions & 5 deletions examples/createnode.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
const { isClientConnected } = require('./wrapper.js');

const persistentNode = 0;

/**
* @param client {ZooKeeperPromise}
* @param path {string}
* @param flags {number}
* @param data {string|Buffer}
* @returns {Promise}
*/
async function createNode(client, path, flags, data = '') {
async function createNode(client, path, flags, ttl, data = '') {
try {
if (!isClientConnected()) {
throw new Error('createNode: client is not connected');
}

const createdPath = await client.create(path, data, flags);
const createdPath = await client.create(path, data, flags, ttl);

return `(created: ${createdPath})`;
} catch (error) {
return `${path} Error: ${error.message}`;
Expand All @@ -24,5 +23,4 @@ async function createNode(client, path, flags, data = '') {

module.exports = {
createNode,
persistentNode,
};
5 changes: 3 additions & 2 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { getClient } = require('./wrapper.js');
const { getClient, constants } = require('./wrapper.js');
const { createNodes } = require('./setup.js');
const { electLeader } = require('./electleader.js');
const { createWorker } = require('./createworker.js');
Expand All @@ -22,7 +22,8 @@ async function init() {
const client = getClient();

client.on('connect', async () => {
await createNodes(client, ['/workers', '/assign', '/tasks', '/status']);
await createNodes(client, ['/workers', '/assign', '/tasks', '/status'], constants.ZOO_CONTAINER);
await createNodes(client, ['/myttl'], constants.ZOO_PERSISTENT_WITH_TTL, 5000);

notifier.on('leader', async () => {
await listen(client, '/workers');
Expand Down
10 changes: 5 additions & 5 deletions examples/setup.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const notifier = require('./notifier.js');
const { createNode, persistentNode } = require('./createnode.js');
const { createNode } = require('./createnode.js');

async function createAllNodes(client, paths) {
async function createAllNodes(client, paths, flags, ttl) {
const promises = [];
paths.forEach((path) => {
promises.push(createNode(client, path, persistentNode));
promises.push(createNode(client, path, flags, ttl));
});

const messages = await Promise.all(promises);
Expand All @@ -13,8 +13,8 @@ async function createAllNodes(client, paths) {
});
}

async function createNodes(client, paths) {
createAllNodes(client, paths);
async function createNodes(client, paths, flags, ttl = undefined) {
createAllNodes(client, paths, flags, ttl);
}

module.exports = {
Expand Down
18 changes: 18 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,30 @@ module.exports.ZOO_LOG_LEVEL_INFO = NativeZk.ZOO_LOG_LEVEL_INFO;
/** @type {number} 4 */
module.exports.ZOO_LOG_LEVEL_DEBUG = NativeZk.ZOO_LOG_LEVEL_DEBUG;

/** @type {number} 0 */
module.exports.ZOO_PERSISTENT = NativeZk.ZOO_PERSISTENT;

/** @type {number} 1 */
module.exports.ZOO_EPHEMERAL = NativeZk.ZOO_EPHEMERAL;

/** @type {number} 2 */
module.exports.ZOO_SEQUENCE = NativeZk.ZOO_SEQUENCE;

/** @type {number} 2 */
module.exports.ZOO_PERSISTENT_SEQUENTIAL = NativeZk.ZOO_PERSISTENT_SEQUENTIAL;

/** @type {number} 3 */
module.exports.ZOO_EPHEMERAL_SEQUENTIAL = NativeZk.ZOO_EPHEMERAL_SEQUENTIAL;

/** @type {number} 4 */
module.exports.ZOO_CONTAINER = NativeZk.ZOO_CONTAINER;

/** @type {number} 5 */
module.exports.ZOO_PERSISTENT_WITH_TTL = NativeZk.ZOO_PERSISTENT_WITH_TTL;

/** @type {number} 6 */
module.exports.ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL = NativeZk.ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL;

/** @type {number} 0 */
module.exports.ZOK = NativeZk.ZOK;

Expand Down
18 changes: 17 additions & 1 deletion lib/typedeclarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,15 @@ declare module "zookeeperWithCallbacks" {
* @returns {*}
*/
a_create(path: string, data: string | Buffer, flags: number, pathCb: pathCb): any;
/**
* @param {string} path
* @param {string|Buffer} data
* @param {number} flags - an int32 value
* @param {number} ttl - a positive int32 value
* @param {pathCb} pathCb
* @returns {*}
*/
a_createTtl(path: string, data: string | Buffer, flags: number, ttl: number, pathCb: pathCb): any;
/**
* @param {string} path
* @param {boolean} watch
Expand Down Expand Up @@ -357,8 +366,14 @@ declare module "zookeeperConstants" {
export var ZOO_LOG_LEVEL_WARN: number;
export var ZOO_LOG_LEVEL_INFO: number;
export var ZOO_LOG_LEVEL_DEBUG: number;
export var ZOO_PERSISTENT: number;
export var ZOO_EPHEMERAL: number;
export var ZOO_SEQUENCE: number;
export var ZOO_PERSISTENT_SEQUENTIAL: number;
export var ZOO_EPHEMERAL_SEQUENTIAL: number;
export var ZOO_CONTAINER: number;
export var ZOO_PERSISTENT_WITH_TTL: number;
export var ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL: number;
export var ZOK: number;
export var ZSYSTEMERROR: number;
export var ZRUNTIMEINCONSISTENCY: number;
Expand Down Expand Up @@ -440,10 +455,11 @@ declare module "zookeeper" {
* @param {string} path
* @param {(string|Buffer)} data
* @param {number} flags
* @param {number|undefined} [ttl=undefined] ttl - positive integer, use only with a TTL flag
* @fulfill {string}
* @returns {Promise.<string>}
*/
create(path: string, data: (string | Buffer), flags: number): Promise<string>;
create(path: string, data: (string | Buffer), flags: number, ttl?: number | undefined): Promise<string>;
/**
* @param {string} path
* @param {function} watch
Expand Down
7 changes: 6 additions & 1 deletion lib/zk_promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@ class ZooKeeperPromise extends ZooKeeper {
* @param {string} path
* @param {(string|Buffer)} data
* @param {number} flags
* @param {number|undefined} [ttl=undefined] ttl - positive integer, use only with a TTL flag
* @fulfill {string}
* @returns {Promise.<string>}
*/
create(path, data, flags) {
create(path, data, flags, ttl = undefined) {
if (ttl) {
return this.promisify(super.a_createTtl, [path, data, flags, ttl]);
}

return this.promisify(super.a_create, [path, data, flags]);
}

Expand Down
13 changes: 13 additions & 0 deletions lib/zookeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,19 @@ class ZooKeeper extends EventEmitter {
return this.native.a_create(path, data, flags, pathCb);
}

/**
* @param {string} path
* @param {string|Buffer} data
* @param {number} flags - an int32 value
* @param {number} ttl - a positive int32 value
* @param {pathCb} pathCb
* @returns {*}
*/
a_createTtl(path, data, flags, ttl, pathCb) {
this.log(`Calling a_create_ttl with ${util.inspect([path, data, flags, ttl, pathCb])}`);
return this.native.a_create_ttl(path, data, flags, ttl, pathCb);
}

/**
* @param {string} path
* @param {boolean} watch
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "zookeeper",
"description": "apache zookeeper client (zookeeper async API v3.4.x - v3.6.x)",
"version": "4.7.1",
"version": "4.8.0",
"author": "Yuri Finkelstein <yurif2003@yahoo.com>",
"license": "MIT",
"contributors": [
Expand Down
8 changes: 4 additions & 4 deletions prebuilds/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ Each platform has prebuilds for Node.js 12 and 14.
Create prebuilds for Mac OS X:

```bash
npx prebuildify --arch x64 --platform darwin --target 12.18.4
npx prebuildify --arch x64 --platform darwin --target 14.13.0
npx prebuildify --arch x64 --platform darwin --target 12.20.1
npx prebuildify --arch x64 --platform darwin --target 14.15.4
```

Create prebuilds for Windows 10:

```bash
npx prebuildify --arch x64 --platform win32 --target 12.13.0
Npx prebuildify --arch x64 --platform win32 --target 14.13.0
npx prebuildify --arch x64 --platform win32 --target 12.20.1
Npx prebuildify --arch x64 --platform win32 --target 14.15.4
```
Binary file modified prebuilds/darwin-x64/node.abi72.node
Binary file not shown.
Binary file modified prebuilds/darwin-x64/node.abi83.node
Binary file not shown.
Binary file modified prebuilds/win32-x64/node.abi72.node
Binary file not shown.
Binary file modified prebuilds/win32-x64/node.abi83.node
Binary file not shown.
23 changes: 23 additions & 0 deletions src/node-zk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class ZooKeeper: public Nan::ObjectWrap {
Nan::SetPrototypeMethod(constructor_template, "init", Init);
Nan::SetPrototypeMethod(constructor_template, "close", Close);
Nan::SetPrototypeMethod(constructor_template, "a_create", ACreate);
Nan::SetPrototypeMethod(constructor_template, "a_create_ttl", ACreateTtl);
Nan::SetPrototypeMethod(constructor_template, "a_exists", AExists);
Nan::SetPrototypeMethod(constructor_template, "aw_exists", AWExists);
Nan::SetPrototypeMethod(constructor_template, "a_get", AGet);
Expand Down Expand Up @@ -190,8 +191,14 @@ class ZooKeeper: public Nan::ObjectWrap {
NODE_DEFINE_CONSTANT(constructor, ZOOKEEPER_WRITE);
NODE_DEFINE_CONSTANT(constructor, ZOOKEEPER_READ);

NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT);
NODE_DEFINE_CONSTANT(constructor, ZOO_EPHEMERAL);
NODE_DEFINE_CONSTANT(constructor, ZOO_SEQUENCE);
NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT_SEQUENTIAL);
NODE_DEFINE_CONSTANT(constructor, ZOO_EPHEMERAL_SEQUENTIAL);
NODE_DEFINE_CONSTANT(constructor, ZOO_CONTAINER);
NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT_WITH_TTL);
NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL);

NODE_DEFINE_CONSTANT(constructor, ZOO_CREATED_EVENT);
NODE_DEFINE_CONSTANT(constructor, ZOO_DELETED_EVENT);
Expand Down Expand Up @@ -651,6 +658,22 @@ class ZooKeeper: public Nan::ObjectWrap {
}
}

static void ACreateTtl(const Nan::FunctionCallbackInfo<Value>& info) {
A_METHOD_PROLOG(5);

Nan::Utf8String _path (toString(info[0]));
uint32_t flags = toUint(info[2]);
int32_t ttl = toInt(info[3]);

if (Buffer::HasInstance(info[1])) { // buffer
Local<Object> _data = toLocalObj(info[1]);
METHOD_EPILOG(zoo_acreate_ttl(zk->zhandle, *_path, BufferData(_data), BufferLength(_data), &ZOO_OPEN_ACL_UNSAFE, flags, ttl, string_completion, cb));
} else { // other
Nan::Utf8String _data (toString(info[1]));
METHOD_EPILOG(zoo_acreate_ttl(zk->zhandle, *_path, *_data, _data.length(), &ZOO_OPEN_ACL_UNSAFE, flags, ttl, string_completion, cb));
}
}

static void void_completion (int rc, const void *data) {
struct completion_data *d = (struct completion_data *) data;
void *cb = (void *) d->cb;
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/index/apitest.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ const test = require('tape');
const ZooKeeper = require('../../../lib/index.js');

function assertPublicApi(zk, t) {
t.plan(25);
t.plan(26);

t.equal(typeof zk.a_create, 'function');
t.equal(typeof zk.a_createTtl, 'function');
t.equal(typeof zk.a_exists, 'function');
t.equal(typeof zk.a_get, 'function');
t.equal(typeof zk.a_get_acl, 'function');
Expand Down
8 changes: 0 additions & 8 deletions tests/unit/zookeeper/exportedconstantstest.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ const ZooKeeper = require('../../../lib/zookeeper');

const keys = Object.keys(NativeZk);

test('deprecated native static constants are exported', (t) => {
t.plan(keys.length);

keys.forEach((key) => {
t.equal(ZooKeeper[key], NativeZk[key]);
});
});

test('native static constants are exported', (t) => {
t.plan(keys.length);

Expand Down

0 comments on commit f750d93

Please sign in to comment.