Skip to content

Commit f750d93

Browse files
authored
Merge pull request #265 from DavidVujic/container-nodes-pr-from-dreusel
Add support for Container and TTL nodes
2 parents 9be8293 + 977bdd9 commit f750d93

19 files changed

+116
-37
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#### v 4.8.0 (2021-01-31)
2+
* feat: add support for TTL and Container nodes. Pull request [255](https://github.com/yfinkelstein/node-zookeeper/pull/255) by @dreusel
3+
* fix: Example code: use one client, use only when connected Pull request [264](https://github.com/yfinkelstein/node-zookeeper/pull/264) by @davidvujic
4+
15
#### v 4.7.1 (2020-12-27)
26
* 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
37

README.md

+15-7
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@ And you're done!
1919
(note the name `zookeeper` in lowercase)
2020

2121
#### News
22+
: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:
23+
2224
: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.
2325
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.
2426

25-
26-
#### Next release (work in progress)
27-
:rocket: Adding support for the new node types introduced in Apache ZooKeeper server v3.5.5: `Container` and `TTL` :rocket:
28-
2927
## Examples
3028

3129
```javascript
@@ -97,7 +95,8 @@ Have a look at the code in the [examples](./examples) folder: with __master__, _
9795
* `init(options)`
9896
* `connect(options, connect_cb)`
9997
* `close()`
100-
* `path = await create(path, data, flags)`
98+
* `path = await create(path, data, flags, ttl)`
99+
* `ttl` is optional. Must be positive if a TTL flag is used. See [Input parameters](#input-parameters)
101100
* `mkdirp(path, callback(Error))`
102101
* `stat = await exists(path, watch)`
103102
* rejects if node does not exist
@@ -132,6 +131,7 @@ Have a look at the code in the [examples](./examples) folder: with __master__, _
132131
* `connect(options, connect_cb)`
133132
* `close()`
134133
* `a_create(path, data, flags, path_cb)`
134+
* `a_createTtl(path, data, flags, ttl, pathCb)`
135135
* `mkdirp(path, callback(Error))`
136136
* `a_exists(path, watch, stat_cb)`
137137
* `a_get(path, watch, data_cb)`
@@ -171,9 +171,17 @@ Have a look at the code in the [examples](./examples) folder: with __master__, _
171171
* options : object. valid keys: { connect, timeout, debug_level, host_order_deterministic, data_as_buffer}
172172
* path : string
173173
* data : string or Buffer
174-
* flags : int32
175-
* version : int32
174+
* flags : int32. Supported:
175+
- `ZOO_PERSISTENT`
176+
- `ZOO_EPHEMERAL`
177+
- `ZOO_PERSISTENT_SEQUENTIAL`
178+
- `ZOO_EPHEMERAL_SEQUENTIAL`
179+
- `ZOO_CONTAINER`
180+
- `ZOO_PERSISTENT_WITH_TTL`
181+
- `ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL`
182+
* version : int32. `null` or `undefined` will skip version checking.
176183
* watch : boolean
184+
* ttl: int32. TTL in milliseconds. Must be positive if any of the TTL modes is used; otherwise `undefined`.
177185
* scheme : authorisation scheme (digest, auth)
178186
* auth : authorisation credentials (username:password)
179187
* acl : acls list (same as output parameter, look below) - read only

examples/addtask.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
const { constants } = require('./wrapper.js');
22
const notifier = require('./notifier.js');
3-
const { createNode, persistentNode } = require('./createnode.js');
3+
const { createNode } = require('./createnode.js');
44

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

examples/createnode.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
const { isClientConnected } = require('./wrapper.js');
22

3-
const persistentNode = 0;
4-
53
/**
64
* @param client {ZooKeeperPromise}
75
* @param path {string}
86
* @param flags {number}
97
* @param data {string|Buffer}
108
* @returns {Promise}
119
*/
12-
async function createNode(client, path, flags, data = '') {
10+
async function createNode(client, path, flags, ttl, data = '') {
1311
try {
1412
if (!isClientConnected()) {
1513
throw new Error('createNode: client is not connected');
1614
}
1715

18-
const createdPath = await client.create(path, data, flags);
16+
const createdPath = await client.create(path, data, flags, ttl);
17+
1918
return `(created: ${createdPath})`;
2019
} catch (error) {
2120
return `${path} Error: ${error.message}`;
@@ -24,5 +23,4 @@ async function createNode(client, path, flags, data = '') {
2423

2524
module.exports = {
2625
createNode,
27-
persistentNode,
2826
};

examples/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { getClient } = require('./wrapper.js');
1+
const { getClient, constants } = require('./wrapper.js');
22
const { createNodes } = require('./setup.js');
33
const { electLeader } = require('./electleader.js');
44
const { createWorker } = require('./createworker.js');
@@ -22,7 +22,8 @@ async function init() {
2222
const client = getClient();
2323

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

2728
notifier.on('leader', async () => {
2829
await listen(client, '/workers');

examples/setup.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
const notifier = require('./notifier.js');
2-
const { createNode, persistentNode } = require('./createnode.js');
2+
const { createNode } = require('./createnode.js');
33

4-
async function createAllNodes(client, paths) {
4+
async function createAllNodes(client, paths, flags, ttl) {
55
const promises = [];
66
paths.forEach((path) => {
7-
promises.push(createNode(client, path, persistentNode));
7+
promises.push(createNode(client, path, flags, ttl));
88
});
99

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

16-
async function createNodes(client, paths) {
17-
createAllNodes(client, paths);
16+
async function createNodes(client, paths, flags, ttl = undefined) {
17+
createAllNodes(client, paths, flags, ttl);
1818
}
1919

2020
module.exports = {

lib/constants.js

+18
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,30 @@ module.exports.ZOO_LOG_LEVEL_INFO = NativeZk.ZOO_LOG_LEVEL_INFO;
4646
/** @type {number} 4 */
4747
module.exports.ZOO_LOG_LEVEL_DEBUG = NativeZk.ZOO_LOG_LEVEL_DEBUG;
4848

49+
/** @type {number} 0 */
50+
module.exports.ZOO_PERSISTENT = NativeZk.ZOO_PERSISTENT;
51+
4952
/** @type {number} 1 */
5053
module.exports.ZOO_EPHEMERAL = NativeZk.ZOO_EPHEMERAL;
5154

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

58+
/** @type {number} 2 */
59+
module.exports.ZOO_PERSISTENT_SEQUENTIAL = NativeZk.ZOO_PERSISTENT_SEQUENTIAL;
60+
61+
/** @type {number} 3 */
62+
module.exports.ZOO_EPHEMERAL_SEQUENTIAL = NativeZk.ZOO_EPHEMERAL_SEQUENTIAL;
63+
64+
/** @type {number} 4 */
65+
module.exports.ZOO_CONTAINER = NativeZk.ZOO_CONTAINER;
66+
67+
/** @type {number} 5 */
68+
module.exports.ZOO_PERSISTENT_WITH_TTL = NativeZk.ZOO_PERSISTENT_WITH_TTL;
69+
70+
/** @type {number} 6 */
71+
module.exports.ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL = NativeZk.ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL;
72+
5573
/** @type {number} 0 */
5674
module.exports.ZOK = NativeZk.ZOK;
5775

lib/typedeclarations.d.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,15 @@ declare module "zookeeperWithCallbacks" {
219219
* @returns {*}
220220
*/
221221
a_create(path: string, data: string | Buffer, flags: number, pathCb: pathCb): any;
222+
/**
223+
* @param {string} path
224+
* @param {string|Buffer} data
225+
* @param {number} flags - an int32 value
226+
* @param {number} ttl - a positive int32 value
227+
* @param {pathCb} pathCb
228+
* @returns {*}
229+
*/
230+
a_createTtl(path: string, data: string | Buffer, flags: number, ttl: number, pathCb: pathCb): any;
222231
/**
223232
* @param {string} path
224233
* @param {boolean} watch
@@ -357,8 +366,14 @@ declare module "zookeeperConstants" {
357366
export var ZOO_LOG_LEVEL_WARN: number;
358367
export var ZOO_LOG_LEVEL_INFO: number;
359368
export var ZOO_LOG_LEVEL_DEBUG: number;
369+
export var ZOO_PERSISTENT: number;
360370
export var ZOO_EPHEMERAL: number;
361371
export var ZOO_SEQUENCE: number;
372+
export var ZOO_PERSISTENT_SEQUENTIAL: number;
373+
export var ZOO_EPHEMERAL_SEQUENTIAL: number;
374+
export var ZOO_CONTAINER: number;
375+
export var ZOO_PERSISTENT_WITH_TTL: number;
376+
export var ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL: number;
362377
export var ZOK: number;
363378
export var ZSYSTEMERROR: number;
364379
export var ZRUNTIMEINCONSISTENCY: number;
@@ -440,10 +455,11 @@ declare module "zookeeper" {
440455
* @param {string} path
441456
* @param {(string|Buffer)} data
442457
* @param {number} flags
458+
* @param {number|undefined} [ttl=undefined] ttl - positive integer, use only with a TTL flag
443459
* @fulfill {string}
444460
* @returns {Promise.<string>}
445461
*/
446-
create(path: string, data: (string | Buffer), flags: number): Promise<string>;
462+
create(path: string, data: (string | Buffer), flags: number, ttl?: number | undefined): Promise<string>;
447463
/**
448464
* @param {string} path
449465
* @param {function} watch

lib/zk_promise.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,15 @@ class ZooKeeperPromise extends ZooKeeper {
2424
* @param {string} path
2525
* @param {(string|Buffer)} data
2626
* @param {number} flags
27+
* @param {number|undefined} [ttl=undefined] ttl - positive integer, use only with a TTL flag
2728
* @fulfill {string}
2829
* @returns {Promise.<string>}
2930
*/
30-
create(path, data, flags) {
31+
create(path, data, flags, ttl = undefined) {
32+
if (ttl) {
33+
return this.promisify(super.a_createTtl, [path, data, flags, ttl]);
34+
}
35+
3136
return this.promisify(super.a_create, [path, data, flags]);
3237
}
3338

lib/zookeeper.js

+13
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,19 @@ class ZooKeeper extends EventEmitter {
179179
return this.native.a_create(path, data, flags, pathCb);
180180
}
181181

182+
/**
183+
* @param {string} path
184+
* @param {string|Buffer} data
185+
* @param {number} flags - an int32 value
186+
* @param {number} ttl - a positive int32 value
187+
* @param {pathCb} pathCb
188+
* @returns {*}
189+
*/
190+
a_createTtl(path, data, flags, ttl, pathCb) {
191+
this.log(`Calling a_create_ttl with ${util.inspect([path, data, flags, ttl, pathCb])}`);
192+
return this.native.a_create_ttl(path, data, flags, ttl, pathCb);
193+
}
194+
182195
/**
183196
* @param {string} path
184197
* @param {boolean} watch

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "zookeeper",
33
"description": "apache zookeeper client (zookeeper async API v3.4.x - v3.6.x)",
4-
"version": "4.7.1",
4+
"version": "4.8.0",
55
"author": "Yuri Finkelstein <[email protected]>",
66
"license": "MIT",
77
"contributors": [

prebuilds/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ Each platform has prebuilds for Node.js 12 and 14.
88
Create prebuilds for Mac OS X:
99

1010
```bash
11-
npx prebuildify --arch x64 --platform darwin --target 12.18.4
12-
npx prebuildify --arch x64 --platform darwin --target 14.13.0
11+
npx prebuildify --arch x64 --platform darwin --target 12.20.1
12+
npx prebuildify --arch x64 --platform darwin --target 14.15.4
1313
```
1414

1515
Create prebuilds for Windows 10:
1616

1717
```bash
18-
npx prebuildify --arch x64 --platform win32 --target 12.13.0
19-
Npx prebuildify --arch x64 --platform win32 --target 14.13.0
18+
npx prebuildify --arch x64 --platform win32 --target 12.20.1
19+
Npx prebuildify --arch x64 --platform win32 --target 14.15.4
2020
```

prebuilds/darwin-x64/node.abi72.node

1.15 KB
Binary file not shown.

prebuilds/darwin-x64/node.abi83.node

1.15 KB
Binary file not shown.

prebuilds/win32-x64/node.abi72.node

2.5 KB
Binary file not shown.

prebuilds/win32-x64/node.abi83.node

2.5 KB
Binary file not shown.

src/node-zk.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class ZooKeeper: public Nan::ObjectWrap {
126126
Nan::SetPrototypeMethod(constructor_template, "init", Init);
127127
Nan::SetPrototypeMethod(constructor_template, "close", Close);
128128
Nan::SetPrototypeMethod(constructor_template, "a_create", ACreate);
129+
Nan::SetPrototypeMethod(constructor_template, "a_create_ttl", ACreateTtl);
129130
Nan::SetPrototypeMethod(constructor_template, "a_exists", AExists);
130131
Nan::SetPrototypeMethod(constructor_template, "aw_exists", AWExists);
131132
Nan::SetPrototypeMethod(constructor_template, "a_get", AGet);
@@ -190,8 +191,14 @@ class ZooKeeper: public Nan::ObjectWrap {
190191
NODE_DEFINE_CONSTANT(constructor, ZOOKEEPER_WRITE);
191192
NODE_DEFINE_CONSTANT(constructor, ZOOKEEPER_READ);
192193

194+
NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT);
193195
NODE_DEFINE_CONSTANT(constructor, ZOO_EPHEMERAL);
194196
NODE_DEFINE_CONSTANT(constructor, ZOO_SEQUENCE);
197+
NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT_SEQUENTIAL);
198+
NODE_DEFINE_CONSTANT(constructor, ZOO_EPHEMERAL_SEQUENTIAL);
199+
NODE_DEFINE_CONSTANT(constructor, ZOO_CONTAINER);
200+
NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT_WITH_TTL);
201+
NODE_DEFINE_CONSTANT(constructor, ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL);
195202

196203
NODE_DEFINE_CONSTANT(constructor, ZOO_CREATED_EVENT);
197204
NODE_DEFINE_CONSTANT(constructor, ZOO_DELETED_EVENT);
@@ -651,6 +658,22 @@ class ZooKeeper: public Nan::ObjectWrap {
651658
}
652659
}
653660

661+
static void ACreateTtl(const Nan::FunctionCallbackInfo<Value>& info) {
662+
A_METHOD_PROLOG(5);
663+
664+
Nan::Utf8String _path (toString(info[0]));
665+
uint32_t flags = toUint(info[2]);
666+
int32_t ttl = toInt(info[3]);
667+
668+
if (Buffer::HasInstance(info[1])) { // buffer
669+
Local<Object> _data = toLocalObj(info[1]);
670+
METHOD_EPILOG(zoo_acreate_ttl(zk->zhandle, *_path, BufferData(_data), BufferLength(_data), &ZOO_OPEN_ACL_UNSAFE, flags, ttl, string_completion, cb));
671+
} else { // other
672+
Nan::Utf8String _data (toString(info[1]));
673+
METHOD_EPILOG(zoo_acreate_ttl(zk->zhandle, *_path, *_data, _data.length(), &ZOO_OPEN_ACL_UNSAFE, flags, ttl, string_completion, cb));
674+
}
675+
}
676+
654677
static void void_completion (int rc, const void *data) {
655678
struct completion_data *d = (struct completion_data *) data;
656679
void *cb = (void *) d->cb;

tests/unit/index/apitest.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ const test = require('tape');
33
const ZooKeeper = require('../../../lib/index.js');
44

55
function assertPublicApi(zk, t) {
6-
t.plan(25);
6+
t.plan(26);
77

88
t.equal(typeof zk.a_create, 'function');
9+
t.equal(typeof zk.a_createTtl, 'function');
910
t.equal(typeof zk.a_exists, 'function');
1011
t.equal(typeof zk.a_get, 'function');
1112
t.equal(typeof zk.a_get_acl, 'function');

tests/unit/zookeeper/exportedconstantstest.js

-8
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@ const ZooKeeper = require('../../../lib/zookeeper');
66

77
const keys = Object.keys(NativeZk);
88

9-
test('deprecated native static constants are exported', (t) => {
10-
t.plan(keys.length);
11-
12-
keys.forEach((key) => {
13-
t.equal(ZooKeeper[key], NativeZk[key]);
14-
});
15-
});
16-
179
test('native static constants are exported', (t) => {
1810
t.plan(keys.length);
1911

0 commit comments

Comments
 (0)