Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions lib/publisher.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ class Publisher extends Entity {
get subscriptionCount() {
return rclnodejs.getSubscriptionCount(this._handle);
}

/**
* Wait until all published message data is acknowledged or until the specified timeout elapses
*
* If the timeout is negative then this function will block indefinitely until all published
* message data is acknowledged.
* If the timeout is 0 then it will check if all published message has been acknowledged without
* waiting.
* If the timeout is greater than 0 then it will return after that period of time has elapsed or
* all published message data is acknowledged.
*
* Raises an error if failed, such as the middleware not supporting this feature.
*
* @param {timeout} timeout - The duration to wait for all published message data to be acknowledged in nanoseconds.
* @return {boolean} `true` if all published message data is acknowledged before the timeout, otherwise `false`.
*/
waitForAllAcked(timeout) {
return rclnodejs.waitForAllAcked(this._handle, timeout);
}
}

module.exports = Publisher;
19 changes: 19 additions & 0 deletions src/rcl_publisher_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,32 @@ Napi::Value GetSubscriptionCount(const Napi::CallbackInfo& info) {
return Napi::Number::New(env, count);
}

Napi::Value WaitForAllAcked(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
rcl_publisher_t* publisher = reinterpret_cast<rcl_publisher_t*>(
RclHandle::Unwrap(info[0].As<Napi::Object>())->ptr());
bool lossless;
int64_t nanoseconds = info[1].As<Napi::BigInt>().Int64Value(&lossless);

rcl_ret_t ret = rcl_publisher_wait_for_all_acked(publisher, nanoseconds);
if (RCL_RET_OK == ret) {
return Napi::Boolean::New(env, true);
} else if (RCL_RET_TIMEOUT == ret) {
return Napi::Boolean::New(env, false);
}
Napi::Error::New(env, "Failed to wait for all acknowledgements")
.ThrowAsJavaScriptException();
throw env.Undefined();
Copy link

Copilot AI May 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider replacing 'throw env.Undefined();' with 'return env.Undefined();' after throwing the error to improve clarity and avoid unnecessary exception propagation.

Suggested change
throw env.Undefined();
return env.Undefined();

Copilot uses AI. Check for mistakes.
}

Napi::Object InitPublisherBindings(Napi::Env env, Napi::Object exports) {
exports.Set("createPublisher", Napi::Function::New(env, CreatePublisher));
exports.Set("publish", Napi::Function::New(env, Publish));
exports.Set("getPublisherTopic", Napi::Function::New(env, GetPublisherTopic));
exports.Set("publishRawMessage", Napi::Function::New(env, PublishRawMessage));
exports.Set("getSubscriptionCount",
Napi::Function::New(env, GetSubscriptionCount));
exports.Set("waitForAllAcked", Napi::Function::New(env, WaitForAllAcked));
return exports;
}

Expand Down
11 changes: 11 additions & 0 deletions test/test-publisher.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,15 @@ describe('rclnodejs publisher test suite', function () {
node.createSubscription(String, 'topic', (msg) => {});
assert.strictEqual(publisher.subscriptionCount, 1);
});

it('Wait for all acked', function () {
const node = rclnodejs.createNode('publisher_node');
const String = 'std_msgs/msg/String';
const publisher = node.createPublisher(String, 'topic');
node.createSubscription(String, 'topic', (msg) => {});
assert.strictEqual(publisher.subscriptionCount, 1);

publisher.publish('Hello World');
assert.strictEqual(publisher.waitForAllAcked(BigInt(1000000000)), true);
});
});
1 change: 1 addition & 0 deletions test/types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ expectType<void>(publisher.publish(MSG));
expectType<void>(publisher.publish(Buffer.from('Hello ROS World')));
expectType<void>(node.destroyPublisher(publisher));
expectType<boolean>(publisher.isDestroyed());
expectType<boolean>(publisher.waitForAllAcked(BigInt(1000)));

// ---- LifecyclePublisher ----
const lifecyclePublisher = lifecycleNode.createLifecyclePublisher(
Expand Down
17 changes: 17 additions & 0 deletions types/publisher.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,22 @@ declare module 'rclnodejs' {
* @returns The number of subscriptions
*/
subscriptionCount(): number;

/**
* Wait until all published message data is acknowledged or until the specified timeout elapses
*
* If the timeout is negative then this function will block indefinitely until all published
* message data is acknowledged.
* If the timeout is 0 then it will check if all published message has been acknowledged without
* waiting.
* If the timeout is greater than 0 then it will return after that period of time has elapsed or
* all published message data is acknowledged.
*
* Raises an error if failed, such as the middleware not supporting this feature.
*
* @param {timeout} timeout - The duration to wait for all published message data to be acknowledged in nanoseconds.
* @return {boolean} `true` if all published message data is acknowledged before the timeout, otherwise `false`.
*/
waitForAllAcked(timeout: bigint): boolean;
}
}
Loading