@rljson/server 0.0.5 → 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 +247 -11
- package/README.md +11 -3
- package/README.public.md +401 -10
- package/dist/README.architecture.md +247 -11
- package/dist/README.md +11 -3
- package/dist/README.public.md +401 -10
- package/dist/client.d.ts +70 -1
- package/dist/index.d.ts +6 -0
- package/dist/logger.d.ts +115 -0
- package/dist/server.d.ts +141 -4
- package/dist/server.js +809 -101
- package/package.json +17 -17
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,11 +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';
|
|
5
6
|
import { SocketLike } from './socket-bundle.ts';
|
|
6
7
|
export type SocketWithClientId = Socket & {
|
|
7
8
|
__clientId?: string;
|
|
8
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
|
+
}
|
|
9
45
|
export declare class Server extends BaseNode {
|
|
10
46
|
private _route;
|
|
11
47
|
protected _localIo: Io;
|
|
@@ -17,10 +53,23 @@ export declare class Server extends BaseNode {
|
|
|
17
53
|
private _bss;
|
|
18
54
|
private _bsMulti;
|
|
19
55
|
private _bsServer;
|
|
20
|
-
private
|
|
56
|
+
private _multicastedRefsCurrent;
|
|
57
|
+
private _multicastedRefsPrevious;
|
|
58
|
+
private _refEvictionTimer?;
|
|
21
59
|
private _refreshPromise?;
|
|
22
60
|
private _pendingSockets;
|
|
23
|
-
|
|
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);
|
|
24
73
|
/**
|
|
25
74
|
* Initializes Io and Bs multis on the server.
|
|
26
75
|
*/
|
|
@@ -41,10 +90,15 @@ export declare class Server extends BaseNode {
|
|
|
41
90
|
private _removeAllListeners;
|
|
42
91
|
/**
|
|
43
92
|
* Broadcasts incoming payloads from any client to all other connected clients.
|
|
44
|
-
*
|
|
93
|
+
* Enriched with ref log, ACK aggregation, and gap-fill support when
|
|
94
|
+
* syncConfig is provided.
|
|
45
95
|
*/
|
|
46
96
|
private _multicastRefs;
|
|
47
97
|
get route(): Route;
|
|
98
|
+
/**
|
|
99
|
+
* Returns the logger instance.
|
|
100
|
+
*/
|
|
101
|
+
get logger(): ServerLogger;
|
|
48
102
|
/**
|
|
49
103
|
* Returns the Io implementation.
|
|
50
104
|
*/
|
|
@@ -64,14 +118,69 @@ export declare class Server extends BaseNode {
|
|
|
64
118
|
io: IoPeer;
|
|
65
119
|
bs: BsPeer;
|
|
66
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;
|
|
67
174
|
/**
|
|
68
175
|
* Creates and initializes a downstream Io peer for a socket.
|
|
69
176
|
* @param socket - Client socket to bind the peer to.
|
|
177
|
+
* @param clientId - Client identifier for logging.
|
|
70
178
|
*/
|
|
71
179
|
private _createIoPeer;
|
|
72
180
|
/**
|
|
73
181
|
* Creates and initializes a downstream Bs peer for a socket.
|
|
74
182
|
* @param socket - Client socket to bind the peer to.
|
|
183
|
+
* @param clientId - Client identifier for logging.
|
|
75
184
|
*/
|
|
76
185
|
private _createBsPeer;
|
|
77
186
|
/**
|
|
@@ -104,6 +213,34 @@ export declare class Server extends BaseNode {
|
|
|
104
213
|
* Batches multi/server refreshes into a single queued task.
|
|
105
214
|
*/
|
|
106
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;
|
|
107
244
|
/** Example instance for test purposes */
|
|
108
245
|
static example(): Promise<Server>;
|
|
109
246
|
}
|