Massive speed up during invitation creation at the expense of reliability. Document method for creating a reliability manager of some sort
This commit is contained in:
52
readme.md
52
readme.md
@@ -155,3 +155,55 @@ xo-tui
|
|||||||
# If not globally installed
|
# If not globally installed
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
### Track invitation sync-server connectivity without blocking the UI
|
||||||
|
|
||||||
|
Each `Invitation` currently owns a `SyncServer` instance for its invitation
|
||||||
|
identifier. The invitation uses that instance to open an SSE connection, fetch
|
||||||
|
remote state, and publish local changes. Publish requests are intentionally
|
||||||
|
fire-and-forget so that invitation actions and the TUI stay responsive when the
|
||||||
|
sync server is slow or unavailable.
|
||||||
|
|
||||||
|
The tradeoff is that failed background requests and SSE connection changes are
|
||||||
|
not represented as application state. `SyncServer` already emits `connected`,
|
||||||
|
`disconnected`, and `error` events, and `Invitation` emits errors from failed
|
||||||
|
publishes, but there is no app-level owner that aggregates those events. The UI
|
||||||
|
therefore cannot reliably tell the user that an invitation may only be updated
|
||||||
|
locally and is not currently syncing with other participants.
|
||||||
|
|
||||||
|
Implement an app-owned `InvitationConnectivityService` (or similarly named
|
||||||
|
invitation watcher) with the following responsibilities:
|
||||||
|
|
||||||
|
- Register an invitation and its `SyncServer` when `AppService` creates or loads
|
||||||
|
it, and unregister it when the invitation is removed or stopped.
|
||||||
|
- Listen for each sync server's `connected`, `disconnected`, and `error` events,
|
||||||
|
plus invitation publish failures.
|
||||||
|
- Track connectivity separately from the invitation's business status
|
||||||
|
(`actionable`, `signed`, `ready`, and so on). Suggested transport states are
|
||||||
|
`connecting`, `online`, `offline`, and `degraded`, with the last error and
|
||||||
|
last successful connection timestamp available for diagnostics.
|
||||||
|
- Expose both per-invitation state and an aggregate app-level state such as
|
||||||
|
"one or more invitations are not syncing".
|
||||||
|
- Emit normalized connectivity-change events that the CLI can log and the TUI
|
||||||
|
can subscribe to without awaiting sync-server requests.
|
||||||
|
|
||||||
|
Keep local persistence and local invitation actions independent from remote
|
||||||
|
sync health. Failed sync attempts should not freeze normal wallet interaction.
|
||||||
|
The service should provide a retry path, or observe retry events from the SSE
|
||||||
|
client, and clear the warning after connectivity recovers. If publish retries
|
||||||
|
are added, make the retry policy explicit and preserve commit idempotency.
|
||||||
|
|
||||||
|
For UI integration, inject a small notification function or subscribe at the
|
||||||
|
app-context layer rather than having invitation instances render UI directly.
|
||||||
|
The first version can show an error dialog when the aggregate state becomes
|
||||||
|
unhealthy. A less intrusive version can expose the same state as a warning icon
|
||||||
|
or message in the TUI status bar and reserve dialogs for prolonged failures or
|
||||||
|
explicit user actions.
|
||||||
|
|
||||||
|
While making this change, consolidate invitation startup ownership. Startup is
|
||||||
|
currently triggered during `Invitation.create()` and again by
|
||||||
|
`AppService.createInvitation()`. The watcher should have one clear lifecycle
|
||||||
|
point so connections, listeners, retries, and cleanup are registered exactly
|
||||||
|
once.
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ export class AppService extends EventEmitter<AppEventMap> {
|
|||||||
|
|
||||||
// Attach listeners before SSE connects so updates are not missed.
|
// Attach listeners before SSE connects so updates are not missed.
|
||||||
await this.addInvitation(invitationInstance);
|
await this.addInvitation(invitationInstance);
|
||||||
await invitationInstance.start();
|
invitationInstance.start();
|
||||||
|
|
||||||
return invitationInstance;
|
return invitationInstance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,12 +224,9 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
private async publishInvitation(
|
private async publishInvitation(
|
||||||
invitation: XOInvitation = this.data,
|
invitation: XOInvitation = this.data,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
this.syncServer.publishInvitation(invitation).catch((error) => {
|
||||||
await this.syncServer.publishInvitation(invitation);
|
this.emit("error", error instanceof Error ? error : new Error(String(error)));
|
||||||
} catch (err) {
|
});
|
||||||
// Emit the error event. We might want to throw? but we need a better way of handling errors in the invitation system because we need the invitation to successfully initialize.
|
|
||||||
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -374,9 +371,13 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
* Update the status of the invitation and emit the new single-word status.
|
* Update the status of the invitation and emit the new single-word status.
|
||||||
*/
|
*/
|
||||||
private async updateStatus(): Promise<void> {
|
private async updateStatus(): Promise<void> {
|
||||||
const status = await this.computeStatus();
|
this.computeStatus().then(status => {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.emit("invitation-status-changed", status);
|
this.emit("invitation-status-changed", status);
|
||||||
|
}).catch((error) => {
|
||||||
|
this.status = `error (${error instanceof Error ? error.message : String(error)})`;
|
||||||
|
this.emit("error", error instanceof Error ? error : new Error(String(error)));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user