@rljson/server 0.0.4 → 0.0.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.
- package/README.architecture.md +1352 -0
- package/README.blog.md +9 -1
- package/README.contributors.md +47 -13
- package/README.md +78 -11
- package/README.public.md +600 -7
- package/README.trouble.md +50 -0
- package/dist/README.architecture.md +1352 -0
- package/dist/README.blog.md +9 -1
- package/dist/README.contributors.md +47 -13
- package/dist/README.md +78 -11
- package/dist/README.public.md +600 -7
- package/dist/README.trouble.md +50 -0
- package/dist/client.d.ts +75 -3
- package/dist/index.d.ts +6 -0
- package/dist/logger.d.ts +115 -0
- package/dist/server.d.ts +148 -7
- package/dist/server.js +858 -118
- package/dist/socket-bundle.d.ts +16 -0
- package/package.json +17 -17
package/dist/README.trouble.md
CHANGED
|
@@ -11,6 +11,7 @@ found in the LICENSE file in the root of this package.
|
|
|
11
11
|
## Table of contents <!-- omit in toc -->
|
|
12
12
|
|
|
13
13
|
- [Vscode Windows: Debugging is not working](#vscode-windows-debugging-is-not-working)
|
|
14
|
+
- [Test Isolation: Socket.IO event listener accumulation](#test-isolation-socketio-event-listener-accumulation)
|
|
14
15
|
|
|
15
16
|
## Vscode Windows: Debugging is not working
|
|
16
17
|
|
|
@@ -21,3 +22,52 @@ in the VS Code Vitest extension (v1.14.4), which prevents test debugging from
|
|
|
21
22
|
working: <https://github.com/vitest-dev/vscode/issues/548> Please check from
|
|
22
23
|
time to time if the issue has been fixed and remove this note once it is
|
|
23
24
|
resolved.
|
|
25
|
+
|
|
26
|
+
## Test Isolation: Socket.IO event listener accumulation
|
|
27
|
+
|
|
28
|
+
Date: 2025-01-28
|
|
29
|
+
|
|
30
|
+
**Problem:**
|
|
31
|
+
|
|
32
|
+
When running multiple tests that use Socket.IO connections, tests pass individually but fail when run together. This is caused by event listeners from previous tests remaining active on persistent socket instances.
|
|
33
|
+
|
|
34
|
+
**Symptoms:**
|
|
35
|
+
|
|
36
|
+
- Individual tests pass: ✅
|
|
37
|
+
- All tests together fail: ❌
|
|
38
|
+
- Error messages like "received 0 instead of expected number of nodes"
|
|
39
|
+
- Unexpected behavior when sockets receive messages from previous tests
|
|
40
|
+
|
|
41
|
+
**Root Cause:**
|
|
42
|
+
|
|
43
|
+
Socket.IO sockets persist across tests in the `beforeAll` setup. When `SocketIoBridge` instances are created in `beforeEach`, old event listeners accumulate on the underlying sockets, causing interference between tests.
|
|
44
|
+
|
|
45
|
+
**Solution:**
|
|
46
|
+
|
|
47
|
+
Clear all event listeners in `beforeEach` before creating new bridges:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
beforeEach(async () => {
|
|
51
|
+
// Remove all event listeners from previous test to prevent interference
|
|
52
|
+
serverSockets.forEach((socket) => socket.removeAllListeners());
|
|
53
|
+
clientSockets.forEach((socket) => socket.removeAllListeners());
|
|
54
|
+
|
|
55
|
+
// Now proceed with test setup...
|
|
56
|
+
server = new Server(route, serverIo, serverBs);
|
|
57
|
+
await server.init();
|
|
58
|
+
// ... rest of setup
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Why This Works:**
|
|
63
|
+
|
|
64
|
+
- `removeAllListeners()` clears accumulated event handlers
|
|
65
|
+
- Each test starts with clean sockets
|
|
66
|
+
- No interference from previous test's `SocketIoBridge` instances
|
|
67
|
+
- Maintains socket connections established in `beforeAll`
|
|
68
|
+
|
|
69
|
+
**Alternative Approaches Considered:**
|
|
70
|
+
|
|
71
|
+
1. ❌ `tearDown()` in `afterEach`: Caused hook timeouts
|
|
72
|
+
2. ❌ Creating new socket connections per test: Too slow, defeats purpose of `beforeAll`
|
|
73
|
+
3. ✅ Clear listeners while reusing connections: Fast and reliable
|
package/dist/client.d.ts
CHANGED
|
@@ -1,21 +1,59 @@
|
|
|
1
1
|
import { Bs } from '@rljson/bs';
|
|
2
|
-
import {
|
|
2
|
+
import { Connector, Db } from '@rljson/db';
|
|
3
|
+
import { Io, IoMulti } from '@rljson/io';
|
|
4
|
+
import { ClientId, Route, SyncConfig } from '@rljson/rljson';
|
|
3
5
|
import { BaseNode } from './base-node.ts';
|
|
6
|
+
import { ServerLogger } from './logger.ts';
|
|
7
|
+
import { SocketLike } from './socket-bundle.ts';
|
|
8
|
+
/**
|
|
9
|
+
* Options for the Client constructor.
|
|
10
|
+
*/
|
|
11
|
+
export interface ClientOptions {
|
|
12
|
+
/** Logger instance for monitoring (defaults to NoopLogger). */
|
|
13
|
+
logger?: ServerLogger;
|
|
14
|
+
/**
|
|
15
|
+
* Sync protocol configuration. When provided, the Connector created
|
|
16
|
+
* by the client will use enriched payloads (sequence numbers, causal
|
|
17
|
+
* ordering, ACK support, client identity).
|
|
18
|
+
*/
|
|
19
|
+
syncConfig?: SyncConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Stable client identity. When provided, this identity is passed
|
|
22
|
+
* to the Connector. When omitted but `syncConfig.includeClientIdentity`
|
|
23
|
+
* is true, a new identity is auto-generated.
|
|
24
|
+
*/
|
|
25
|
+
clientIdentity?: ClientId;
|
|
26
|
+
/**
|
|
27
|
+
* Timeout in milliseconds for peer initialization during init().
|
|
28
|
+
* If an Io or Bs peer does not respond within this window, init()
|
|
29
|
+
* rejects. Defaults to 30 000 (30 s). Set to 0 to disable the timeout.
|
|
30
|
+
*/
|
|
31
|
+
peerInitTimeoutMs?: number;
|
|
32
|
+
}
|
|
4
33
|
export declare class Client extends BaseNode {
|
|
5
34
|
private _socketToServer;
|
|
6
35
|
protected _localIo: Io;
|
|
7
36
|
protected _localBs: Bs;
|
|
37
|
+
private _route?;
|
|
8
38
|
private _ioMultiIos;
|
|
9
39
|
private _ioMulti?;
|
|
10
40
|
private _bsMultiBss;
|
|
11
41
|
private _bsMulti?;
|
|
42
|
+
private _db?;
|
|
43
|
+
private _connector?;
|
|
44
|
+
private _logger;
|
|
45
|
+
private _syncConfig?;
|
|
46
|
+
private _clientIdentity?;
|
|
47
|
+
private _peerInitTimeoutMs;
|
|
12
48
|
/**
|
|
13
49
|
* Creates a Client instance
|
|
14
|
-
* @param _socketToServer - Socket to connect to server
|
|
50
|
+
* @param _socketToServer - Socket or namespace bundle to connect to server
|
|
15
51
|
* @param _localIo - Local Io for local storage
|
|
16
52
|
* @param _localBs - Local Bs for local blob storage
|
|
53
|
+
* @param _route - Optional route for automatic Db and Connector creation
|
|
54
|
+
* @param options - Optional configuration including logger for monitoring
|
|
17
55
|
*/
|
|
18
|
-
constructor(_socketToServer:
|
|
56
|
+
constructor(_socketToServer: SocketLike, _localIo: Io, _localBs: Bs, _route?: Route | undefined, options?: ClientOptions);
|
|
19
57
|
/**
|
|
20
58
|
* Initializes Io and Bs multis and their peer bridges.
|
|
21
59
|
* @returns The initialized Io implementation.
|
|
@@ -37,6 +75,27 @@ export declare class Client extends BaseNode {
|
|
|
37
75
|
* Returns the Bs implementation.
|
|
38
76
|
*/
|
|
39
77
|
get bs(): Bs | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Returns the Db instance (available when route was provided).
|
|
80
|
+
*/
|
|
81
|
+
get db(): Db | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Returns the Connector instance (available when route was provided).
|
|
84
|
+
*/
|
|
85
|
+
get connector(): Connector | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* Returns the route (if provided).
|
|
88
|
+
*/
|
|
89
|
+
get route(): Route | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Returns the logger instance.
|
|
92
|
+
*/
|
|
93
|
+
get logger(): ServerLogger;
|
|
94
|
+
/**
|
|
95
|
+
* Creates Db and Connector from the route and IoMulti.
|
|
96
|
+
* Called during init() when a route was provided.
|
|
97
|
+
*/
|
|
98
|
+
private _setupDbAndConnector;
|
|
40
99
|
/**
|
|
41
100
|
* Builds the Io multi with local and peer layers.
|
|
42
101
|
*/
|
|
@@ -47,10 +106,23 @@ export declare class Client extends BaseNode {
|
|
|
47
106
|
private _setupBs;
|
|
48
107
|
/**
|
|
49
108
|
* Creates and initializes a downstream Io peer.
|
|
109
|
+
* @param socket - Downstream socket to the server Io namespace.
|
|
50
110
|
*/
|
|
51
111
|
private _createIoPeer;
|
|
52
112
|
/**
|
|
53
113
|
* Creates and initializes a downstream Bs peer.
|
|
114
|
+
* @param socket - Downstream socket to the server Bs namespace.
|
|
54
115
|
*/
|
|
55
116
|
private _createBsPeer;
|
|
117
|
+
/**
|
|
118
|
+
* Returns the configured peer init timeout in milliseconds.
|
|
119
|
+
*/
|
|
120
|
+
get peerInitTimeoutMs(): number;
|
|
121
|
+
/**
|
|
122
|
+
* Races a promise against a timeout. Resolves/rejects with the original
|
|
123
|
+
* promise outcome if it settles first, or rejects with a timeout error.
|
|
124
|
+
* @param promise - The promise to race.
|
|
125
|
+
* @param label - Human-readable label for timeout error messages.
|
|
126
|
+
*/
|
|
127
|
+
private _withTimeout;
|
|
56
128
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export { Client } from './client.ts';
|
|
2
|
+
export type { ClientOptions } from './client.ts';
|
|
3
|
+
export { BufferedLogger, ConsoleLogger, FilteredLogger, NoopLogger, noopLogger, } from './logger.ts';
|
|
4
|
+
export type { LogEntry, ServerLogger } from './logger.ts';
|
|
2
5
|
export { Server } from './server.ts';
|
|
6
|
+
export type { ServerOptions } from './server.ts';
|
|
3
7
|
export { SocketIoBridge } from './socket-io-bridge.ts';
|
|
8
|
+
export type { AckPayload, ConnectorPayload, GapFillRequest, GapFillResponse, SyncConfig, SyncEventNames, } from '@rljson/rljson';
|
|
9
|
+
export { syncEvents } from '@rljson/rljson';
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger interface for monitoring Client/Server lifecycle, errors,
|
|
3
|
+
* and network traffic. Implementations can be injected via options.
|
|
4
|
+
*
|
|
5
|
+
* Use `NoopLogger` (default) in production for zero overhead.
|
|
6
|
+
* Use `ConsoleLogger` or `BufferedLogger` for development/testing.
|
|
7
|
+
*/
|
|
8
|
+
export interface ServerLogger {
|
|
9
|
+
/**
|
|
10
|
+
* Informational messages (lifecycle events, state changes).
|
|
11
|
+
* @param source - Component identifier (e.g., 'Server', 'Client.Io')
|
|
12
|
+
* @param message - Human-readable message
|
|
13
|
+
* @param data - Optional structured context
|
|
14
|
+
*/
|
|
15
|
+
info(source: string, message: string, data?: Record<string, unknown>): void;
|
|
16
|
+
/**
|
|
17
|
+
* Warning messages (suppressed duplicates, loop prevention).
|
|
18
|
+
* @param source - Component identifier
|
|
19
|
+
* @param message - Human-readable message
|
|
20
|
+
* @param data - Optional structured context
|
|
21
|
+
*/
|
|
22
|
+
warn(source: string, message: string, data?: Record<string, unknown>): void;
|
|
23
|
+
/**
|
|
24
|
+
* Error messages (failures during init, multicast, peer creation).
|
|
25
|
+
* @param source - Component identifier
|
|
26
|
+
* @param message - Human-readable message
|
|
27
|
+
* @param error - The caught error or unknown value
|
|
28
|
+
* @param data - Optional structured context
|
|
29
|
+
*/
|
|
30
|
+
error(source: string, message: string, error?: unknown, data?: Record<string, unknown>): void;
|
|
31
|
+
/**
|
|
32
|
+
* Network traffic messages (socket emit/on events).
|
|
33
|
+
* @param direction - 'in' for received, 'out' for sent
|
|
34
|
+
* @param source - Component identifier
|
|
35
|
+
* @param event - Socket event name
|
|
36
|
+
* @param data - Optional structured context (ref, clientId, etc.)
|
|
37
|
+
*/
|
|
38
|
+
traffic(direction: 'in' | 'out', source: string, event: string, data?: Record<string, unknown>): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* No-op logger. All methods are empty. Zero overhead in production.
|
|
42
|
+
* This is the default logger when none is provided.
|
|
43
|
+
*/
|
|
44
|
+
export declare class NoopLogger implements ServerLogger {
|
|
45
|
+
info(..._args: Parameters<ServerLogger['info']>): void;
|
|
46
|
+
warn(..._args: Parameters<ServerLogger['warn']>): void;
|
|
47
|
+
error(..._args: Parameters<ServerLogger['error']>): void;
|
|
48
|
+
traffic(..._args: Parameters<ServerLogger['traffic']>): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Logs all events to console. Useful for development and debugging.
|
|
52
|
+
* Data is serialized inline as compact JSON for single-line output.
|
|
53
|
+
*/
|
|
54
|
+
export declare class ConsoleLogger implements ServerLogger {
|
|
55
|
+
private _fmt;
|
|
56
|
+
info(source: string, message: string, data?: Record<string, unknown>): void;
|
|
57
|
+
warn(source: string, message: string, data?: Record<string, unknown>): void;
|
|
58
|
+
error(source: string, message: string, error?: unknown, data?: Record<string, unknown>): void;
|
|
59
|
+
traffic(direction: 'in' | 'out', source: string, event: string, data?: Record<string, unknown>): void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Log entry stored by BufferedLogger.
|
|
63
|
+
*/
|
|
64
|
+
export interface LogEntry {
|
|
65
|
+
level: 'info' | 'warn' | 'error' | 'traffic';
|
|
66
|
+
source: string;
|
|
67
|
+
message: string;
|
|
68
|
+
error?: unknown;
|
|
69
|
+
data?: Record<string, unknown>;
|
|
70
|
+
direction?: 'in' | 'out';
|
|
71
|
+
event?: string;
|
|
72
|
+
timestamp: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Stores log entries in memory. Useful for test assertions.
|
|
76
|
+
*/
|
|
77
|
+
export declare class BufferedLogger implements ServerLogger {
|
|
78
|
+
readonly entries: LogEntry[];
|
|
79
|
+
info(source: string, message: string, data?: Record<string, unknown>): void;
|
|
80
|
+
warn(source: string, message: string, data?: Record<string, unknown>): void;
|
|
81
|
+
error(source: string, message: string, error?: unknown, data?: Record<string, unknown>): void;
|
|
82
|
+
traffic(direction: 'in' | 'out', source: string, event: string, data?: Record<string, unknown>): void;
|
|
83
|
+
/**
|
|
84
|
+
* Returns entries filtered by level.
|
|
85
|
+
* @param level - The log level to filter by
|
|
86
|
+
*/
|
|
87
|
+
byLevel(level: LogEntry['level']): LogEntry[];
|
|
88
|
+
/**
|
|
89
|
+
* Returns entries filtered by source (substring match).
|
|
90
|
+
* @param source - The source substring to match
|
|
91
|
+
*/
|
|
92
|
+
bySource(source: string): LogEntry[];
|
|
93
|
+
/**
|
|
94
|
+
* Clears all stored entries.
|
|
95
|
+
*/
|
|
96
|
+
clear(): void;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Wraps another logger and filters entries by level and/or source.
|
|
100
|
+
*/
|
|
101
|
+
export declare class FilteredLogger implements ServerLogger {
|
|
102
|
+
private _inner;
|
|
103
|
+
private _filter;
|
|
104
|
+
constructor(_inner: ServerLogger, _filter?: {
|
|
105
|
+
levels?: Array<'info' | 'warn' | 'error' | 'traffic'>;
|
|
106
|
+
sources?: string[];
|
|
107
|
+
});
|
|
108
|
+
private _shouldLog;
|
|
109
|
+
info(source: string, message: string, data?: Record<string, unknown>): void;
|
|
110
|
+
warn(source: string, message: string, data?: Record<string, unknown>): void;
|
|
111
|
+
error(source: string, message: string, error?: unknown, data?: Record<string, unknown>): void;
|
|
112
|
+
traffic(direction: 'in' | 'out', source: string, event: string, data?: Record<string, unknown>): void;
|
|
113
|
+
}
|
|
114
|
+
/** Shared no-op instance to avoid repeated allocations. */
|
|
115
|
+
export declare const noopLogger: ServerLogger;
|
package/dist/server.d.ts
CHANGED
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
import { Bs, BsPeer } from '@rljson/bs';
|
|
2
2
|
import { Io, IoPeer, Socket } from '@rljson/io';
|
|
3
|
-
import { Route } from '@rljson/rljson';
|
|
3
|
+
import { ConnectorPayload, Route, SyncConfig, SyncEventNames } from '@rljson/rljson';
|
|
4
4
|
import { BaseNode } from './base-node.ts';
|
|
5
|
+
import { ServerLogger } from './logger.ts';
|
|
6
|
+
import { SocketLike } from './socket-bundle.ts';
|
|
5
7
|
export type SocketWithClientId = Socket & {
|
|
6
8
|
__clientId?: string;
|
|
7
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Options for the Server constructor.
|
|
12
|
+
*/
|
|
13
|
+
export interface ServerOptions {
|
|
14
|
+
/** Logger instance for monitoring (defaults to NoopLogger). */
|
|
15
|
+
logger?: ServerLogger;
|
|
16
|
+
/**
|
|
17
|
+
* Interval in milliseconds for evicting stale multicast ref entries.
|
|
18
|
+
* Uses a two-generation sweep: refs older than two intervals are discarded.
|
|
19
|
+
* Defaults to 60 000 (60 s). Set to 0 to disable automatic eviction.
|
|
20
|
+
*/
|
|
21
|
+
refEvictionIntervalMs?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Timeout in milliseconds for peer initialization during addSocket().
|
|
24
|
+
* If a peer does not respond within this window, addSocket() rejects.
|
|
25
|
+
* Defaults to 30 000 (30 s). Set to 0 to disable the timeout.
|
|
26
|
+
*/
|
|
27
|
+
peerInitTimeoutMs?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Sync protocol configuration. When provided, the server activates
|
|
30
|
+
* ACK aggregation, gap-fill response, and enriched payload forwarding.
|
|
31
|
+
*/
|
|
32
|
+
syncConfig?: SyncConfig;
|
|
33
|
+
/**
|
|
34
|
+
* Maximum number of recent payloads to retain in the ref log
|
|
35
|
+
* for gap-fill responses. Defaults to 1000.
|
|
36
|
+
*/
|
|
37
|
+
refLogSize?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Timeout in milliseconds for collecting individual client ACKs
|
|
40
|
+
* before emitting the aggregated AckPayload back to the sender.
|
|
41
|
+
* Defaults to the SyncConfig's ackTimeoutMs (or 10 000 ms).
|
|
42
|
+
*/
|
|
43
|
+
ackTimeoutMs?: number;
|
|
44
|
+
}
|
|
8
45
|
export declare class Server extends BaseNode {
|
|
9
46
|
private _route;
|
|
10
47
|
protected _localIo: Io;
|
|
@@ -16,10 +53,23 @@ export declare class Server extends BaseNode {
|
|
|
16
53
|
private _bss;
|
|
17
54
|
private _bsMulti;
|
|
18
55
|
private _bsServer;
|
|
19
|
-
private
|
|
56
|
+
private _multicastedRefsCurrent;
|
|
57
|
+
private _multicastedRefsPrevious;
|
|
58
|
+
private _refEvictionTimer?;
|
|
20
59
|
private _refreshPromise?;
|
|
21
60
|
private _pendingSockets;
|
|
22
|
-
|
|
61
|
+
private _logger;
|
|
62
|
+
private _peerInitTimeoutMs;
|
|
63
|
+
private _disconnectCleanups;
|
|
64
|
+
private _syncConfig;
|
|
65
|
+
private _events;
|
|
66
|
+
private _refLog;
|
|
67
|
+
private _refLogSize;
|
|
68
|
+
private _ackTimeoutMs;
|
|
69
|
+
private _latestRef;
|
|
70
|
+
private _bootstrapHeartbeatTimer?;
|
|
71
|
+
private _tornDown;
|
|
72
|
+
constructor(_route: Route, _localIo: Io, _localBs: Bs, options?: ServerOptions);
|
|
23
73
|
/**
|
|
24
74
|
* Initializes Io and Bs multis on the server.
|
|
25
75
|
*/
|
|
@@ -33,17 +83,22 @@ export declare class Server extends BaseNode {
|
|
|
33
83
|
* @param socket - Client socket to register.
|
|
34
84
|
* @returns The server instance.
|
|
35
85
|
*/
|
|
36
|
-
addSocket(socket:
|
|
86
|
+
addSocket(socket: SocketLike): Promise<this>;
|
|
37
87
|
/**
|
|
38
88
|
* Removes all listeners from all connected clients.
|
|
39
89
|
*/
|
|
40
90
|
private _removeAllListeners;
|
|
41
91
|
/**
|
|
42
92
|
* Broadcasts incoming payloads from any client to all other connected clients.
|
|
43
|
-
*
|
|
93
|
+
* Enriched with ref log, ACK aggregation, and gap-fill support when
|
|
94
|
+
* syncConfig is provided.
|
|
44
95
|
*/
|
|
45
96
|
private _multicastRefs;
|
|
46
97
|
get route(): Route;
|
|
98
|
+
/**
|
|
99
|
+
* Returns the logger instance.
|
|
100
|
+
*/
|
|
101
|
+
get logger(): ServerLogger;
|
|
47
102
|
/**
|
|
48
103
|
* Returns the Io implementation.
|
|
49
104
|
*/
|
|
@@ -56,24 +111,82 @@ export declare class Server extends BaseNode {
|
|
|
56
111
|
* Returns the connected clients map.
|
|
57
112
|
*/
|
|
58
113
|
get clients(): Map<string, {
|
|
59
|
-
|
|
114
|
+
ioUp: SocketWithClientId;
|
|
115
|
+
ioDown: SocketWithClientId;
|
|
116
|
+
bsUp: SocketWithClientId;
|
|
117
|
+
bsDown: SocketWithClientId;
|
|
60
118
|
io: IoPeer;
|
|
61
119
|
bs: BsPeer;
|
|
62
120
|
}>;
|
|
121
|
+
/**
|
|
122
|
+
* Returns the sync configuration, if any.
|
|
123
|
+
*/
|
|
124
|
+
get syncConfig(): SyncConfig | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Returns the typed sync event names.
|
|
127
|
+
*/
|
|
128
|
+
get events(): SyncEventNames;
|
|
129
|
+
/**
|
|
130
|
+
* Returns the current ref log contents (for diagnostics / testing).
|
|
131
|
+
*/
|
|
132
|
+
get refLog(): readonly ConnectorPayload[];
|
|
133
|
+
/**
|
|
134
|
+
* Returns the latest ref tracked by the server (for bootstrap / diagnostics).
|
|
135
|
+
*/
|
|
136
|
+
get latestRef(): string | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* Appends a payload to the bounded ref log (ring buffer).
|
|
139
|
+
* Drops the oldest entry when the log exceeds `_refLogSize`.
|
|
140
|
+
* @param payload - The ConnectorPayload to append.
|
|
141
|
+
*/
|
|
142
|
+
private _appendToRefLog;
|
|
143
|
+
/**
|
|
144
|
+
* Sends the latest ref to a specific client socket as a bootstrap message.
|
|
145
|
+
* If no ref has been seen yet, this is a no-op.
|
|
146
|
+
* @param ioDown - The downstream socket to send the bootstrap message on.
|
|
147
|
+
*/
|
|
148
|
+
private _sendBootstrap;
|
|
149
|
+
/**
|
|
150
|
+
* Broadcasts the latest ref to all connected clients as a heartbeat.
|
|
151
|
+
* Each client's dedup pipeline will filter out refs it already has.
|
|
152
|
+
*/
|
|
153
|
+
private _broadcastBootstrapHeartbeat;
|
|
154
|
+
/**
|
|
155
|
+
* Starts the periodic bootstrap heartbeat timer if configured
|
|
156
|
+
* and not already running.
|
|
157
|
+
*/
|
|
158
|
+
private _startBootstrapHeartbeat;
|
|
159
|
+
/**
|
|
160
|
+
* Sets up ACK collection listeners before broadcast.
|
|
161
|
+
* Returns a cleanup function that emits an immediate ACK
|
|
162
|
+
* (used when there are no receivers).
|
|
163
|
+
* @param senderClientId - The internal client ID of the sender.
|
|
164
|
+
* @param ref - The ref being acknowledged.
|
|
165
|
+
* @returns A function to call for immediate ACK (zero receivers).
|
|
166
|
+
*/
|
|
167
|
+
private _setupAckCollection;
|
|
168
|
+
/**
|
|
169
|
+
* Registers a gap-fill request listener for a specific client socket.
|
|
170
|
+
* @param clientId - The internal client ID.
|
|
171
|
+
* @param socket - The upstream socket to listen on.
|
|
172
|
+
*/
|
|
173
|
+
private _registerGapFillListener;
|
|
63
174
|
/**
|
|
64
175
|
* Creates and initializes a downstream Io peer for a socket.
|
|
65
176
|
* @param socket - Client socket to bind the peer to.
|
|
177
|
+
* @param clientId - Client identifier for logging.
|
|
66
178
|
*/
|
|
67
179
|
private _createIoPeer;
|
|
68
180
|
/**
|
|
69
181
|
* Creates and initializes a downstream Bs peer for a socket.
|
|
70
182
|
* @param socket - Client socket to bind the peer to.
|
|
183
|
+
* @param clientId - Client identifier for logging.
|
|
71
184
|
*/
|
|
72
185
|
private _createBsPeer;
|
|
73
186
|
/**
|
|
74
187
|
* Registers the client socket and peers.
|
|
75
188
|
* @param clientId - Stable client identifier.
|
|
76
|
-
* @param
|
|
189
|
+
* @param sockets - Directional sockets to register.
|
|
77
190
|
* @param io - Io peer associated with the client.
|
|
78
191
|
* @param bs - Bs peer associated with the client.
|
|
79
192
|
*/
|
|
@@ -100,6 +213,34 @@ export declare class Server extends BaseNode {
|
|
|
100
213
|
* Batches multi/server refreshes into a single queued task.
|
|
101
214
|
*/
|
|
102
215
|
private _queueRefresh;
|
|
216
|
+
/**
|
|
217
|
+
* Removes a connected client by its internal client ID.
|
|
218
|
+
* Cleans up listeners, peers, and rebuilds multis.
|
|
219
|
+
* @param clientId - The client identifier (from server.clients keys).
|
|
220
|
+
*/
|
|
221
|
+
removeSocket(clientId: string): Promise<void>;
|
|
222
|
+
/**
|
|
223
|
+
* Gracefully shuts down the server: stops timers, removes listeners,
|
|
224
|
+
* clears all client state, and closes storage layers.
|
|
225
|
+
*/
|
|
226
|
+
tearDown(): Promise<void>;
|
|
227
|
+
/**
|
|
228
|
+
* Whether the server has been torn down.
|
|
229
|
+
*/
|
|
230
|
+
get isTornDown(): boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Registers a listener that auto-removes the client on socket disconnect.
|
|
233
|
+
* @param clientId - Client identifier.
|
|
234
|
+
* @param socket - The upstream socket to listen on.
|
|
235
|
+
*/
|
|
236
|
+
private _registerDisconnectHandler;
|
|
237
|
+
/**
|
|
238
|
+
* Races a promise against a timeout. Resolves/rejects with the original
|
|
239
|
+
* promise outcome if it settles first, or rejects with a timeout error.
|
|
240
|
+
* @param promise - The promise to race.
|
|
241
|
+
* @param label - Human-readable label for timeout error messages.
|
|
242
|
+
*/
|
|
243
|
+
private _withTimeout;
|
|
103
244
|
/** Example instance for test purposes */
|
|
104
245
|
static example(): Promise<Server>;
|
|
105
246
|
}
|