@hydranium/protocol 1.0.0-next.227 → 1.0.0-next.229

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.
@@ -222,8 +222,9 @@ export type DataSessionFactory<TTransfer extends TransferElement, TServer extend
222
222
  * re-opens and re-watches what it had open, tells the client of their dirty
223
223
  * state where it changed, and reports the documents whose unsaved edits did
224
224
  * not survive; see {@link restore}. The connection does this at
225
- * once for a session with documents open, and any session's next call does it
226
- * too.
225
+ * once for a session with documents open, and again once any later connection
226
+ * is ready, so a reconnect that failed is not left to the session's own next
227
+ * call; any session's next call does it too.
227
228
  *
228
229
  * Generic over the transfer root so this file names no grammar.
229
230
  *
@@ -350,6 +351,9 @@ export class DataSession<
350
351
  this.registration = this.register(server, reconnected);
351
352
  }
352
353
  await this.registration;
354
+ // And after the registration: a call waiting on it has not reached the
355
+ // wire, and sent now it would land after the session's close.
356
+ this.assertLive();
353
357
  return server;
354
358
  }
355
359
 
@@ -635,8 +639,9 @@ export class DataSession<
635
639
  /**
636
640
  * Register again and restore now, after the connection dropped, instead of
637
641
  * on the next call. A no-op for a session with nothing open, which the next
638
- * call restores anyway. A failure is left to that next call, which meets it
639
- * again.
642
+ * call restores anyway, and for one already registered on the current
643
+ * connection. A failure is retried on the connection's next ready
644
+ * generation; a call before then meets it again.
640
645
  */
641
646
  reconnect(): void {
642
647
  if (!this.disposed && this.openUris.size > 0) {
@@ -229,6 +229,8 @@ export class RpcConnection<TServer extends ReadyServer, TClient extends object>
229
229
  return;
230
230
  }
231
231
  await generation.server.waitForReady();
232
+ // Before `onReady`, so a failing restore reports a failure alone.
233
+ this.generationReady(generation);
232
234
  this.lifecycle.onReady?.();
233
235
  } catch (error: unknown) {
234
236
  // A dropped generation's request fails with its transport, which says
@@ -247,6 +249,17 @@ export class RpcConnection<TServer extends ReadyServer, TClient extends object>
247
249
  }
248
250
  }
249
251
 
252
+ /**
253
+ * Called once `generation` has passed its readiness gate, whichever request
254
+ * brought it up. A generation can replace one that failed at readiness
255
+ * without {@link dropGeneration}, so this, not a drop, is where state kept
256
+ * on the server is put back. It runs inside the readiness gate, so a throw
257
+ * from an override fails the generation as a refused gate would.
258
+ */
259
+ protected generationReady(_generation: RpcConnectionGeneration<TServer>): void {
260
+ // Nothing to put back at this layer.
261
+ }
262
+
250
263
  /**
251
264
  * Discard the current generation, disposing its connection if it opened.
252
265
  * The next {@link connected} builds a fresh one.
@@ -26,6 +26,7 @@
26
26
  export * from './primitives';
27
27
 
28
28
  export { DOCUMENT_NOT_OPEN, DUPLICATE_CLIENT_ID, SESSION_CLOSED, STALE_BASE_VERSION_UPDATE } from '../errors';
29
+ export { DATA_CONNECTION_SESSION_RESTORE_FAILED, DATA_CONNECTION_WATCH_RESTORE_FAILED } from '../client/data-connection';
29
30
  export { DATA_SERVER_CONNECT_FAILED, DATA_SERVER_NOT_READY } from '../client/rpc-connection';
30
31
  export { DATA_SESSION_ANSWER_WITHOUT_MODEL, DATA_SESSION_RESTORE_FAILED, DATA_SESSION_UNSAVED_LOST } from '../client/data-session';
31
32
  export {
@@ -43,6 +43,7 @@ import type {
43
43
  TransferDocumentsBuiltEvent,
44
44
  TransferDocumentUpdatedEvent
45
45
  } from '../data/events';
46
+ import type { Logger } from '../logger';
46
47
  import type { ResolvedMessage } from '../messages/primitives';
47
48
  import type { RpcProxyLifecycle } from '../rpc/create-rpc-proxy';
48
49
  import type { Project } from '../project';
@@ -61,6 +62,8 @@ export interface FakeDataPortOptions {
61
62
  * which the consumer surfaces through {@link FakeDataPort.reported}.
62
63
  */
63
64
  connect(): MessageConnection | Promise<MessageConnection>;
65
+ /** The port's {@link DataPort.logger}. */
66
+ logger?: Logger;
64
67
  }
65
68
 
66
69
  /** A {@link DataPort} that records what passed through it. */
@@ -105,6 +108,7 @@ export function makeFakeDataPort(options: FakeDataPortOptions): FakeDataPort {
105
108
  return {
106
109
  connections,
107
110
  reported,
111
+ logger: options.logger,
108
112
  onDispose: disposeEmitter.event,
109
113
  async connect(): Promise<MessageConnection> {
110
114
  const connection = await options.connect();