@dronedeploy/rocos-js-sdk 3.1.5 → 3.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -43,6 +43,44 @@ export declare class CallerService extends BaseStreamService<ICallerStream> {
|
|
|
43
43
|
ack$: Observable<IRocosCallerMessageResponseAck>;
|
|
44
44
|
cancel: () => Promise<void>;
|
|
45
45
|
};
|
|
46
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
47
|
+
*
|
|
48
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
49
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
50
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
51
|
+
* and tear it down only when the action itself completes/errors.
|
|
52
|
+
*
|
|
53
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
54
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
55
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
56
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
57
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
58
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
59
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
60
|
+
* still receives it.
|
|
61
|
+
*
|
|
62
|
+
* Lifecycle:
|
|
63
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
64
|
+
* errors (or completes) before any ack arrives.
|
|
65
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
66
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
67
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
68
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
69
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
70
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
71
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
72
|
+
* where the action should keep running but the result is no longer needed.
|
|
73
|
+
*
|
|
74
|
+
* @see call
|
|
75
|
+
* @see callRaw
|
|
76
|
+
*/
|
|
77
|
+
callAction<T = unknown>(params: ICallerCallParams): {
|
|
78
|
+
ack: Promise<IRocosCallerMessageResponseAck>;
|
|
79
|
+
result$: Observable<IRocosCallerMessageResponseResult>;
|
|
80
|
+
return$: Observable<T>;
|
|
81
|
+
cancel: () => Promise<void>;
|
|
82
|
+
close: () => void;
|
|
83
|
+
};
|
|
46
84
|
protected createStream(): Promise<ICallerStream>;
|
|
47
85
|
protected getStream(config: IStreamConfig): ICallerStream;
|
|
48
86
|
}
|
|
@@ -104,6 +104,62 @@ class CallerService extends BaseStreamService_1.BaseStreamService {
|
|
|
104
104
|
cancel,
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
108
|
+
*
|
|
109
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
110
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
111
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
112
|
+
* and tear it down only when the action itself completes/errors.
|
|
113
|
+
*
|
|
114
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
115
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
116
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
117
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
118
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
119
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
120
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
121
|
+
* still receives it.
|
|
122
|
+
*
|
|
123
|
+
* Lifecycle:
|
|
124
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
125
|
+
* errors (or completes) before any ack arrives.
|
|
126
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
127
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
128
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
129
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
130
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
131
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
132
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
133
|
+
* where the action should keep running but the result is no longer needed.
|
|
134
|
+
*
|
|
135
|
+
* @see call
|
|
136
|
+
* @see callRaw
|
|
137
|
+
*/
|
|
138
|
+
callAction(params) {
|
|
139
|
+
const stream = this.call(params);
|
|
140
|
+
// Replay the one-shot result so subscription order never matters and a late
|
|
141
|
+
// subscriber still receives it.
|
|
142
|
+
const result = new rxjs_1.ReplaySubject(1);
|
|
143
|
+
// One SDK-owned subscription pins the shared source alive for the whole action.
|
|
144
|
+
// It fires the request once (first subscriber) and forwards the result into the
|
|
145
|
+
// replay subject, completing/erroring it when the action ends. Because this
|
|
146
|
+
// subscription outlives any `firstValueFrom(ack)` teardown, subscriber churn can
|
|
147
|
+
// never reset the source and re-issue the goal.
|
|
148
|
+
const pin = stream.result$.subscribe(result);
|
|
149
|
+
// `ack` rejects if the action errors or completes before any ack arrives. Since
|
|
150
|
+
// callAction is meant to be consumed via result$/return$ too, a caller may never
|
|
151
|
+
// touch `ack` — without a handler that rejection would surface as an unhandled
|
|
152
|
+
// promise rejection. Awaiting `action.ack` still rejects for callers who do care.
|
|
153
|
+
const ack = (0, rxjs_1.firstValueFrom)(stream.ack$);
|
|
154
|
+
ack.catch(() => { });
|
|
155
|
+
return {
|
|
156
|
+
ack,
|
|
157
|
+
result$: result.asObservable(),
|
|
158
|
+
return$: stream.return$,
|
|
159
|
+
cancel: stream.cancel,
|
|
160
|
+
close: () => pin.unsubscribe(),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
107
163
|
async createStream() {
|
|
108
164
|
return (await this.createStreamFromConfig(identifier_1.IDENTIFIER_NAME_CALLER, {
|
|
109
165
|
url: this.config.url,
|
|
@@ -43,6 +43,44 @@ export declare class CallerService extends BaseStreamService<ICallerStream> {
|
|
|
43
43
|
ack$: Observable<IRocosCallerMessageResponseAck>;
|
|
44
44
|
cancel: () => Promise<void>;
|
|
45
45
|
};
|
|
46
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
47
|
+
*
|
|
48
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
49
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
50
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
51
|
+
* and tear it down only when the action itself completes/errors.
|
|
52
|
+
*
|
|
53
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
54
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
55
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
56
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
57
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
58
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
59
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
60
|
+
* still receives it.
|
|
61
|
+
*
|
|
62
|
+
* Lifecycle:
|
|
63
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
64
|
+
* errors (or completes) before any ack arrives.
|
|
65
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
66
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
67
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
68
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
69
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
70
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
71
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
72
|
+
* where the action should keep running but the result is no longer needed.
|
|
73
|
+
*
|
|
74
|
+
* @see call
|
|
75
|
+
* @see callRaw
|
|
76
|
+
*/
|
|
77
|
+
callAction<T = unknown>(params: ICallerCallParams): {
|
|
78
|
+
ack: Promise<IRocosCallerMessageResponseAck>;
|
|
79
|
+
result$: Observable<IRocosCallerMessageResponseResult>;
|
|
80
|
+
return$: Observable<T>;
|
|
81
|
+
cancel: () => Promise<void>;
|
|
82
|
+
close: () => void;
|
|
83
|
+
};
|
|
46
84
|
protected createStream(): Promise<ICallerStream>;
|
|
47
85
|
protected getStream(config: IStreamConfig): ICallerStream;
|
|
48
86
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ResultStatus, RocosResponseLevel, } from '../models';
|
|
2
|
-
import { from, lastValueFrom, map, mergeMap, share, switchMap, take, takeUntil, throwError } from 'rxjs';
|
|
2
|
+
import { ReplaySubject, firstValueFrom, from, lastValueFrom, map, mergeMap, share, switchMap, take, takeUntil, throwError, } from 'rxjs';
|
|
3
3
|
import { catchError, filter } from 'rxjs/operators';
|
|
4
4
|
import { getResponses, handleChunkedMessages } from '../helpers/callerMessageHelpers';
|
|
5
5
|
import { BaseStreamService } from './BaseStreamService';
|
|
@@ -101,6 +101,62 @@ export class CallerService extends BaseStreamService {
|
|
|
101
101
|
cancel,
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
+
/** Invoke a long-running action (ROS 2 action-server semantics) and expose its lifecycle safely.
|
|
105
|
+
*
|
|
106
|
+
* Use this instead of `call` when the request is *accepted* (ack) long before it
|
|
107
|
+
* *completes* (result) — e.g. a navigation goal or a mission. The semantics are:
|
|
108
|
+
* fire the request exactly once, hold the underlying stream open after the ack,
|
|
109
|
+
* and tear it down only when the action itself completes/errors.
|
|
110
|
+
*
|
|
111
|
+
* This differs from `call` in one crucial way: `call` builds `ack$`/`result$` on a
|
|
112
|
+
* refcounted shared source, so awaiting `ack$` (dropping the subscriber count to
|
|
113
|
+
* zero) and *then* subscribing to `result$` re-issues the goal. `callAction` pins the
|
|
114
|
+
* source with a single SDK-owned subscription for the action's lifetime, so:
|
|
115
|
+
* - the request fires once and is never re-issued by subscriber churn,
|
|
116
|
+
* - `ack` is a Promise (inherently replayable — await it in any order),
|
|
117
|
+
* - `result$` replays the one-shot result, so a late or out-of-order subscriber
|
|
118
|
+
* still receives it.
|
|
119
|
+
*
|
|
120
|
+
* Lifecycle:
|
|
121
|
+
* - `ack` resolves with the first acknowledgement; rejects if the action
|
|
122
|
+
* errors (or completes) before any ack arrives.
|
|
123
|
+
* - `result$` emits the single result and completes when the action ends. Replayed,
|
|
124
|
+
* so subscription order relative to awaiting `ack` does not matter.
|
|
125
|
+
* - `return$` streams live feedback/return payloads (decoded as `T`). Not replayed —
|
|
126
|
+
* subscribe before the action emits feedback to avoid missing it.
|
|
127
|
+
* - `cancel` asks the server to cancel; the action then emits its result and closes.
|
|
128
|
+
* - `close` stops tracking the action locally *without* cancelling it on the robot,
|
|
129
|
+
* releasing the underlying stream. For teardown paths (e.g. UI unmount)
|
|
130
|
+
* where the action should keep running but the result is no longer needed.
|
|
131
|
+
*
|
|
132
|
+
* @see call
|
|
133
|
+
* @see callRaw
|
|
134
|
+
*/
|
|
135
|
+
callAction(params) {
|
|
136
|
+
const stream = this.call(params);
|
|
137
|
+
// Replay the one-shot result so subscription order never matters and a late
|
|
138
|
+
// subscriber still receives it.
|
|
139
|
+
const result = new ReplaySubject(1);
|
|
140
|
+
// One SDK-owned subscription pins the shared source alive for the whole action.
|
|
141
|
+
// It fires the request once (first subscriber) and forwards the result into the
|
|
142
|
+
// replay subject, completing/erroring it when the action ends. Because this
|
|
143
|
+
// subscription outlives any `firstValueFrom(ack)` teardown, subscriber churn can
|
|
144
|
+
// never reset the source and re-issue the goal.
|
|
145
|
+
const pin = stream.result$.subscribe(result);
|
|
146
|
+
// `ack` rejects if the action errors or completes before any ack arrives. Since
|
|
147
|
+
// callAction is meant to be consumed via result$/return$ too, a caller may never
|
|
148
|
+
// touch `ack` — without a handler that rejection would surface as an unhandled
|
|
149
|
+
// promise rejection. Awaiting `action.ack` still rejects for callers who do care.
|
|
150
|
+
const ack = firstValueFrom(stream.ack$);
|
|
151
|
+
ack.catch(() => { });
|
|
152
|
+
return {
|
|
153
|
+
ack,
|
|
154
|
+
result$: result.asObservable(),
|
|
155
|
+
return$: stream.return$,
|
|
156
|
+
cancel: stream.cancel,
|
|
157
|
+
close: () => pin.unsubscribe(),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
104
160
|
async createStream() {
|
|
105
161
|
return (await this.createStreamFromConfig(IDENTIFIER_NAME_CALLER, {
|
|
106
162
|
url: this.config.url,
|