@hydranium/glsp-client 1.0.0-next.327 → 1.0.0-next.328

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.
package/README.md CHANGED
@@ -115,7 +115,14 @@ for touch, and size its `<svg>` to it, or sprotty draws into 300×150. The
115
115
  first render replaces the element with sprotty's own under the same id, so
116
116
  keep no reference to it and find it by id when you need it. A failed load
117
117
  resolves the mount; read `diagram.loadOutcome` to report it, since the status
118
- overlay cannot show a failure of the action dispatcher itself.
118
+ overlay cannot show a failure of the action dispatcher itself. A page that
119
+ asks before a reload also reads `diagram.editsInFlight`, the edits the server
120
+ has not answered yet, which no dirty state shows, and a save or a file
121
+ switch awaits `diagram.whenEditsSettled()` so it does not run ahead of one,
122
+ and stops when it resolves `false`, its bound passed with one unanswered.
123
+ A host that calls `createGlspClientModule` itself counts them only when it
124
+ passes `trackEditsInFlight: true`, and reads them from
125
+ `HydraniumGlspActionDispatcher`.
119
126
 
120
127
  For a browser page, see *Host in a browser* in
121
128
  [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
@@ -7,7 +7,7 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
  import { type Action, CheckEdgeResultAction, GLSPActionDispatcher, RequestCheckEdgeAction } from '@eclipse-glsp/client';
10
- import { type Clock, type Logger, type Stopwatch, type Tracer } from '@hydranium/protocol';
10
+ import { type Clock, Deferred, type Logger, PendingWorkTracker, type Stopwatch, type Tracer } from '@hydranium/protocol';
11
11
  /** Default subset of action kinds the framework dispatcher will log: the GLSP
12
12
  * traffic an observer reading the log typically wants to see. All
13
13
  * are standard `@eclipse-glsp/client` kinds; adopters with custom action kinds
@@ -38,15 +38,41 @@ export interface HydraniumGlspActionDispatcherOptions {
38
38
  * kind the protocol defines. Adopters with custom kinds either pass
39
39
  * `extraLoggedKinds` / `extraKindPairs` to the constructor (via a
40
40
  * `toDynamicValue` binding) or subclass and override.
41
+ *
42
+ * Where the host asks for it, it also counts the edits it sends that the server
43
+ * has not answered yet, as {@link editsInFlight}, so a page can ask before a
44
+ * reload drops one. The dirty state cannot say this: the server sets it only
45
+ * once it has answered, and an edit that changed nothing is answered with
46
+ * nothing at all. Each edit is followed by a {@link RequestEditsSettledAction},
47
+ * which the server answers after it, and counts until that request or a later
48
+ * one is answered or rejected: the server handles them in order. With no
49
+ * answer, as when the connection is lost, the count stays, so a guard asks
50
+ * rather than loses the edit. An action from the server is not counted, nor
51
+ * is anything on a server that serves no settle request.
41
52
  */
42
53
  export declare class HydraniumGlspActionDispatcher extends GLSPActionDispatcher {
43
54
  protected readonly hydraniumLogger: Logger;
44
55
  protected readonly tracer: Tracer;
45
56
  /** Times each request to its response: the diagram container's {@link Clock}, or a `SystemClock`. */
46
57
  protected readonly clock: Clock;
58
+ /** Whether to count edits in flight; the host asks for it through `createGlspClientModule`. */
59
+ protected readonly trackEditsInFlight: boolean;
47
60
  protected readonly loggedKinds: ReadonlySet<string>;
48
61
  protected readonly kindPairs: ReadonlyMap<string, string>;
49
62
  protected readonly kindPairsReverse: ReadonlyMap<string, string>;
63
+ /** Per edit sent, until its {@link RequestEditsSettledAction} or a later one is answered or rejected. */
64
+ protected readonly pendingEdits: PendingWorkTracker;
65
+ /** The edits in flight by the number of their settle request, in send order. */
66
+ protected readonly editsBySettle: Map<number, Deferred<void>>;
67
+ protected settlesSent: number;
68
+ /**
69
+ * How long {@link whenEditsSettled} waits before going on anyway: well past
70
+ * the server's bounded waits on one settle together. Its handling of the
71
+ * edits before has no bound, so a server slower than that is taken as lost.
72
+ */
73
+ protected readonly settleEditsMs: number;
74
+ /** The postponed actions a lifted block is dispatching a second time, counted when first sent. */
75
+ protected redispatched: ReadonlySet<Action> | undefined;
50
76
  protected pairCounter: number;
51
77
  /** Pending requests keyed by requestId (for actions that carry one). */
52
78
  protected pendingById: Map<string, {
@@ -69,7 +95,31 @@ export declare class HydraniumGlspActionDispatcher extends GLSPActionDispatcher
69
95
  * uncaught rejection that blanks the diagram with no server-side signal.
70
96
  */
71
97
  protected registerInitTiming(): void;
98
+ /** How many edits the server has not answered yet; see {@link isEdit}. */
99
+ get editsInFlight(): number;
100
+ /**
101
+ * Resolves to `true` once the edits in flight now have been answered or
102
+ * rejected, or to `false` once {@link settleEditsMs} has passed first. An
103
+ * edit sent while it waits is not waited for. Never rejects. For a save or a
104
+ * switch that must not run ahead of an edit the server has not answered.
105
+ */
106
+ whenEditsSettled(): Promise<boolean>;
72
107
  dispatch(action: Action): Promise<void>;
108
+ protected handleBlocked(action: Action, predicate: (action: Action) => boolean): Promise<void>;
109
+ /** Whether `action` changes the model on the server: an operation, an undo or a redo. Widen it for an edit kind of your own. */
110
+ protected isEdit(action: Action): boolean;
111
+ /**
112
+ * Count `action` if it is an edit the client sends, even one whose dispatch
113
+ * failed, since it may have reached the server. One dispatched again counts
114
+ * again, except where a lifted block dispatches what it postponed.
115
+ */
116
+ protected trackEdit(action: Action): void;
117
+ /**
118
+ * End every edit up to the `settle`th: the server handles a client's actions
119
+ * in order, so its answer covers the edits before it, one whose own settle
120
+ * was lost included.
121
+ */
122
+ protected endEditsThrough(settle: number): void;
73
123
  protected logAction(action: Action): void;
74
124
  protected classify(action: Action): {
75
125
  verb: string;
@@ -1 +1 @@
1
- {"version":3,"file":"action-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,MAAM,EACX,qBAAqB,EAErB,oBAAoB,EAOpB,sBAAsB,EAaxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,MAAM,EAAE,KAAK,SAAS,EAAe,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAIxG;;;qCAGqC;AACrC,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAiB7D,CAAC;AAEH;;gEAEgE;AAChE,eAAO,MAAM,4BAA4B,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAInE,CAAC;AAEH;;6EAE6E;AAC7E,MAAM,WAAW,oCAAoC;IAClD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D;+DAC2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAClD;AAED;;;;;;;;;;;GAWG;AACH,qBACa,6BAA8B,SAAQ,oBAAoB;IAC/B,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAG,MAAM,CAAC;IAC5C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAG,MAAM,CAAC;IACxE,qGAAqG;IACrD,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAqB;IAEpG,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjE,SAAS,CAAC,WAAW,SAAK;IAC1B,wEAAwE;IACxE,SAAS,CAAC,WAAW;YAAyB,MAAM;sBAAgB,SAAS;OAAM;IACnF,wFAAwF;IACxF,SAAS,CAAC,aAAa;YAA+B,MAAM;sBAAgB,SAAS;SAAO;IAE5F,YAAyB,OAAO,CAAC,EAAE,oCAAoC,EAWtE;IAEQ,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAOnC;IAED;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,IAAI,IAAI,CAMnC;IAEQ,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/C;IAED,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAYxC;IAED,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAgBtE;IAED;gFAC4E;IAC5E,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA+B1C;IAED,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,SAAS,CAAA;KAAE,GAAG,MAAM,CAG/E;IAED,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAsC1C;IAED,yGAAyG;IACzG,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,sBAAsB,GAAG,qBAAqB,GAAG,MAAM,CAGxF;CACH"}
1
+ {"version":3,"file":"action-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-dispatcher.ts"],"names":[],"mappings":"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"}
@@ -66,15 +66,41 @@ exports.HYDRANIUM_DEFAULT_KIND_PAIRS = new Map([
66
66
  * kind the protocol defines. Adopters with custom kinds either pass
67
67
  * `extraLoggedKinds` / `extraKindPairs` to the constructor (via a
68
68
  * `toDynamicValue` binding) or subclass and override.
69
+ *
70
+ * Where the host asks for it, it also counts the edits it sends that the server
71
+ * has not answered yet, as {@link editsInFlight}, so a page can ask before a
72
+ * reload drops one. The dirty state cannot say this: the server sets it only
73
+ * once it has answered, and an edit that changed nothing is answered with
74
+ * nothing at all. Each edit is followed by a {@link RequestEditsSettledAction},
75
+ * which the server answers after it, and counts until that request or a later
76
+ * one is answered or rejected: the server handles them in order. With no
77
+ * answer, as when the connection is lost, the count stays, so a guard asks
78
+ * rather than loses the edit. An action from the server is not counted, nor
79
+ * is anything on a server that serves no settle request.
69
80
  */
70
81
  let HydraniumGlspActionDispatcher = class HydraniumGlspActionDispatcher extends client_1.GLSPActionDispatcher {
71
82
  hydraniumLogger;
72
83
  tracer;
73
84
  /** Times each request to its response: the diagram container's {@link Clock}, or a `SystemClock`. */
74
85
  clock = new protocol_1.SystemClock();
86
+ /** Whether to count edits in flight; the host asks for it through `createGlspClientModule`. */
87
+ trackEditsInFlight = false;
75
88
  loggedKinds;
76
89
  kindPairs;
77
90
  kindPairsReverse;
91
+ /** Per edit sent, until its {@link RequestEditsSettledAction} or a later one is answered or rejected. */
92
+ pendingEdits = new protocol_1.PendingWorkTracker();
93
+ /** The edits in flight by the number of their settle request, in send order. */
94
+ editsBySettle = new Map();
95
+ settlesSent = 0;
96
+ /**
97
+ * How long {@link whenEditsSettled} waits before going on anyway: well past
98
+ * the server's bounded waits on one settle together. Its handling of the
99
+ * edits before has no bound, so a server slower than that is taken as lost.
100
+ */
101
+ settleEditsMs = 30_000;
102
+ /** The postponed actions a lifted block is dispatching a second time, counted when first sent. */
103
+ redispatched;
78
104
  pairCounter = 0;
79
105
  /** Pending requests keyed by requestId (for actions that carry one). */
80
106
  pendingById = new Map();
@@ -116,11 +142,80 @@ let HydraniumGlspActionDispatcher = class HydraniumGlspActionDispatcher extends
116
142
  this.hydraniumLogger.error('Failed to register model-initialized timing instrumentation', err);
117
143
  }
118
144
  }
145
+ /** How many edits the server has not answered yet; see {@link isEdit}. */
146
+ get editsInFlight() {
147
+ return this.pendingEdits.size;
148
+ }
149
+ /**
150
+ * Resolves to `true` once the edits in flight now have been answered or
151
+ * rejected, or to `false` once {@link settleEditsMs} has passed first. An
152
+ * edit sent while it waits is not waited for. Never rejects. For a save or a
153
+ * switch that must not run ahead of an edit the server has not answered.
154
+ */
155
+ async whenEditsSettled() {
156
+ if (this.pendingEdits.isIdle) {
157
+ return true;
158
+ }
159
+ return (await this.clock.raceTimer(this.pendingEdits.whenSettled(), this.settleEditsMs)) !== protocol_1.TIMED_OUT;
160
+ }
119
161
  dispatch(action) {
120
162
  if (this.loggedKinds.has(action.kind)) {
121
163
  this.logAction(action);
122
164
  }
123
- return super.dispatch(action);
165
+ const dispatched = super.dispatch(action);
166
+ this.trackEdit(action);
167
+ return dispatched;
168
+ }
169
+ handleBlocked(action, predicate) {
170
+ if (!predicate(action)) {
171
+ return super.handleBlocked(action, predicate);
172
+ }
173
+ // A lifted block dispatches what it postponed again, within this call.
174
+ this.redispatched = new Set(this.postponedActions.map(postponed => postponed.action));
175
+ try {
176
+ return super.handleBlocked(action, predicate);
177
+ }
178
+ finally {
179
+ this.redispatched = undefined;
180
+ }
181
+ }
182
+ /** Whether `action` changes the model on the server: an operation, an undo or a redo. Widen it for an edit kind of your own. */
183
+ isEdit(action) {
184
+ return client_1.Operation.is(action) || client_1.UndoAction.is(action) || client_1.RedoAction.is(action);
185
+ }
186
+ /**
187
+ * Count `action` if it is an edit the client sends, even one whose dispatch
188
+ * failed, since it may have reached the server. One dispatched again counts
189
+ * again, except where a lifted block dispatches what it postponed.
190
+ */
191
+ trackEdit(action) {
192
+ if (!this.trackEditsInFlight ||
193
+ client_1.ServerAction.is(action) ||
194
+ !this.isEdit(action) ||
195
+ this.redispatched?.has(action) ||
196
+ !this.hasHandler({ kind: protocol_1.RequestEditsSettledAction.KIND })) {
197
+ return;
198
+ }
199
+ const settle = ++this.settlesSent;
200
+ const edit = new protocol_1.Deferred();
201
+ this.editsBySettle.set(settle, edit);
202
+ void this.pendingEdits.track(edit.promise);
203
+ const answered = () => this.endEditsThrough(settle);
204
+ this.request(protocol_1.RequestEditsSettledAction.create()).then(answered, answered);
205
+ }
206
+ /**
207
+ * End every edit up to the `settle`th: the server handles a client's actions
208
+ * in order, so its answer covers the edits before it, one whose own settle
209
+ * was lost included.
210
+ */
211
+ endEditsThrough(settle) {
212
+ for (const [sent, edit] of this.editsBySettle) {
213
+ if (sent > settle) {
214
+ break;
215
+ }
216
+ edit.resolve();
217
+ this.editsBySettle.delete(sent);
218
+ }
124
219
  }
125
220
  logAction(action) {
126
221
  const { verb, direction } = this.classify(action);
@@ -249,6 +344,11 @@ __decorate([
249
344
  (0, inversify_1.optional)(),
250
345
  __metadata("design:type", Object)
251
346
  ], HydraniumGlspActionDispatcher.prototype, "clock", void 0);
347
+ __decorate([
348
+ (0, inversify_1.inject)(types_1.HydraniumClientTypes.TrackEditsInFlight),
349
+ (0, inversify_1.optional)(),
350
+ __metadata("design:type", Boolean)
351
+ ], HydraniumGlspActionDispatcher.prototype, "trackEditsInFlight", void 0);
252
352
  exports.HydraniumGlspActionDispatcher = HydraniumGlspActionDispatcher = __decorate([
253
353
  (0, inversify_1.injectable)(),
254
354
  __param(0, (0, inversify_1.unmanaged)()),
@@ -1 +1 @@
1
- {"version":3,"file":"action-dispatcher.js","sourceRoot":"","sources":["../src/action-dispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"action-dispatcher.js","sourceRoot":"","sources":["../src/action-dispatcher.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,23 @@ export interface GlspDiagramMount extends Disposable {
41
41
  * the caller learns of it; when the failure is not `surfaced`, no overlay
42
42
  * shows it and the caller is the only report left. */
43
43
  readonly loadOutcome: DiagramLoadOutcome;
44
+ /**
45
+ * How many edits the server has not answered yet, as
46
+ * {@link HydraniumGlspActionDispatcher.editsInFlight} counts them, for a
47
+ * page that asks before a reload drops one: the diagram's dirty state is
48
+ * set only once the server has answered. None after a failed load, or
49
+ * when the dispatcher is not the framework's. None once disposed either:
50
+ * the server drops the edits the ended session still had queued, though
51
+ * one it was handling still lands.
52
+ */
53
+ readonly editsInFlight: number;
54
+ /**
55
+ * Resolves to `true` once the edits in flight now have been answered or
56
+ * rejected, or to `false` once the dispatcher's bound has passed first, as
57
+ * {@link HydraniumGlspActionDispatcher.whenEditsSettled} does. `true` at
58
+ * once wherever {@link editsInFlight} reads none.
59
+ */
60
+ whenEditsSettled(): Promise<boolean>;
44
61
  /** Ends the client session on the server and stops watching the element;
45
62
  * what is drawn in it is left to the host to remove. */
46
63
  dispose(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"diagram-mount.d.ts","sourceRoot":"","sources":["../src/diagram-mount.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAEJ,KAAK,sBAAsB,EAU7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,UAAU,EAAwB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAmB,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,KAAK,kBAAkB,EAA0B,MAAM,kBAAkB,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAKzD,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACrC;;;;0EAIsE;IACtE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,sCAAsC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;+DAC2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC;;uEAEmE;IACnE,QAAQ,CAAC,0BAA0B,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,aAAa,EAAE,sBAAsB,KAAK,SAAS,CAAC;IACnH,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B;;2DAEuD;IACvD,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IACzC;6DACyD;IACzD,OAAO,IAAI,IAAI,CAAC;CAClB;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiElG"}
1
+ {"version":3,"file":"diagram-mount.d.ts","sourceRoot":"","sources":["../src/diagram-mount.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAEJ,KAAK,sBAAsB,EAU7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,UAAU,EAAwB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAmB,MAAM,WAAW,CAAC;AAEvD,OAAO,EAAE,KAAK,kBAAkB,EAA0B,MAAM,kBAAkB,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAKzD,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACrC;;;;0EAIsE;IACtE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,sCAAsC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;+DAC2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC;;uEAEmE;IACnE,QAAQ,CAAC,0BAA0B,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,aAAa,EAAE,sBAAsB,KAAK,SAAS,CAAC;IACnH,qEAAqE;IACrE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B;;2DAEuD;IACvD,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IACzC;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC;6DACyD;IACzD,OAAO,IAAI,IAAI,CAAC;CAClB;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkFlG"}
@@ -13,6 +13,7 @@ exports.mountGlspDiagram = mountGlspDiagram;
13
13
  const client_1 = require("@eclipse-glsp/client");
14
14
  const protocol_1 = require("@hydranium/protocol");
15
15
  const inversify_1 = require("inversify");
16
+ const action_dispatcher_1 = require("./action-dispatcher");
16
17
  const diagram_loader_1 = require("./diagram-loader");
17
18
  const glsp_client_module_1 = require("./glsp-client-module");
18
19
  const touch_input_1 = require("./touch-input");
@@ -82,7 +83,7 @@ async function mountGlspDiagram(options) {
82
83
  // After the standalone modules, since every class the binder binds replaces
83
84
  // a token those modules bind.
84
85
  const hydraniumModule = new inversify_1.ContainerModule((bind, unbind, isBound, rebind) => {
85
- (0, glsp_client_module_1.createGlspClientModule)({ bind, unbind, isBound, rebind }, { logger: options.logger });
86
+ (0, glsp_client_module_1.createGlspClientModule)({ bind, unbind, isBound, rebind }, { logger: options.logger, trackEditsInFlight: true });
86
87
  });
87
88
  const container = options.initializeDiagramContainer(new inversify_1.Container(), (0, client_1.createDiagramOptionsModule)(diagramOptions), client_1.STANDALONE_MODULE_CONFIG, hydraniumModule);
88
89
  // After the container is built rather than in a module, so the host's own
@@ -94,7 +95,21 @@ async function mountGlspDiagram(options) {
94
95
  // Pushed first, so it runs last: `unbindAll` reaches `disposeClientSession`
95
96
  // through the model source's pre-destroy hook, after the listeners are gone.
96
97
  toDispose.push({ dispose: () => container.unbindAll() });
97
- const dispose = () => toDispose.dispose();
98
+ // Set once the mount loaded with the framework's dispatcher, until disposed.
99
+ let editsDispatcher;
100
+ const dispose = () => {
101
+ editsDispatcher = undefined;
102
+ toDispose.dispose();
103
+ };
104
+ const mountWith = (loadOutcome) => ({
105
+ container,
106
+ loadOutcome,
107
+ get editsInFlight() {
108
+ return editsDispatcher?.editsInFlight ?? 0;
109
+ },
110
+ whenEditsSettled: () => editsDispatcher?.whenEditsSettled() ?? Promise.resolve(true),
111
+ dispose
112
+ });
98
113
  try {
99
114
  const loader = container.get(client_1.DiagramLoader);
100
115
  await loader.load();
@@ -103,7 +118,7 @@ async function mountGlspDiagram(options) {
103
118
  // A model that never arrived has no use for the accommodations, and when
104
119
  // the dispatcher is what failed, every later dispatch rejects too.
105
120
  if (loadOutcome.status === 'failed') {
106
- return { container, loadOutcome, dispose };
121
+ return mountWith(loadOutcome);
107
122
  }
108
123
  const dispatcher = container.get(client_1.TYPES.IActionDispatcher);
109
124
  // The bounds the fit measures come from the hidden rendering pass inside
@@ -118,7 +133,10 @@ async function mountGlspDiagram(options) {
118
133
  }
119
134
  toDispose.push(trackCanvasBounds(live, dispatcher, container.get(client_1.EditorContextService), container.get(types_1.HydraniumClientTypes.Logger)));
120
135
  toDispose.push((0, touch_input_1.enableTouchDragging)(live));
121
- return { container, loadOutcome, dispose };
136
+ if (dispatcher instanceof action_dispatcher_1.HydraniumGlspActionDispatcher) {
137
+ editsDispatcher = dispatcher;
138
+ }
139
+ return mountWith(loadOutcome);
122
140
  }
123
141
  catch (err) {
124
142
  // The caller gets no mount to dispose, so the session would outlive it.
@@ -1 +1 @@
1
- {"version":3,"file":"diagram-mount.js","sourceRoot":"","sources":["../src/diagram-mount.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diagram-mount.js","sourceRoot":"","sources":["../src/diagram-mount.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,11 @@ export interface GlspClientModuleOptions {
14
14
  * binding the host made. Absent, the token keeps the host's own binding, or
15
15
  * gets a `ConsoleLogger` when it has none. */
16
16
  readonly logger?: Logger;
17
+ /** Count the diagram edits the server has not answered yet, as
18
+ * `HydraniumGlspActionDispatcher.editsInFlight`, for a host that reads the
19
+ * count. Off by default: each edit then costs an extra request and its
20
+ * answer. */
21
+ readonly trackEditsInFlight?: boolean;
17
22
  }
18
23
  /**
19
24
  * Binds the framework's client classes into a GLSP diagram container, whatever
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-client-module.d.ts","sourceRoot":"","sources":["../src/glsp-client-module.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,cAAc,EAOrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAA4C,KAAK,MAAM,EAAe,MAAM,qBAAqB,CAAC;AASzG,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACrC;;mDAE+C;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,uBAA4B,GAAG,IAAI,CAyB3G"}
1
+ {"version":3,"file":"glsp-client-module.d.ts","sourceRoot":"","sources":["../src/glsp-client-module.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,cAAc,EAOrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAA4C,KAAK,MAAM,EAAe,MAAM,qBAAqB,CAAC;AASzG,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACrC;;mDAE+C;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;kBAGc;IACd,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,uBAA4B,GAAG,IAAI,CA8B3G"}
@@ -55,6 +55,9 @@ function createGlspClientModule(context, options = {}) {
55
55
  })
56
56
  .inSingletonScope();
57
57
  }
58
+ if (options.trackEditsInFlight !== undefined) {
59
+ (isBound(types_1.HydraniumClientTypes.TrackEditsInFlight) ? rebind : bind)(types_1.HydraniumClientTypes.TrackEditsInFlight).toConstantValue(options.trackEditsInFlight);
60
+ }
58
61
  bind(action_dispatcher_1.HydraniumGlspActionDispatcher).toSelf().inSingletonScope();
59
62
  rebind(client_1.GLSPActionDispatcher).toService(action_dispatcher_1.HydraniumGlspActionDispatcher);
60
63
  rebind(client_1.DiagramLoader).to(diagram_loader_1.HydraniumDiagramLoader).inSingletonScope();
@@ -1 +1 @@
1
- {"version":3,"file":"glsp-client-module.js","sourceRoot":"","sources":["../src/glsp-client-module.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,iDAQ8B;AAC9B,kDAAyG;AACzG,2DAAoE;AACpE,qDAA0D;AAC1D,mEAAuE;AACvE,mEAAuE;AACvE,qEAAgE;AAChE,qDAA0D;AAC1D,mCAA+C;AAU/C;;;;;;;;;;;;;;;;;GAiBG;AACH,gCAAuC,OAAuB,EAAE,OAAO,GAA4B,EAAE;IAClG,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC1C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC,OAAO,CAAC,4BAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,4BAAoB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvH,CAAC;SAAM,IAAI,CAAC,OAAO,CAAC,4BAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,4BAAoB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,IAAI,wBAAa,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,4BAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,4BAAoB,CAAC,MAAM,CAAC;aAC7B,cAAc,CAAC,GAAG,CAAC,EAAE;YACnB,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAS,4BAAoB,CAAC,MAAM,CAAC,CAAC;YACtE,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,4BAAoB,CAAC,KAAK,CAAC;gBAC5D,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAQ,4BAAoB,CAAC,KAAK,CAAC;gBACtD,CAAC,CAAC,IAAI,sBAAW,EAAE,CAAC;YACvB,OAAO,IAAI,wBAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC;aACD,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,CAAC,iDAA6B,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;IAChE,MAAM,CAAC,6BAAoB,CAAC,CAAC,SAAS,CAAC,iDAA6B,CAAC,CAAC;IACtE,MAAM,CAAC,sBAAa,CAAC,CAAC,EAAE,CAAC,uCAAsB,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpE,MAAM,CAAC,gCAAuB,CAAC,CAAC,EAAE,CAAC,oDAA4B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpF,MAAM,CAAC,sBAAa,CAAC,CAAC,EAAE,CAAC,uCAAsB,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpE,MAAM,CAAC,kCAAyB,CAAC,CAAC,EAAE,CAAC,oDAA4B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACtF,MAAM,CAAC,cAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,6CAAoB,CAAC,CAAC,gBAAgB,EAAE,CAAC;AACrE,CAAC"}
1
+ {"version":3,"file":"glsp-client-module.js","sourceRoot":"","sources":["../src/glsp-client-module.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,iDAQ8B;AAC9B,kDAAyG;AACzG,2DAAoE;AACpE,qDAA0D;AAC1D,mEAAuE;AACvE,mEAAuE;AACvE,qEAAgE;AAChE,qDAA0D;AAC1D,mCAA+C;AAe/C;;;;;;;;;;;;;;;;;GAiBG;AACH,gCAAuC,OAAuB,EAAE,OAAO,GAA4B,EAAE;IAClG,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC1C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC,OAAO,CAAC,4BAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,4BAAoB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvH,CAAC;SAAM,IAAI,CAAC,OAAO,CAAC,4BAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,4BAAoB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,IAAI,wBAAa,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,4BAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,4BAAoB,CAAC,MAAM,CAAC;aAC7B,cAAc,CAAC,GAAG,CAAC,EAAE;YACnB,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAS,4BAAoB,CAAC,MAAM,CAAC,CAAC;YACtE,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,4BAAoB,CAAC,KAAK,CAAC;gBAC5D,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAQ,4BAAoB,CAAC,KAAK,CAAC;gBACtD,CAAC,CAAC,IAAI,sBAAW,EAAE,CAAC;YACvB,OAAO,IAAI,wBAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC;aACD,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC5C,CAAC,OAAO,CAAC,4BAAoB,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,4BAAoB,CAAC,kBAAkB,CAAC,CAAC,eAAe,CACxH,OAAO,CAAC,kBAAkB,CAC5B,CAAC;IACL,CAAC;IACD,IAAI,CAAC,iDAA6B,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;IAChE,MAAM,CAAC,6BAAoB,CAAC,CAAC,SAAS,CAAC,iDAA6B,CAAC,CAAC;IACtE,MAAM,CAAC,sBAAa,CAAC,CAAC,EAAE,CAAC,uCAAsB,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpE,MAAM,CAAC,gCAAuB,CAAC,CAAC,EAAE,CAAC,oDAA4B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpF,MAAM,CAAC,sBAAa,CAAC,CAAC,EAAE,CAAC,uCAAsB,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpE,MAAM,CAAC,kCAAyB,CAAC,CAAC,EAAE,CAAC,oDAA4B,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACtF,MAAM,CAAC,cAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,6CAAoB,CAAC,CAAC,gBAAgB,EAAE,CAAC;AACrE,CAAC"}
package/lib/types.d.ts CHANGED
@@ -17,11 +17,13 @@ import type { interfaces } from 'inversify';
17
17
  * `Logger` and `Tracer` are required, so a host that binds neither fails at
18
18
  * resolution rather than running silent; `createGlspClientModule` binds
19
19
  * defaults for a host that passes none. `Clock` is optional: the classes fall
20
- * back to a `SystemClock`.
20
+ * back to a `SystemClock`. `TrackEditsInFlight` is optional too, and off
21
+ * unbound: `createGlspClientModule` binds it for a host that asks.
21
22
  */
22
23
  export declare const HydraniumClientTypes: {
23
24
  readonly Logger: interfaces.ServiceIdentifier<Logger>;
24
25
  readonly Tracer: interfaces.ServiceIdentifier<Tracer>;
25
26
  readonly Clock: interfaces.ServiceIdentifier<Clock>;
27
+ readonly TrackEditsInFlight: interfaces.ServiceIdentifier<boolean>;
26
28
  };
27
29
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAQ5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB;aAC9B,MAAM;aACN,MAAM;aACN,KAAK;CACE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAQ5C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB;aAC9B,MAAM;aACN,MAAM;aACN,KAAK;aACL,kBAAkB;CACX,CAAC"}
package/lib/types.js CHANGED
@@ -23,11 +23,13 @@ function serviceIdentifier(description) {
23
23
  * `Logger` and `Tracer` are required, so a host that binds neither fails at
24
24
  * resolution rather than running silent; `createGlspClientModule` binds
25
25
  * defaults for a host that passes none. `Clock` is optional: the classes fall
26
- * back to a `SystemClock`.
26
+ * back to a `SystemClock`. `TrackEditsInFlight` is optional too, and off
27
+ * unbound: `createGlspClientModule` binds it for a host that asks.
27
28
  */
28
29
  exports.HydraniumClientTypes = {
29
30
  Logger: serviceIdentifier('HydraniumClientLogger'),
30
31
  Tracer: serviceIdentifier('HydraniumClientTracer'),
31
- Clock: serviceIdentifier('HydraniumClientClock')
32
+ Clock: serviceIdentifier('HydraniumClientClock'),
33
+ TrackEditsInFlight: serviceIdentifier('HydraniumClientTrackEditsInFlight')
32
34
  };
33
35
  //# sourceMappingURL=types.js.map
package/lib/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAKlF;gEACgE;AAChE,SAAS,iBAAiB,CAAI,WAAmB;IAC9C,OAAO,MAAM,CAAC,WAAW,CAAoC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;GAUG;AACU,QAAA,oBAAoB,GAAG;IACjC,MAAM,EAAE,iBAAiB,CAAS,uBAAuB,CAAC;IAC1D,MAAM,EAAE,iBAAiB,CAAS,uBAAuB,CAAC;IAC1D,KAAK,EAAE,iBAAiB,CAAQ,sBAAsB,CAAC;CAChD,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAKlF;gEACgE;AAChE,SAAS,iBAAiB,CAAI,WAAmB;IAC9C,OAAO,MAAM,CAAC,WAAW,CAAoC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;GAWG;AACU,QAAA,oBAAoB,GAAG;IACjC,MAAM,EAAE,iBAAiB,CAAS,uBAAuB,CAAC;IAC1D,MAAM,EAAE,iBAAiB,CAAS,uBAAuB,CAAC;IAC1D,KAAK,EAAE,iBAAiB,CAAQ,sBAAsB,CAAC;IACvD,kBAAkB,EAAE,iBAAiB,CAAU,mCAAmC,CAAC;CAC5E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydranium/glsp-client",
3
- "version": "1.0.0-next.327",
3
+ "version": "1.0.0-next.328",
4
4
  "description": "Host-neutral client classes for GLSP heads built on @hydranium/glsp-server, the binder that mounts them in a Theia frontend, a VS Code webview or a plain browser page, the one call that mounts a diagram in a page, and the edge whose labels keep finite bounds without bendpoints.",
5
5
  "keywords": [
6
6
  "diagram",
@@ -59,7 +59,7 @@
59
59
  },
60
60
  "devDependencies": {
61
61
  "@eclipse-glsp/client": "2.7.0",
62
- "@hydranium/protocol": "1.0.0-next.327",
62
+ "@hydranium/protocol": "1.0.0-next.328",
63
63
  "@types/node": "^22.0.0",
64
64
  "inversify": "6.2.2",
65
65
  "reflect-metadata": "0.2.2",
@@ -69,7 +69,7 @@
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@eclipse-glsp/client": "^2.6.0",
72
- "@hydranium/protocol": "1.0.0-next.327",
72
+ "@hydranium/protocol": "1.0.0-next.328",
73
73
  "inversify": "^6.0.0",
74
74
  "snabbdom": "^3.5.1"
75
75
  },
@@ -15,6 +15,8 @@ import {
15
15
  GLSPModelSource,
16
16
  LocalComputedBoundsAction,
17
17
  MessageAction,
18
+ Operation,
19
+ RedoAction,
18
20
  RejectAction,
19
21
  RequestAction,
20
22
  RequestBoundsAction,
@@ -30,9 +32,20 @@ import {
30
32
  SetModelAction,
31
33
  SetTypeHintsAction,
32
34
  StatusAction,
35
+ UndoAction,
33
36
  UpdateModelAction
34
37
  } from '@eclipse-glsp/client';
35
- import { type Clock, type Logger, type Stopwatch, SystemClock, type Tracer } from '@hydranium/protocol';
38
+ import {
39
+ type Clock,
40
+ Deferred,
41
+ type Logger,
42
+ PendingWorkTracker,
43
+ RequestEditsSettledAction,
44
+ type Stopwatch,
45
+ SystemClock,
46
+ TIMED_OUT,
47
+ type Tracer
48
+ } from '@hydranium/protocol';
36
49
  import { inject, injectable, optional, unmanaged } from 'inversify';
37
50
  import { HydraniumClientTypes } from './types';
38
51
 
@@ -90,6 +103,17 @@ export interface HydraniumGlspActionDispatcherOptions {
90
103
  * kind the protocol defines. Adopters with custom kinds either pass
91
104
  * `extraLoggedKinds` / `extraKindPairs` to the constructor (via a
92
105
  * `toDynamicValue` binding) or subclass and override.
106
+ *
107
+ * Where the host asks for it, it also counts the edits it sends that the server
108
+ * has not answered yet, as {@link editsInFlight}, so a page can ask before a
109
+ * reload drops one. The dirty state cannot say this: the server sets it only
110
+ * once it has answered, and an edit that changed nothing is answered with
111
+ * nothing at all. Each edit is followed by a {@link RequestEditsSettledAction},
112
+ * which the server answers after it, and counts until that request or a later
113
+ * one is answered or rejected: the server handles them in order. With no
114
+ * answer, as when the connection is lost, the count stays, so a guard asks
115
+ * rather than loses the edit. An action from the server is not counted, nor
116
+ * is anything on a server that serves no settle request.
93
117
  */
94
118
  @injectable()
95
119
  export class HydraniumGlspActionDispatcher extends GLSPActionDispatcher {
@@ -97,11 +121,27 @@ export class HydraniumGlspActionDispatcher extends GLSPActionDispatcher {
97
121
  @inject(HydraniumClientTypes.Tracer) protected readonly tracer!: Tracer;
98
122
  /** Times each request to its response: the diagram container's {@link Clock}, or a `SystemClock`. */
99
123
  @inject(HydraniumClientTypes.Clock) @optional() protected readonly clock: Clock = new SystemClock();
124
+ /** Whether to count edits in flight; the host asks for it through `createGlspClientModule`. */
125
+ @inject(HydraniumClientTypes.TrackEditsInFlight) @optional() protected readonly trackEditsInFlight: boolean = false;
100
126
 
101
127
  protected readonly loggedKinds: ReadonlySet<string>;
102
128
  protected readonly kindPairs: ReadonlyMap<string, string>;
103
129
  protected readonly kindPairsReverse: ReadonlyMap<string, string>;
104
130
 
131
+ /** Per edit sent, until its {@link RequestEditsSettledAction} or a later one is answered or rejected. */
132
+ protected readonly pendingEdits = new PendingWorkTracker();
133
+ /** The edits in flight by the number of their settle request, in send order. */
134
+ protected readonly editsBySettle = new Map<number, Deferred>();
135
+ protected settlesSent = 0;
136
+ /**
137
+ * How long {@link whenEditsSettled} waits before going on anyway: well past
138
+ * the server's bounded waits on one settle together. Its handling of the
139
+ * edits before has no bound, so a server slower than that is taken as lost.
140
+ */
141
+ protected readonly settleEditsMs: number = 30_000;
142
+ /** The postponed actions a lifted block is dispatching a second time, counted when first sent. */
143
+ protected redispatched: ReadonlySet<Action> | undefined;
144
+
105
145
  protected pairCounter = 0;
106
146
  /** Pending requests keyed by requestId (for actions that carry one). */
107
147
  protected pendingById = new Map<string, { id: number; sinceRequest: Stopwatch }>();
@@ -146,11 +186,87 @@ export class HydraniumGlspActionDispatcher extends GLSPActionDispatcher {
146
186
  }
147
187
  }
148
188
 
189
+ /** How many edits the server has not answered yet; see {@link isEdit}. */
190
+ get editsInFlight(): number {
191
+ return this.pendingEdits.size;
192
+ }
193
+
194
+ /**
195
+ * Resolves to `true` once the edits in flight now have been answered or
196
+ * rejected, or to `false` once {@link settleEditsMs} has passed first. An
197
+ * edit sent while it waits is not waited for. Never rejects. For a save or a
198
+ * switch that must not run ahead of an edit the server has not answered.
199
+ */
200
+ async whenEditsSettled(): Promise<boolean> {
201
+ if (this.pendingEdits.isIdle) {
202
+ return true;
203
+ }
204
+ return (await this.clock.raceTimer(this.pendingEdits.whenSettled(), this.settleEditsMs)) !== TIMED_OUT;
205
+ }
206
+
149
207
  override dispatch(action: Action): Promise<void> {
150
208
  if (this.loggedKinds.has(action.kind)) {
151
209
  this.logAction(action);
152
210
  }
153
- return super.dispatch(action);
211
+ const dispatched = super.dispatch(action);
212
+ this.trackEdit(action);
213
+ return dispatched;
214
+ }
215
+
216
+ protected override handleBlocked(action: Action, predicate: (action: Action) => boolean): Promise<void> {
217
+ if (!predicate(action)) {
218
+ return super.handleBlocked(action, predicate);
219
+ }
220
+ // A lifted block dispatches what it postponed again, within this call.
221
+ this.redispatched = new Set(this.postponedActions.map(postponed => postponed.action));
222
+ try {
223
+ return super.handleBlocked(action, predicate);
224
+ } finally {
225
+ this.redispatched = undefined;
226
+ }
227
+ }
228
+
229
+ /** Whether `action` changes the model on the server: an operation, an undo or a redo. Widen it for an edit kind of your own. */
230
+ protected isEdit(action: Action): boolean {
231
+ return Operation.is(action) || UndoAction.is(action) || RedoAction.is(action);
232
+ }
233
+
234
+ /**
235
+ * Count `action` if it is an edit the client sends, even one whose dispatch
236
+ * failed, since it may have reached the server. One dispatched again counts
237
+ * again, except where a lifted block dispatches what it postponed.
238
+ */
239
+ protected trackEdit(action: Action): void {
240
+ if (
241
+ !this.trackEditsInFlight ||
242
+ ServerAction.is(action) ||
243
+ !this.isEdit(action) ||
244
+ this.redispatched?.has(action) ||
245
+ !this.hasHandler({ kind: RequestEditsSettledAction.KIND })
246
+ ) {
247
+ return;
248
+ }
249
+ const settle = ++this.settlesSent;
250
+ const edit = new Deferred();
251
+ this.editsBySettle.set(settle, edit);
252
+ void this.pendingEdits.track(edit.promise);
253
+ const answered = (): void => this.endEditsThrough(settle);
254
+ this.request(RequestEditsSettledAction.create()).then(answered, answered);
255
+ }
256
+
257
+ /**
258
+ * End every edit up to the `settle`th: the server handles a client's actions
259
+ * in order, so its answer covers the edits before it, one whose own settle
260
+ * was lost included.
261
+ */
262
+ protected endEditsThrough(settle: number): void {
263
+ for (const [sent, edit] of this.editsBySettle) {
264
+ if (sent > settle) {
265
+ break;
266
+ }
267
+ edit.resolve();
268
+ this.editsBySettle.delete(sent);
269
+ }
154
270
  }
155
271
 
156
272
  protected logAction(action: Action): void {
@@ -22,6 +22,7 @@ import {
22
22
  } from '@eclipse-glsp/client';
23
23
  import { type Disposable, DisposableCollection, type Logger } from '@hydranium/protocol';
24
24
  import { Container, ContainerModule } from 'inversify';
25
+ import { HydraniumGlspActionDispatcher } from './action-dispatcher';
25
26
  import { type DiagramLoadOutcome, HydraniumDiagramLoader } from './diagram-loader';
26
27
  import type { HydraniumGlspClient } from './glsp-client';
27
28
  import { createGlspClientModule } from './glsp-client-module';
@@ -59,6 +60,23 @@ export interface GlspDiagramMount extends Disposable {
59
60
  * the caller learns of it; when the failure is not `surfaced`, no overlay
60
61
  * shows it and the caller is the only report left. */
61
62
  readonly loadOutcome: DiagramLoadOutcome;
63
+ /**
64
+ * How many edits the server has not answered yet, as
65
+ * {@link HydraniumGlspActionDispatcher.editsInFlight} counts them, for a
66
+ * page that asks before a reload drops one: the diagram's dirty state is
67
+ * set only once the server has answered. None after a failed load, or
68
+ * when the dispatcher is not the framework's. None once disposed either:
69
+ * the server drops the edits the ended session still had queued, though
70
+ * one it was handling still lands.
71
+ */
72
+ readonly editsInFlight: number;
73
+ /**
74
+ * Resolves to `true` once the edits in flight now have been answered or
75
+ * rejected, or to `false` once the dispatcher's bound has passed first, as
76
+ * {@link HydraniumGlspActionDispatcher.whenEditsSettled} does. `true` at
77
+ * once wherever {@link editsInFlight} reads none.
78
+ */
79
+ whenEditsSettled(): Promise<boolean>;
62
80
  /** Ends the client session on the server and stops watching the element;
63
81
  * what is drawn in it is left to the host to remove. */
64
82
  dispose(): void;
@@ -130,7 +148,7 @@ export async function mountGlspDiagram(options: GlspDiagramMountOptions): Promis
130
148
  // After the standalone modules, since every class the binder binds replaces
131
149
  // a token those modules bind.
132
150
  const hydraniumModule = new ContainerModule((bind, unbind, isBound, rebind) => {
133
- createGlspClientModule({ bind, unbind, isBound, rebind }, { logger: options.logger });
151
+ createGlspClientModule({ bind, unbind, isBound, rebind }, { logger: options.logger, trackEditsInFlight: true });
134
152
  });
135
153
  const container = options.initializeDiagramContainer(
136
154
  new Container(),
@@ -148,7 +166,21 @@ export async function mountGlspDiagram(options: GlspDiagramMountOptions): Promis
148
166
  // Pushed first, so it runs last: `unbindAll` reaches `disposeClientSession`
149
167
  // through the model source's pre-destroy hook, after the listeners are gone.
150
168
  toDispose.push({ dispose: () => container.unbindAll() });
151
- const dispose = (): void => toDispose.dispose();
169
+ // Set once the mount loaded with the framework's dispatcher, until disposed.
170
+ let editsDispatcher: HydraniumGlspActionDispatcher | undefined;
171
+ const dispose = (): void => {
172
+ editsDispatcher = undefined;
173
+ toDispose.dispose();
174
+ };
175
+ const mountWith = (loadOutcome: DiagramLoadOutcome): GlspDiagramMount => ({
176
+ container,
177
+ loadOutcome,
178
+ get editsInFlight() {
179
+ return editsDispatcher?.editsInFlight ?? 0;
180
+ },
181
+ whenEditsSettled: () => editsDispatcher?.whenEditsSettled() ?? Promise.resolve(true),
182
+ dispose
183
+ });
152
184
  try {
153
185
  const loader = container.get(DiagramLoader);
154
186
  await loader.load();
@@ -157,7 +189,7 @@ export async function mountGlspDiagram(options: GlspDiagramMountOptions): Promis
157
189
  // A model that never arrived has no use for the accommodations, and when
158
190
  // the dispatcher is what failed, every later dispatch rejects too.
159
191
  if (loadOutcome.status === 'failed') {
160
- return { container, loadOutcome, dispose };
192
+ return mountWith(loadOutcome);
161
193
  }
162
194
  const dispatcher = container.get<GLSPActionDispatcher>(TYPES.IActionDispatcher);
163
195
  // The bounds the fit measures come from the hidden rendering pass inside
@@ -175,7 +207,10 @@ export async function mountGlspDiagram(options: GlspDiagramMountOptions): Promis
175
207
  trackCanvasBounds(live, dispatcher, container.get(EditorContextService), container.get<Logger>(HydraniumClientTypes.Logger))
176
208
  );
177
209
  toDispose.push(enableTouchDragging(live));
178
- return { container, loadOutcome, dispose };
210
+ if (dispatcher instanceof HydraniumGlspActionDispatcher) {
211
+ editsDispatcher = dispatcher;
212
+ }
213
+ return mountWith(loadOutcome);
179
214
  } catch (err: unknown) {
180
215
  // The caller gets no mount to dispose, so the session would outlive it.
181
216
  toDispose.dispose();
@@ -31,6 +31,11 @@ export interface GlspClientModuleOptions {
31
31
  * binding the host made. Absent, the token keeps the host's own binding, or
32
32
  * gets a `ConsoleLogger` when it has none. */
33
33
  readonly logger?: Logger;
34
+ /** Count the diagram edits the server has not answered yet, as
35
+ * `HydraniumGlspActionDispatcher.editsInFlight`, for a host that reads the
36
+ * count. Off by default: each edit then costs an extra request and its
37
+ * answer. */
38
+ readonly trackEditsInFlight?: boolean;
34
39
  }
35
40
 
36
41
  /**
@@ -69,6 +74,11 @@ export function createGlspClientModule(context: BindingContext, options: GlspCli
69
74
  })
70
75
  .inSingletonScope();
71
76
  }
77
+ if (options.trackEditsInFlight !== undefined) {
78
+ (isBound(HydraniumClientTypes.TrackEditsInFlight) ? rebind : bind)(HydraniumClientTypes.TrackEditsInFlight).toConstantValue(
79
+ options.trackEditsInFlight
80
+ );
81
+ }
72
82
  bind(HydraniumGlspActionDispatcher).toSelf().inSingletonScope();
73
83
  rebind(GLSPActionDispatcher).toService(HydraniumGlspActionDispatcher);
74
84
  rebind(DiagramLoader).to(HydraniumDiagramLoader).inSingletonScope();
package/src/types.ts CHANGED
@@ -25,10 +25,12 @@ function serviceIdentifier<T>(description: string): interfaces.ServiceIdentifier
25
25
  * `Logger` and `Tracer` are required, so a host that binds neither fails at
26
26
  * resolution rather than running silent; `createGlspClientModule` binds
27
27
  * defaults for a host that passes none. `Clock` is optional: the classes fall
28
- * back to a `SystemClock`.
28
+ * back to a `SystemClock`. `TrackEditsInFlight` is optional too, and off
29
+ * unbound: `createGlspClientModule` binds it for a host that asks.
29
30
  */
30
31
  export const HydraniumClientTypes = {
31
32
  Logger: serviceIdentifier<Logger>('HydraniumClientLogger'),
32
33
  Tracer: serviceIdentifier<Tracer>('HydraniumClientTracer'),
33
- Clock: serviceIdentifier<Clock>('HydraniumClientClock')
34
+ Clock: serviceIdentifier<Clock>('HydraniumClientClock'),
35
+ TrackEditsInFlight: serviceIdentifier<boolean>('HydraniumClientTrackEditsInFlight')
34
36
  } as const;