Skip to content

Commit 9960c3d

Browse files
committed
Add pre-set and post-set parameter callbacks (#1470)
Add `addPreSetParametersCallback()` / `removePreSetParametersCallback()` and `addPostSetParametersCallback()` / `removePostSetParametersCallback()` to the Node class. Pre-set callbacks run before validation and can transform the parameter list (e.g. coerce values); returning an empty list rejects the set. Post-set callbacks run after parameters are successfully applied, for side effects (e.g. reconfiguring a component). Both follow LIFO ordering (newest callback runs first), matching rclpy's `add_pre_set_parameters_callback` / `add_post_set_parameters_callback` behavior. **Modified: `lib/node.js`** — Added `_preSetParametersCallbacks` and `_postSetParametersCallbacks` arrays. Modified `_setParametersAtomically()` to invoke pre callbacks before validation (merging all returned lists, rejecting on empty) and post callbacks after successful set and ParameterEvent publishing. Added 4 new public methods with JSDoc. **Modified: `types/node.d.ts`** — Added `PreSetParametersCallback` and `PostSetParametersCallback` type aliases, and all 4 new methods to the Node interface. **New: `test/test-pre-post-param-callbacks.js`** — 11 tests covering pre (value modification, empty-list rejection, LIFO ordering, removal), post (called on success, skipped on rejection, LIFO ordering, removal), and full chain (pre→on→post order, pre rejection stops chain, on rejection stops post). Fix : #1469
1 parent bf41b27 commit 9960c3d

4 files changed

Lines changed: 466 additions & 0 deletions

File tree

lib/node.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ class Node extends rclnodejs.ShadowNode {
161161
this._parameterService = null;
162162
this._typeDescriptionService = null;
163163
this._parameterEventPublisher = null;
164+
this._preSetParametersCallbacks = [];
164165
this._setParametersCallbacks = [];
166+
this._postSetParametersCallbacks = [];
165167
this._logger = new Logging(rclnodejs.getNodeLoggerName(this.handle));
166168
this._spinning = false;
167169
this._enableRosout = options.enableRosout;
@@ -2057,6 +2059,29 @@ class Node extends rclnodejs.ShadowNode {
20572059
* @return {SetParameterResult} - A single collective result.
20582060
*/
20592061
_setParametersAtomically(parameters = [], declareParameterMode = false) {
2062+
// 1) PRE callbacks — pipeline: each callback receives the output of the previous
2063+
if (this._preSetParametersCallbacks.length > 0) {
2064+
for (const callback of this._preSetParametersCallbacks) {
2065+
const result = callback(parameters);
2066+
if (!Array.isArray(result)) {
2067+
return {
2068+
successful: false,
2069+
reason:
2070+
'pre-set parameters callback must return an array of Parameters',
2071+
};
2072+
}
2073+
parameters = result;
2074+
if (parameters.length === 0) {
2075+
return {
2076+
successful: false,
2077+
reason:
2078+
'parameter list is empty after pre-set callback; set rejected',
2079+
};
2080+
}
2081+
}
2082+
}
2083+
2084+
// 2) Validate
20602085
let result = this._validateParameters(parameters, declareParameterMode);
20612086
if (!result.successful) {
20622087
return result;
@@ -2126,6 +2151,11 @@ class Node extends rclnodejs.ShadowNode {
21262151
// Publish ParameterEvent.
21272152
this._parameterEventPublisher.publish(parameterEvent);
21282153

2154+
// POST callbacks — for side effects after successful set
2155+
for (const callback of this._postSetParametersCallbacks) {
2156+
callback(parameters);
2157+
}
2158+
21292159
return {
21302160
successful: true,
21312161
reason: '',
@@ -2170,6 +2200,82 @@ class Node extends rclnodejs.ShadowNode {
21702200
}
21712201
}
21722202

2203+
/**
2204+
* A callback invoked before parameter validation and setting.
2205+
* It receives the parameter list and must return a (possibly modified) parameter list.
2206+
*
2207+
* @callback PreSetParametersCallback
2208+
* @param {Parameter[]} parameters - The parameters about to be set.
2209+
* @returns {Parameter[]} - The modified parameter list to proceed with.
2210+
*
2211+
* @see [Node.addPreSetParametersCallback]{@link Node#addPreSetParametersCallback}
2212+
* @see [Node.removePreSetParametersCallback]{@link Node#removePreSetParametersCallback}
2213+
*/
2214+
2215+
/**
2216+
* Add a callback invoked before parameter validation.
2217+
* The callback receives the parameter list and must return a (possibly modified)
2218+
* parameter list. This can be used to coerce, add, or remove parameters before
2219+
* they are validated and applied. If any pre-set callback returns an empty list,
2220+
* the set is rejected.
2221+
*
2222+
* @param {PreSetParametersCallback} callback - The callback to add.
2223+
* @returns {undefined}
2224+
*/
2225+
addPreSetParametersCallback(callback) {
2226+
this._preSetParametersCallbacks.unshift(callback);
2227+
}
2228+
2229+
/**
2230+
* Remove a pre-set parameters callback.
2231+
*
2232+
* @param {PreSetParametersCallback} callback - The callback to remove.
2233+
* @returns {undefined}
2234+
*/
2235+
removePreSetParametersCallback(callback) {
2236+
const idx = this._preSetParametersCallbacks.indexOf(callback);
2237+
if (idx > -1) {
2238+
this._preSetParametersCallbacks.splice(idx, 1);
2239+
}
2240+
}
2241+
2242+
/**
2243+
* A callback invoked after parameters have been successfully set.
2244+
* It receives the final parameter list. For side effects only (return value is ignored).
2245+
*
2246+
* @callback PostSetParametersCallback
2247+
* @param {Parameter[]} parameters - The parameters that were set.
2248+
* @returns {undefined}
2249+
*
2250+
* @see [Node.addPostSetParametersCallback]{@link Node#addPostSetParametersCallback}
2251+
* @see [Node.removePostSetParametersCallback]{@link Node#removePostSetParametersCallback}
2252+
*/
2253+
2254+
/**
2255+
* Add a callback invoked after parameters are successfully set.
2256+
* The callback receives the final parameter list. Useful for triggering
2257+
* side effects (e.g., reconfiguring a component when a parameter changes).
2258+
*
2259+
* @param {PostSetParametersCallback} callback - The callback to add.
2260+
* @returns {undefined}
2261+
*/
2262+
addPostSetParametersCallback(callback) {
2263+
this._postSetParametersCallbacks.unshift(callback);
2264+
}
2265+
2266+
/**
2267+
* Remove a post-set parameters callback.
2268+
*
2269+
* @param {PostSetParametersCallback} callback - The callback to remove.
2270+
* @returns {undefined}
2271+
*/
2272+
removePostSetParametersCallback(callback) {
2273+
const idx = this._postSetParametersCallbacks.indexOf(callback);
2274+
if (idx > -1) {
2275+
this._postSetParametersCallbacks.splice(idx, 1);
2276+
}
2277+
}
2278+
21732279
/**
21742280
* Get the fully qualified name of the node.
21752281
*

0 commit comments

Comments
 (0)