@interopio/bridge 0.0.1-alpha
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/bin/bridge.js +9 -0
- package/gen/instance/GeneratedBuildInfo.ts +4 -0
- package/license.md +5 -0
- package/package.json +40 -0
- package/readme.md +10 -0
- package/src/cluster/Address.ts +57 -0
- package/src/cluster/Cluster.ts +13 -0
- package/src/cluster/Endpoint.ts +5 -0
- package/src/cluster/Member.ts +9 -0
- package/src/cluster/MembershipListener.ts +6 -0
- package/src/config/Config.ts +100 -0
- package/src/config/DiscoveryConfig.ts +21 -0
- package/src/config/Duration.ts +168 -0
- package/src/config/KubernetesConfig.ts +7 -0
- package/src/config/NamedDiscoveryConfig.ts +17 -0
- package/src/config/Properties.ts +49 -0
- package/src/config/index.ts +1 -0
- package/src/discovery/SimpleDiscoveryNode.ts +14 -0
- package/src/discovery/index.ts +207 -0
- package/src/discovery/multicast/MulticastDiscoveryStrategy.ts +141 -0
- package/src/discovery/multicast/MulticastDiscoveryStrategyFactory.ts +30 -0
- package/src/discovery/multicast/MulticastProperties.ts +4 -0
- package/src/discovery/settings.ts +37 -0
- package/src/error/RequestFailure.ts +48 -0
- package/src/gossip/ApplicationState.ts +48 -0
- package/src/gossip/EndpointState.ts +141 -0
- package/src/gossip/FailureDetector.ts +235 -0
- package/src/gossip/Gossiper.ts +1133 -0
- package/src/gossip/HeartbeatState.ts +66 -0
- package/src/gossip/Messenger.ts +130 -0
- package/src/gossip/VersionedValue.ts +59 -0
- package/src/index.ts +3 -0
- package/src/instance/AddressPicker.ts +245 -0
- package/src/instance/BridgeNode.ts +141 -0
- package/src/instance/ClusterTopologyIntentTracker.ts +4 -0
- package/src/io/VersionedSerializer.ts +230 -0
- package/src/io/util.ts +117 -0
- package/src/kubernetes/DnsEndpointResolver.ts +70 -0
- package/src/kubernetes/KubernetesApiEndpointResolver.ts +111 -0
- package/src/kubernetes/KubernetesApiProvider.ts +75 -0
- package/src/kubernetes/KubernetesClient.ts +264 -0
- package/src/kubernetes/KubernetesConfig.ts +130 -0
- package/src/kubernetes/KubernetesDiscoveryStrategy.ts +30 -0
- package/src/kubernetes/KubernetesDiscoveryStrategyFactory.ts +71 -0
- package/src/kubernetes/KubernetesEndpointResolver.ts +43 -0
- package/src/kubernetes/KubernetesProperties.ts +22 -0
- package/src/license/BridgeLicenseValidator.ts +19 -0
- package/src/license/LicenseValidator.ts +114 -0
- package/src/license/types.ts +40 -0
- package/src/logging.ts +22 -0
- package/src/main.mts +53 -0
- package/src/net/Action.ts +143 -0
- package/src/net/AddressSerializer.ts +44 -0
- package/src/net/ByteBufferAllocator.ts +27 -0
- package/src/net/FrameDecoder.ts +314 -0
- package/src/net/FrameEncoder.ts +138 -0
- package/src/net/HandshakeProtocol.ts +143 -0
- package/src/net/InboundConnection.ts +108 -0
- package/src/net/InboundConnectionInitiator.ts +150 -0
- package/src/net/InboundMessageHandler.ts +377 -0
- package/src/net/InboundSink.ts +38 -0
- package/src/net/Message.ts +428 -0
- package/src/net/OutboundConnection.ts +1141 -0
- package/src/net/OutboundConnectionInitiator.ts +76 -0
- package/src/net/RequestCallbacks.ts +148 -0
- package/src/net/ResponseHandler.ts +30 -0
- package/src/net/ShareableBytes.ts +125 -0
- package/src/net/internal/AsyncResourceExecutor.ts +464 -0
- package/src/net/internal/AsyncSocketPromise.ts +37 -0
- package/src/net/internal/channel/ChannelHandlerAdapter.ts +99 -0
- package/src/net/internal/channel/types.ts +188 -0
- package/src/utils/bigint.ts +23 -0
- package/src/utils/buffer.ts +434 -0
- package/src/utils/clock.ts +148 -0
- package/src/utils/collections.ts +283 -0
- package/src/utils/crc.ts +39 -0
- package/src/utils/internal/IpAddressUtil.ts +161 -0
- package/src/utils/memory/BufferPools.ts +40 -0
- package/src/utils/network.ts +130 -0
- package/src/utils/promise.ts +38 -0
- package/src/utils/uuid.ts +5 -0
- package/src/utils/vint.ts +238 -0
- package/src/version/MemberVersion.ts +42 -0
- package/src/version/Version.ts +12 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import {ByteBufferInput, type DataInput, type DataOutput, type VersionedSerializer} from '../io/VersionedSerializer.ts';
|
|
2
|
+
import {fromId, NoPayload, type Verb, Verbs} from './Action.ts';
|
|
3
|
+
import {approximateClock, type Clock, type ClockTranslation} from '../utils/clock.ts';
|
|
4
|
+
import {type Address} from '../cluster/Address.ts';
|
|
5
|
+
import type {RequestFailureReason} from '../error/RequestFailure.ts';
|
|
6
|
+
import {convert} from '../config/Duration.ts';
|
|
7
|
+
import {
|
|
8
|
+
computeUnsignedVIntSize,
|
|
9
|
+
getUnsignedVInt,
|
|
10
|
+
getUnsignedVInt32,
|
|
11
|
+
getUnsignedVIntSize,
|
|
12
|
+
skipUnsignedVInt
|
|
13
|
+
} from '../utils/vint.ts';
|
|
14
|
+
import type {ByteBuffer} from '../utils/buffer.ts';
|
|
15
|
+
import {absn} from '../utils/bigint.ts';
|
|
16
|
+
|
|
17
|
+
const MessageFlags = {
|
|
18
|
+
CALL_BACK_ON_FAILURE: 0x0,
|
|
19
|
+
URGENT: 0x3,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type MessageFlag = keyof typeof MessageFlags
|
|
23
|
+
|
|
24
|
+
export function isFlagOn(header: MessageHeader, flag: MessageFlag) {
|
|
25
|
+
return (header.flags & (1 << MessageFlags[flag])) !== 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function addFlag(header: MessageHeader, flag: MessageFlag): MessageHeader {
|
|
29
|
+
const flags = header.flags | (1 << MessageFlags[flag]);
|
|
30
|
+
return {...header, flags};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const VERSION_40 = 12;
|
|
35
|
+
const VERSION_50 = 13;
|
|
36
|
+
const VERSION_51 = 14;
|
|
37
|
+
export const MessagingVersion = {VERSION_40: VERSION_40, VERSION_50: VERSION_50, VERSION_51: VERSION_51};
|
|
38
|
+
|
|
39
|
+
export interface MessageHeader {
|
|
40
|
+
// message sequence id
|
|
41
|
+
readonly seq: MessageId
|
|
42
|
+
// sender
|
|
43
|
+
readonly from: Address
|
|
44
|
+
// expiration time
|
|
45
|
+
readonly expiresAtNanos: bigint
|
|
46
|
+
// creation time
|
|
47
|
+
readonly createdAtNanos: bigint
|
|
48
|
+
// flags
|
|
49
|
+
readonly flags: number
|
|
50
|
+
readonly params?: unknown
|
|
51
|
+
// message verb
|
|
52
|
+
verb<T>(): Verb<T>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type MessageId = bigint | number
|
|
56
|
+
|
|
57
|
+
class Message<T> {
|
|
58
|
+
readonly header: MessageHeader;
|
|
59
|
+
readonly payload: T;
|
|
60
|
+
readonly payloadSerializer: VersionedSerializer<T>
|
|
61
|
+
readonly serializedSizes: {[keys: number]: number} = {};
|
|
62
|
+
|
|
63
|
+
constructor(header: MessageHeader, payload: T) {
|
|
64
|
+
this.payload = payload;
|
|
65
|
+
this.header = header;
|
|
66
|
+
this.payloadSerializer = header.verb<T>().serializer;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
serializedSize(version: number): number {
|
|
70
|
+
// todo expect valid version here
|
|
71
|
+
this.serializedSizes[version] ??= serializer.serializedSize(this, version);
|
|
72
|
+
return this.serializedSizes[version];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
payloadSize(version?: number): number {
|
|
76
|
+
return serializer.payloadSize(this, version);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get failureResponse(): boolean {
|
|
80
|
+
return fromId(this.header.verb().id) === 'FAILURE_RESPONSE';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get from() {
|
|
84
|
+
return this.header.from;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get creationTime() {
|
|
88
|
+
return approximateClock().translate.toMillisSinceEpoch(this.header.createdAtNanos);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get id() {
|
|
92
|
+
return this.header.seq;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get callbackOnFailure() {
|
|
96
|
+
return isFlagOn(this.header, 'CALL_BACK_ON_FAILURE');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
withCallbackOnFailure() {
|
|
100
|
+
return this.withFlag('CALL_BACK_ON_FAILURE');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
withFlag(flag: MessageFlag) {
|
|
104
|
+
return new Message(addFlag(this.header, flag), this.payload);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
toString() {
|
|
108
|
+
return `from ${this.from}, verb: ${fromId(this.header.verb().id)}, seq: ${this.id}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type {Message}
|
|
113
|
+
|
|
114
|
+
let nextId = 0;
|
|
115
|
+
|
|
116
|
+
const GRACE_START = 0xFFFFFFFFn - convert('milliseconds', 15, 'minutes');
|
|
117
|
+
const GRACE_END = convert('milliseconds', 15, 'minutes');
|
|
118
|
+
|
|
119
|
+
export class MessageFactory {
|
|
120
|
+
readonly from: Address;
|
|
121
|
+
private readonly clock: Clock;
|
|
122
|
+
|
|
123
|
+
constructor(from: Address, clock?: Clock) {
|
|
124
|
+
this.from = from;
|
|
125
|
+
this.clock = clock ?? approximateClock();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
emptyResponse(message: Message<unknown>) {
|
|
130
|
+
return this.responseWith(message, NoPayload.instance);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
responseWith<T>(message: Message<unknown>, payload: T): Message<T> {
|
|
134
|
+
let result = this.out<T>(message.header.verb().responseVerb as Verb<T>, payload, message.id, message.header.expiresAtNanos);
|
|
135
|
+
if (isFlagOn(message.header, 'URGENT')) {
|
|
136
|
+
result = result.withFlag('URGENT');
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
failureResponse(id: MessageId, expiresAt: bigint, reason: RequestFailureReason): Message<RequestFailureReason> {
|
|
142
|
+
return this.out(Verbs.FAILURE_RESPONSE, reason, id, expiresAt);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
out<T>(verb: Verb<T>, payload: T, id?: MessageId, expiresAt?: bigint, flags?: MessageFlag[]): Message<T> {
|
|
146
|
+
if (!verb) {
|
|
147
|
+
throw new Error('verb is required');
|
|
148
|
+
}
|
|
149
|
+
const seq = id ?? ++nextId;
|
|
150
|
+
const createdAtNanos = this.clock.now();
|
|
151
|
+
const expiresAtNanos = expiresAt ?? verb.expiresAt(createdAtNanos);
|
|
152
|
+
let encodedFlags = 0;
|
|
153
|
+
if (flags) {
|
|
154
|
+
for (const flag of flags) {
|
|
155
|
+
encodedFlags |= (1 << MessageFlags[flag]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const header: MessageHeader = {
|
|
159
|
+
seq,
|
|
160
|
+
from: this.from,
|
|
161
|
+
createdAtNanos,
|
|
162
|
+
expiresAtNanos,
|
|
163
|
+
flags: encodedFlags,
|
|
164
|
+
verb: <V>() => {return verb as V;},
|
|
165
|
+
|
|
166
|
+
};
|
|
167
|
+
return new Message(header, payload);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function calculateCreatedAtNanos(messageTimestamp: number, timeSnapshot: ClockTranslation, nowNs: bigint): bigint {
|
|
172
|
+
const currentMillis = timeSnapshot.toMillisSinceEpoch(nowNs);
|
|
173
|
+
|
|
174
|
+
let hi = currentMillis & 0xFFFFFFFF00000000n;
|
|
175
|
+
|
|
176
|
+
const sentLo = BigInt(messageTimestamp) & 0x00000000FFFFFFFFn;
|
|
177
|
+
const currentLo = currentMillis & 0x00000000FFFFFFFFn;
|
|
178
|
+
|
|
179
|
+
if (sentLo > GRACE_START && currentLo < GRACE_END) {
|
|
180
|
+
hi -= 0x0000000100000000n;
|
|
181
|
+
}
|
|
182
|
+
else if (sentLo < GRACE_END && currentLo > GRACE_START) {
|
|
183
|
+
hi += 0x0000000100000000n;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let sentTimeMs = (hi | sentLo);
|
|
187
|
+
|
|
188
|
+
if (absn(currentMillis - sentTimeMs) > convert('milliseconds', 15, 'minutes')) {
|
|
189
|
+
sentTimeMs = currentMillis;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return timeSnapshot.fromMillisSinceEpoch(sentTimeMs);
|
|
193
|
+
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
class Serializer {
|
|
197
|
+
private static readonly CREATION_TIME_SIZE = 4; // 4 bytes for createdAtNanos
|
|
198
|
+
|
|
199
|
+
serialize<T>(message: Message<T>, out: DataOutput, version: number) {
|
|
200
|
+
this.serializeHeader(message.header, out, version);
|
|
201
|
+
out.writeUnsignedVInt32(message.payloadSize(version));
|
|
202
|
+
message.payloadSerializer.serialize(message.payload, out, version);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
deserialize<T>(input: DataInput, header: MessageHeader, version: number): Message<T> {
|
|
206
|
+
this.skipHeader(input, version);
|
|
207
|
+
skipUnsignedVInt(input);// payload size
|
|
208
|
+
const payload = header.verb<T>().serializer.deserialize(input, version);
|
|
209
|
+
return new Message<T>(header, payload);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private skipHeader(input: DataInput, version: number) {
|
|
213
|
+
skipUnsignedVInt(input);
|
|
214
|
+
if (version >= VERSION_51) {
|
|
215
|
+
skipUnsignedVInt(input);
|
|
216
|
+
}
|
|
217
|
+
input.skipBytesFully(Serializer.CREATION_TIME_SIZE);
|
|
218
|
+
skipUnsignedVInt(input); // expiresIn
|
|
219
|
+
skipUnsignedVInt(input); // verb
|
|
220
|
+
skipUnsignedVInt(input); // flags
|
|
221
|
+
this.skipParams(input, version);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private skipParams(input: DataInput, version: number) {
|
|
225
|
+
const count = input.readUnsignedVInt32();
|
|
226
|
+
if (count == 0) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
for (let i = 0; i < count; i++) {
|
|
230
|
+
skipUnsignedVInt(input);
|
|
231
|
+
const length = input.readUnsignedVInt32();
|
|
232
|
+
input.skipBytesFully(length);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
serializedSize<T>(message: Message<T>, version: number): number {
|
|
237
|
+
let size = 0;
|
|
238
|
+
size += this.serializedSizeHeader(message.header, version);
|
|
239
|
+
const payloadSize = message.payloadSize(version);
|
|
240
|
+
size += computeUnsignedVIntSize(payloadSize);
|
|
241
|
+
size += payloadSize;
|
|
242
|
+
return size;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private serializedSizeHeader(header: MessageHeader, version?: number) {
|
|
246
|
+
let size = 0;
|
|
247
|
+
size += computeUnsignedVIntSize(header.seq);
|
|
248
|
+
if (version >= VERSION_51) {
|
|
249
|
+
// todo: epoch
|
|
250
|
+
}
|
|
251
|
+
size += Serializer.CREATION_TIME_SIZE; // createdAt
|
|
252
|
+
const expiresInMillis = convert('milliseconds', header.expiresAtNanos - header.createdAtNanos, 'nanoseconds');
|
|
253
|
+
size += computeUnsignedVIntSize(expiresInMillis); // expiresAtNanos - createdAtNanos
|
|
254
|
+
size += computeUnsignedVIntSize(header.verb().id); // verb.id
|
|
255
|
+
size += computeUnsignedVIntSize(header.flags); // flags
|
|
256
|
+
size += computeUnsignedVIntSize(0);// params size
|
|
257
|
+
return size;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
private serializeHeader(header: MessageHeader, out: DataOutput, version?: number) {
|
|
261
|
+
out.writeUnsignedVInt(header.seq);
|
|
262
|
+
if (version >= VERSION_51) {
|
|
263
|
+
// todo: epoch
|
|
264
|
+
}
|
|
265
|
+
out.writeInt32(Number(0xffffffffn & approximateClock().translate.toMillisSinceEpoch(header.createdAtNanos)));
|
|
266
|
+
const expiresInMillis = convert('milliseconds', header.expiresAtNanos - header.createdAtNanos, 'nanoseconds');
|
|
267
|
+
out.writeUnsignedVInt(expiresInMillis);
|
|
268
|
+
out.writeUnsignedVInt32(header.verb().id);
|
|
269
|
+
out.writeUnsignedVInt32(header.flags);
|
|
270
|
+
this.serializeParams(header.params, out, version);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private serializeParams(params: unknown, out: DataOutput, version: number) {
|
|
274
|
+
out.writeUnsignedVInt32(0);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
inferMessageSize(buffer: ByteBuffer, readerPosition: number, limit: number, version: number): number {
|
|
278
|
+
let position = readerPosition;
|
|
279
|
+
const seqSize = getUnsignedVIntSize(buffer, position, limit);
|
|
280
|
+
if (seqSize < 0) {
|
|
281
|
+
return -1; // not enough data
|
|
282
|
+
}
|
|
283
|
+
position += seqSize;
|
|
284
|
+
if (version >= VERSION_51) {
|
|
285
|
+
//todo: epoch
|
|
286
|
+
}
|
|
287
|
+
position += Serializer.CREATION_TIME_SIZE;
|
|
288
|
+
if (position > limit) {
|
|
289
|
+
return -1; // not enough data
|
|
290
|
+
}
|
|
291
|
+
const expiresInSize = getUnsignedVIntSize(buffer, position, limit);
|
|
292
|
+
if (expiresInSize < 0) {
|
|
293
|
+
return -1; // not enough data
|
|
294
|
+
}
|
|
295
|
+
position += expiresInSize;
|
|
296
|
+
|
|
297
|
+
const verbSize = getUnsignedVIntSize(buffer, position, limit);
|
|
298
|
+
if (verbSize < 0) {
|
|
299
|
+
return -1; // not enough data
|
|
300
|
+
}
|
|
301
|
+
position += verbSize;
|
|
302
|
+
|
|
303
|
+
const flagsSize = getUnsignedVIntSize(buffer, position, limit);
|
|
304
|
+
if (flagsSize < 0) {
|
|
305
|
+
return -1; // not enough data
|
|
306
|
+
}
|
|
307
|
+
position += flagsSize;
|
|
308
|
+
|
|
309
|
+
const paramsSize = this.extractParamsSize(buffer, position, limit);
|
|
310
|
+
if (paramsSize < 0) {
|
|
311
|
+
return -1; // not enough data
|
|
312
|
+
}
|
|
313
|
+
position += paramsSize;
|
|
314
|
+
|
|
315
|
+
const payloadSize = getUnsignedVInt(buffer, position, limit);
|
|
316
|
+
if (payloadSize < 0) {
|
|
317
|
+
return -1; // not enough data
|
|
318
|
+
}
|
|
319
|
+
position += computeUnsignedVIntSize(payloadSize) + Number(payloadSize);
|
|
320
|
+
|
|
321
|
+
const size = position - readerPosition;
|
|
322
|
+
// todo: check if size is valid
|
|
323
|
+
return size;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
extractHeader(buffer: ByteBuffer, from: Address, nowNs: bigint, version: number): MessageHeader {
|
|
327
|
+
const timeSnapshot = approximateClock().translate;
|
|
328
|
+
|
|
329
|
+
let position = buffer.position;
|
|
330
|
+
|
|
331
|
+
const seq = getUnsignedVInt(buffer, position);
|
|
332
|
+
position += computeUnsignedVIntSize(seq);
|
|
333
|
+
|
|
334
|
+
if (version >= VERSION_51) {
|
|
335
|
+
const epochN= getUnsignedVInt(buffer, position);
|
|
336
|
+
position += computeUnsignedVIntSize(epochN);
|
|
337
|
+
}
|
|
338
|
+
const createdAtMillis = buffer.getInt32(position);
|
|
339
|
+
position += Serializer.CREATION_TIME_SIZE;
|
|
340
|
+
|
|
341
|
+
const expiresInMillis = getUnsignedVInt(buffer, position);
|
|
342
|
+
position += computeUnsignedVIntSize(expiresInMillis);
|
|
343
|
+
|
|
344
|
+
const verb = Verbs[fromId(getUnsignedVInt32(buffer, position))];
|
|
345
|
+
position += computeUnsignedVIntSize(verb.id);
|
|
346
|
+
|
|
347
|
+
const flags = getUnsignedVInt32(buffer, position);
|
|
348
|
+
position += computeUnsignedVIntSize(flags);
|
|
349
|
+
|
|
350
|
+
const params = this.extractParams(buffer, position, version);
|
|
351
|
+
|
|
352
|
+
const createdAtNanos = calculateCreatedAtNanos(createdAtMillis, timeSnapshot, nowNs);
|
|
353
|
+
const expiresAtNanos = createdAtNanos + BigInt(convert('nanoseconds', expiresInMillis, 'milliseconds'));
|
|
354
|
+
|
|
355
|
+
const header: MessageHeader = {
|
|
356
|
+
seq,
|
|
357
|
+
from,
|
|
358
|
+
createdAtNanos,
|
|
359
|
+
expiresAtNanos,
|
|
360
|
+
flags,
|
|
361
|
+
verb: <V>() => {return verb as V;},
|
|
362
|
+
|
|
363
|
+
};
|
|
364
|
+
return header;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private extractParams(buffer: ByteBuffer, readerPosition: number, version: number): unknown {
|
|
368
|
+
const count = getUnsignedVInt(buffer, readerPosition);
|
|
369
|
+
if (count == 0) {
|
|
370
|
+
return {};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const position = buffer.position;
|
|
374
|
+
buffer.position = readerPosition;
|
|
375
|
+
try {
|
|
376
|
+
const input = new ByteBufferInput(buffer, false);
|
|
377
|
+
return this.deserializeParams(input, version);
|
|
378
|
+
} finally {
|
|
379
|
+
buffer.position = position;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
private deserializeParams(input: DataInput, version: number): unknown {
|
|
384
|
+
const count = input.readUnsignedVInt32();
|
|
385
|
+
if (count == 0) {
|
|
386
|
+
return {};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const params: Record<string, unknown> = {};
|
|
390
|
+
for (let i = 0; i < count; i++) {
|
|
391
|
+
const type = input.readUnsignedVInt32();
|
|
392
|
+
const length = input.readUnsignedVInt32();
|
|
393
|
+
|
|
394
|
+
input.skipBytesFully(length);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
private extractParamsSize(buffer: ByteBuffer, readerPosition: number, limit: number): number {
|
|
399
|
+
let position = readerPosition;
|
|
400
|
+
const paramsCount = getUnsignedVInt(buffer, position, limit);
|
|
401
|
+
if (paramsCount < 0) {
|
|
402
|
+
return -1; // not enough data
|
|
403
|
+
}
|
|
404
|
+
position += computeUnsignedVIntSize(paramsCount);
|
|
405
|
+
|
|
406
|
+
for (let i = 0; i < paramsCount; i++) {
|
|
407
|
+
|
|
408
|
+
const type = getUnsignedVInt(buffer, position, limit);
|
|
409
|
+
if (type < 0) {
|
|
410
|
+
return -1; // not enough data
|
|
411
|
+
}
|
|
412
|
+
position += computeUnsignedVIntSize(type);
|
|
413
|
+
|
|
414
|
+
const length = getUnsignedVInt(buffer, position, limit);
|
|
415
|
+
if (length < 0) {
|
|
416
|
+
return -1; // not enough data
|
|
417
|
+
}
|
|
418
|
+
position += computeUnsignedVIntSize(length) + Number(length);
|
|
419
|
+
}
|
|
420
|
+
return position - readerPosition;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
payloadSize<T>(message: Message<T>, version?: number): number {
|
|
424
|
+
let size = message.payload === undefined ? 0 : message.payloadSerializer.serializedSize(message.payload, version);
|
|
425
|
+
return size;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
export const serializer = new Serializer();
|