@ignex/nova 0.1.3 → 0.1.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.md +4 -1
- package/docs/ai/TREE.md +69 -9
- package/docs/architecture.md +75 -27
- package/docs/events.md +83 -1
- package/docs/generic-bindings.md +10 -0
- package/docs/wire-format.md +65 -18
- package/package.json +2 -1
- package/prebuilds/linux-x64/libignex_ffi.so +0 -0
- package/public/generate.ts +97 -3
- package/public/server.ts +10 -0
- package/rust/src/generated/backend.rs +503 -0
- package/rust/src/transcode/generated.rs +376 -17
- package/src/bridge/nats/inbound.ts +46 -0
- package/src/bridge/nats/index.ts +131 -0
- package/src/bridge/nats/real-transport.ts +133 -0
- package/src/bridge/nats/types.ts +80 -0
- package/src/codegen/constants.ts +14 -4
- package/src/codegen/direct-gen.ts +20 -6
- package/src/codegen/registry-gen.ts +10 -6
- package/src/codegen/rust-glue-gen.ts +10 -3
- package/src/codegen/schema-model.ts +28 -3
- package/src/codegen/ts-ser-gen.ts +12 -3
- package/src/core/auth.ts +65 -4
- package/src/core/client-rpc.ts +75 -0
- package/src/core/client-state.ts +53 -0
- package/src/core/client-wire.ts +183 -8
- package/src/core/client.ts +84 -4
- package/src/core/groups.ts +5 -0
- package/src/core/metrics.ts +38 -21
- package/src/core/outbound.ts +50 -6
- package/src/core/rate-limit.ts +69 -0
- package/src/core/replay.ts +41 -1
- package/src/core/resume.ts +181 -0
- package/src/core/rooms.ts +10 -3
- package/src/core/routing.ts +128 -5
- package/src/core/server/client-info.ts +37 -0
- package/src/core/server/http-routes.ts +59 -0
- package/src/core/{server.ts → server/index.ts} +112 -120
- package/src/core/server/metrics-view.ts +53 -0
- package/src/core/server/socket-lifecycle.ts +57 -0
- package/src/core/state.ts +73 -1
- package/src/core/topic-log.ts +86 -0
- package/src/events/clients.ts +18 -0
- package/src/events/cluster/dedupe.ts +43 -0
- package/src/events/cluster/envelope.ts +149 -0
- package/src/events/cluster/index.ts +50 -0
- package/src/events/cluster/keys.ts +33 -0
- package/src/events/cluster/kinds.ts +32 -0
- package/src/events/cluster/presence-table.ts +99 -0
- package/src/events/cluster/presence.ts +53 -0
- package/src/events/cluster/redis-client.ts +50 -0
- package/src/events/cluster/store-memory.ts +67 -0
- package/src/events/cluster/store-redis.ts +44 -0
- package/src/events/cluster/subjects.ts +30 -0
- package/src/events/cluster/sync.ts +476 -0
- package/src/events/cluster/transport-nats.ts +24 -0
- package/src/events/cluster/transport-redis.ts +120 -0
- package/src/events/cluster-rpc.ts +196 -0
- package/src/events/delivery.ts +83 -0
- package/src/events/emit.ts +57 -11
- package/src/events/hub/context-factory.ts +79 -0
- package/src/events/hub/dispatch.ts +86 -0
- package/src/events/hub/index.ts +536 -0
- package/src/events/hub/internal.ts +31 -0
- package/src/events/hub/metrics-snapshot.ts +84 -0
- package/src/events/hub/resolve-cluster.ts +49 -0
- package/src/events/queue.ts +36 -9
- package/src/events/registry.ts +90 -54
- package/src/events/schedule.ts +73 -0
- package/src/events/trace.ts +283 -0
- package/src/events/types/client.ts +68 -0
- package/src/events/types/cluster.ts +40 -0
- package/src/events/types/context.ts +50 -0
- package/src/events/types/emit-target.ts +29 -0
- package/src/events/types/groups.ts +35 -0
- package/src/events/types/hub.ts +124 -0
- package/src/events/types/index.ts +30 -0
- package/src/events/types/metrics.ts +52 -0
- package/src/events/types/options.ts +62 -0
- package/src/generated/direct-ser.ts +146 -59
- package/src/generated/fbs/backend.fbs +23 -0
- package/src/generated/registry.ts +92 -33
- package/src/generated/rust/backend_generated.rs +503 -0
- package/src/generated/ts/backend.ts +4 -0
- package/src/generated/ts/resume.ts +74 -0
- package/src/generated/ts/resumed.ts +88 -0
- package/src/generated/ts/rpc-call.ts +112 -0
- package/src/generated/ts/rpc-result.ts +126 -0
- package/src/generated/ts/snapshot-request.ts +19 -5
- package/src/generated/ts-ser.ts +109 -16
- package/src/generated/wire-registry.json +7 -3
- package/src/schema/index.ts +45 -1
- package/src/transport/transport.ts +117 -77
- package/src/bridge/nats.ts +0 -309
- package/src/events/cluster.ts +0 -732
- package/src/events/hub.ts +0 -481
- package/src/events/types.ts +0 -378
- package/src/transport/stats.ts +0 -48
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// automatically generated by the FlatBuffers compiler, do not modify
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
|
4
|
+
|
|
5
|
+
import * as flatbuffers from 'flatbuffers';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export class Resumed implements flatbuffers.IUnpackableObject<ResumedT> {
|
|
10
|
+
bb: flatbuffers.ByteBuffer|null = null;
|
|
11
|
+
bb_pos = 0;
|
|
12
|
+
__init(i:number, bb:flatbuffers.ByteBuffer):Resumed {
|
|
13
|
+
this.bb_pos = i;
|
|
14
|
+
this.bb = bb;
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getRootAsResumed(bb:flatbuffers.ByteBuffer, obj?:Resumed):Resumed {
|
|
19
|
+
return (obj || new Resumed()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static getSizePrefixedRootAsResumed(bb:flatbuffers.ByteBuffer, obj?:Resumed):Resumed {
|
|
23
|
+
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
|
24
|
+
return (obj || new Resumed()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
ok():boolean {
|
|
28
|
+
const offset = this.bb!.__offset(this.bb_pos, 4);
|
|
29
|
+
return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
from():bigint {
|
|
33
|
+
const offset = this.bb!.__offset(this.bb_pos, 6);
|
|
34
|
+
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static startResumed(builder:flatbuffers.Builder) {
|
|
38
|
+
builder.startObject(2);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static addOk(builder:flatbuffers.Builder, ok:boolean) {
|
|
42
|
+
builder.addFieldInt8(0, +ok, +false);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static addFrom(builder:flatbuffers.Builder, from:bigint) {
|
|
46
|
+
builder.addFieldInt64(1, from, BigInt('0'));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static endResumed(builder:flatbuffers.Builder):flatbuffers.Offset {
|
|
50
|
+
const offset = builder.endObject();
|
|
51
|
+
return offset;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static createResumed(builder:flatbuffers.Builder, ok:boolean, from:bigint):flatbuffers.Offset {
|
|
55
|
+
Resumed.startResumed(builder);
|
|
56
|
+
Resumed.addOk(builder, ok);
|
|
57
|
+
Resumed.addFrom(builder, from);
|
|
58
|
+
return Resumed.endResumed(builder);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
unpack(): ResumedT {
|
|
62
|
+
return new ResumedT(
|
|
63
|
+
this.ok(),
|
|
64
|
+
this.from()
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
unpackTo(_o: ResumedT): void {
|
|
70
|
+
_o.ok = this.ok();
|
|
71
|
+
_o.from = this.from();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class ResumedT implements flatbuffers.IGeneratedObject {
|
|
76
|
+
constructor(
|
|
77
|
+
public ok: boolean = false,
|
|
78
|
+
public from: bigint = BigInt('0')
|
|
79
|
+
){}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
|
83
|
+
return Resumed.createResumed(builder,
|
|
84
|
+
this.ok,
|
|
85
|
+
this.from
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// automatically generated by the FlatBuffers compiler, do not modify
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
|
4
|
+
|
|
5
|
+
import * as flatbuffers from 'flatbuffers';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export class RpcCall implements flatbuffers.IUnpackableObject<RpcCallT> {
|
|
10
|
+
bb: flatbuffers.ByteBuffer|null = null;
|
|
11
|
+
bb_pos = 0;
|
|
12
|
+
__init(i:number, bb:flatbuffers.ByteBuffer):RpcCall {
|
|
13
|
+
this.bb_pos = i;
|
|
14
|
+
this.bb = bb;
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getRootAsRpcCall(bb:flatbuffers.ByteBuffer, obj?:RpcCall):RpcCall {
|
|
19
|
+
return (obj || new RpcCall()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static getSizePrefixedRootAsRpcCall(bb:flatbuffers.ByteBuffer, obj?:RpcCall):RpcCall {
|
|
23
|
+
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
|
24
|
+
return (obj || new RpcCall()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
id():string|null
|
|
28
|
+
id(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
|
29
|
+
id(optionalEncoding?:any):string|Uint8Array|null {
|
|
30
|
+
const offset = this.bb!.__offset(this.bb_pos, 4);
|
|
31
|
+
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
name():string|null
|
|
35
|
+
name(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
|
36
|
+
name(optionalEncoding?:any):string|Uint8Array|null {
|
|
37
|
+
const offset = this.bb!.__offset(this.bb_pos, 6);
|
|
38
|
+
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
payloadB64():string|null
|
|
42
|
+
payloadB64(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
|
43
|
+
payloadB64(optionalEncoding?:any):string|Uint8Array|null {
|
|
44
|
+
const offset = this.bb!.__offset(this.bb_pos, 8);
|
|
45
|
+
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static startRpcCall(builder:flatbuffers.Builder) {
|
|
49
|
+
builder.startObject(3);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static addId(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset) {
|
|
53
|
+
builder.addFieldOffset(0, idOffset, 0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static addName(builder:flatbuffers.Builder, nameOffset:flatbuffers.Offset) {
|
|
57
|
+
builder.addFieldOffset(1, nameOffset, 0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static addPayloadB64(builder:flatbuffers.Builder, payloadB64Offset:flatbuffers.Offset) {
|
|
61
|
+
builder.addFieldOffset(2, payloadB64Offset, 0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static endRpcCall(builder:flatbuffers.Builder):flatbuffers.Offset {
|
|
65
|
+
const offset = builder.endObject();
|
|
66
|
+
return offset;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static createRpcCall(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset, nameOffset:flatbuffers.Offset, payloadB64Offset:flatbuffers.Offset):flatbuffers.Offset {
|
|
70
|
+
RpcCall.startRpcCall(builder);
|
|
71
|
+
RpcCall.addId(builder, idOffset);
|
|
72
|
+
RpcCall.addName(builder, nameOffset);
|
|
73
|
+
RpcCall.addPayloadB64(builder, payloadB64Offset);
|
|
74
|
+
return RpcCall.endRpcCall(builder);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
unpack(): RpcCallT {
|
|
78
|
+
return new RpcCallT(
|
|
79
|
+
this.id(),
|
|
80
|
+
this.name(),
|
|
81
|
+
this.payloadB64()
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
unpackTo(_o: RpcCallT): void {
|
|
87
|
+
_o.id = this.id();
|
|
88
|
+
_o.name = this.name();
|
|
89
|
+
_o.payloadB64 = this.payloadB64();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export class RpcCallT implements flatbuffers.IGeneratedObject {
|
|
94
|
+
constructor(
|
|
95
|
+
public id: string|Uint8Array|null = null,
|
|
96
|
+
public name: string|Uint8Array|null = null,
|
|
97
|
+
public payloadB64: string|Uint8Array|null = null
|
|
98
|
+
){}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
|
102
|
+
const id = (this.id !== null ? builder.createString(this.id!) : 0);
|
|
103
|
+
const name = (this.name !== null ? builder.createString(this.name!) : 0);
|
|
104
|
+
const payloadB64 = (this.payloadB64 !== null ? builder.createString(this.payloadB64!) : 0);
|
|
105
|
+
|
|
106
|
+
return RpcCall.createRpcCall(builder,
|
|
107
|
+
id,
|
|
108
|
+
name,
|
|
109
|
+
payloadB64
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// automatically generated by the FlatBuffers compiler, do not modify
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
|
4
|
+
|
|
5
|
+
import * as flatbuffers from 'flatbuffers';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export class RpcResult implements flatbuffers.IUnpackableObject<RpcResultT> {
|
|
10
|
+
bb: flatbuffers.ByteBuffer|null = null;
|
|
11
|
+
bb_pos = 0;
|
|
12
|
+
__init(i:number, bb:flatbuffers.ByteBuffer):RpcResult {
|
|
13
|
+
this.bb_pos = i;
|
|
14
|
+
this.bb = bb;
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getRootAsRpcResult(bb:flatbuffers.ByteBuffer, obj?:RpcResult):RpcResult {
|
|
19
|
+
return (obj || new RpcResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static getSizePrefixedRootAsRpcResult(bb:flatbuffers.ByteBuffer, obj?:RpcResult):RpcResult {
|
|
23
|
+
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
|
24
|
+
return (obj || new RpcResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
id():string|null
|
|
28
|
+
id(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
|
29
|
+
id(optionalEncoding?:any):string|Uint8Array|null {
|
|
30
|
+
const offset = this.bb!.__offset(this.bb_pos, 4);
|
|
31
|
+
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
ok():boolean {
|
|
35
|
+
const offset = this.bb!.__offset(this.bb_pos, 6);
|
|
36
|
+
return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
err():string|null
|
|
40
|
+
err(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
|
41
|
+
err(optionalEncoding?:any):string|Uint8Array|null {
|
|
42
|
+
const offset = this.bb!.__offset(this.bb_pos, 8);
|
|
43
|
+
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
payloadB64():string|null
|
|
47
|
+
payloadB64(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
|
48
|
+
payloadB64(optionalEncoding?:any):string|Uint8Array|null {
|
|
49
|
+
const offset = this.bb!.__offset(this.bb_pos, 10);
|
|
50
|
+
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static startRpcResult(builder:flatbuffers.Builder) {
|
|
54
|
+
builder.startObject(4);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static addId(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset) {
|
|
58
|
+
builder.addFieldOffset(0, idOffset, 0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static addOk(builder:flatbuffers.Builder, ok:boolean) {
|
|
62
|
+
builder.addFieldInt8(1, +ok, +false);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static addErr(builder:flatbuffers.Builder, errOffset:flatbuffers.Offset) {
|
|
66
|
+
builder.addFieldOffset(2, errOffset, 0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static addPayloadB64(builder:flatbuffers.Builder, payloadB64Offset:flatbuffers.Offset) {
|
|
70
|
+
builder.addFieldOffset(3, payloadB64Offset, 0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static endRpcResult(builder:flatbuffers.Builder):flatbuffers.Offset {
|
|
74
|
+
const offset = builder.endObject();
|
|
75
|
+
return offset;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static createRpcResult(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset, ok:boolean, errOffset:flatbuffers.Offset, payloadB64Offset:flatbuffers.Offset):flatbuffers.Offset {
|
|
79
|
+
RpcResult.startRpcResult(builder);
|
|
80
|
+
RpcResult.addId(builder, idOffset);
|
|
81
|
+
RpcResult.addOk(builder, ok);
|
|
82
|
+
RpcResult.addErr(builder, errOffset);
|
|
83
|
+
RpcResult.addPayloadB64(builder, payloadB64Offset);
|
|
84
|
+
return RpcResult.endRpcResult(builder);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
unpack(): RpcResultT {
|
|
88
|
+
return new RpcResultT(
|
|
89
|
+
this.id(),
|
|
90
|
+
this.ok(),
|
|
91
|
+
this.err(),
|
|
92
|
+
this.payloadB64()
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
unpackTo(_o: RpcResultT): void {
|
|
98
|
+
_o.id = this.id();
|
|
99
|
+
_o.ok = this.ok();
|
|
100
|
+
_o.err = this.err();
|
|
101
|
+
_o.payloadB64 = this.payloadB64();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export class RpcResultT implements flatbuffers.IGeneratedObject {
|
|
106
|
+
constructor(
|
|
107
|
+
public id: string|Uint8Array|null = null,
|
|
108
|
+
public ok: boolean = false,
|
|
109
|
+
public err: string|Uint8Array|null = null,
|
|
110
|
+
public payloadB64: string|Uint8Array|null = null
|
|
111
|
+
){}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
|
115
|
+
const id = (this.id !== null ? builder.createString(this.id!) : 0);
|
|
116
|
+
const err = (this.err !== null ? builder.createString(this.err!) : 0);
|
|
117
|
+
const payloadB64 = (this.payloadB64 !== null ? builder.createString(this.payloadB64!) : 0);
|
|
118
|
+
|
|
119
|
+
return RpcResult.createRpcResult(builder,
|
|
120
|
+
id,
|
|
121
|
+
this.ok,
|
|
122
|
+
err,
|
|
123
|
+
payloadB64
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -31,40 +31,53 @@ topic(optionalEncoding?:any):string|Uint8Array|null {
|
|
|
31
31
|
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
fromSeq():bigint {
|
|
35
|
+
const offset = this.bb!.__offset(this.bb_pos, 6);
|
|
36
|
+
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
|
37
|
+
}
|
|
38
|
+
|
|
34
39
|
static startSnapshotRequest(builder:flatbuffers.Builder) {
|
|
35
|
-
builder.startObject(
|
|
40
|
+
builder.startObject(2);
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
static addTopic(builder:flatbuffers.Builder, topicOffset:flatbuffers.Offset) {
|
|
39
44
|
builder.addFieldOffset(0, topicOffset, 0);
|
|
40
45
|
}
|
|
41
46
|
|
|
47
|
+
static addFromSeq(builder:flatbuffers.Builder, fromSeq:bigint) {
|
|
48
|
+
builder.addFieldInt64(1, fromSeq, BigInt('0'));
|
|
49
|
+
}
|
|
50
|
+
|
|
42
51
|
static endSnapshotRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
|
43
52
|
const offset = builder.endObject();
|
|
44
53
|
return offset;
|
|
45
54
|
}
|
|
46
55
|
|
|
47
|
-
static createSnapshotRequest(builder:flatbuffers.Builder, topicOffset:flatbuffers.Offset):flatbuffers.Offset {
|
|
56
|
+
static createSnapshotRequest(builder:flatbuffers.Builder, topicOffset:flatbuffers.Offset, fromSeq:bigint):flatbuffers.Offset {
|
|
48
57
|
SnapshotRequest.startSnapshotRequest(builder);
|
|
49
58
|
SnapshotRequest.addTopic(builder, topicOffset);
|
|
59
|
+
SnapshotRequest.addFromSeq(builder, fromSeq);
|
|
50
60
|
return SnapshotRequest.endSnapshotRequest(builder);
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
unpack(): SnapshotRequestT {
|
|
54
64
|
return new SnapshotRequestT(
|
|
55
|
-
this.topic()
|
|
65
|
+
this.topic(),
|
|
66
|
+
this.fromSeq()
|
|
56
67
|
);
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
|
|
60
71
|
unpackTo(_o: SnapshotRequestT): void {
|
|
61
72
|
_o.topic = this.topic();
|
|
73
|
+
_o.fromSeq = this.fromSeq();
|
|
62
74
|
}
|
|
63
75
|
}
|
|
64
76
|
|
|
65
77
|
export class SnapshotRequestT implements flatbuffers.IGeneratedObject {
|
|
66
78
|
constructor(
|
|
67
|
-
public topic: string|Uint8Array|null = null
|
|
79
|
+
public topic: string|Uint8Array|null = null,
|
|
80
|
+
public fromSeq: bigint = BigInt('0')
|
|
68
81
|
){}
|
|
69
82
|
|
|
70
83
|
|
|
@@ -72,7 +85,8 @@ pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
|
|
72
85
|
const topic = (this.topic !== null ? builder.createString(this.topic!) : 0);
|
|
73
86
|
|
|
74
87
|
return SnapshotRequest.createSnapshotRequest(builder,
|
|
75
|
-
topic
|
|
88
|
+
topic,
|
|
89
|
+
this.fromSeq
|
|
76
90
|
);
|
|
77
91
|
}
|
|
78
92
|
}
|
package/src/generated/ts-ser.ts
CHANGED
|
@@ -20,6 +20,10 @@ import {
|
|
|
20
20
|
SnapshotRequestT,
|
|
21
21
|
PingT,
|
|
22
22
|
PongT,
|
|
23
|
+
ResumeT,
|
|
24
|
+
ResumedT,
|
|
25
|
+
RpcCallT,
|
|
26
|
+
RpcResultT,
|
|
23
27
|
} from "./ts/backend";
|
|
24
28
|
import { anyEventNameToId, WIRE_HEADER_LEN, WIRE_VERSION } from "./registry";
|
|
25
29
|
import type { AnyEventName, ControlEvents, Events } from "../schema";
|
|
@@ -149,6 +153,7 @@ type LeaveGroupPlain = {
|
|
|
149
153
|
|
|
150
154
|
type SnapshotRequestPlain = {
|
|
151
155
|
topic: string;
|
|
156
|
+
fromSeq: number;
|
|
152
157
|
};
|
|
153
158
|
|
|
154
159
|
type PingPlain = {
|
|
@@ -159,6 +164,28 @@ type PongPlain = {
|
|
|
159
164
|
ts: number;
|
|
160
165
|
};
|
|
161
166
|
|
|
167
|
+
type ResumePlain = {
|
|
168
|
+
lastSeq: number;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
type ResumedPlain = {
|
|
172
|
+
ok: boolean;
|
|
173
|
+
from: number;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
type RpcCallPlain = {
|
|
177
|
+
id: string;
|
|
178
|
+
name: string;
|
|
179
|
+
payloadB64: string;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
type RpcResultPlain = {
|
|
183
|
+
id: string;
|
|
184
|
+
ok: boolean;
|
|
185
|
+
err: string;
|
|
186
|
+
payloadB64: string;
|
|
187
|
+
};
|
|
188
|
+
|
|
162
189
|
function buildQuoteT(o: QuotePlain): QuoteT {
|
|
163
190
|
return new QuoteT(
|
|
164
191
|
o.symbol,
|
|
@@ -306,6 +333,7 @@ function buildLeaveGroupT(o: LeaveGroupPlain): LeaveGroupT {
|
|
|
306
333
|
function buildSnapshotRequestT(o: SnapshotRequestPlain): SnapshotRequestT {
|
|
307
334
|
return new SnapshotRequestT(
|
|
308
335
|
o.topic,
|
|
336
|
+
o.fromSeq === undefined ? 0n : BigInt(o.fromSeq),
|
|
309
337
|
);
|
|
310
338
|
}
|
|
311
339
|
|
|
@@ -321,6 +349,36 @@ function buildPongT(o: PongPlain): PongT {
|
|
|
321
349
|
);
|
|
322
350
|
}
|
|
323
351
|
|
|
352
|
+
function buildResumeT(o: ResumePlain): ResumeT {
|
|
353
|
+
return new ResumeT(
|
|
354
|
+
o.lastSeq === undefined ? 0n : BigInt(o.lastSeq),
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function buildResumedT(o: ResumedPlain): ResumedT {
|
|
359
|
+
return new ResumedT(
|
|
360
|
+
o.ok,
|
|
361
|
+
o.from === undefined ? 0n : BigInt(o.from),
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function buildRpcCallT(o: RpcCallPlain): RpcCallT {
|
|
366
|
+
return new RpcCallT(
|
|
367
|
+
o.id,
|
|
368
|
+
o.name,
|
|
369
|
+
o.payloadB64,
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function buildRpcResultT(o: RpcResultPlain): RpcResultT {
|
|
374
|
+
return new RpcResultT(
|
|
375
|
+
o.id,
|
|
376
|
+
o.ok,
|
|
377
|
+
o.err,
|
|
378
|
+
o.payloadB64,
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
324
382
|
/** payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
325
383
|
export function encodeQuotePayload(o: Events["quote"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
326
384
|
b.clear();
|
|
@@ -426,24 +484,56 @@ export function encodePongPayload(o: ControlEvents["pong"], b: flatbuffers.Build
|
|
|
426
484
|
return b.asUint8Array();
|
|
427
485
|
}
|
|
428
486
|
|
|
487
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
488
|
+
export function encodeResumePayload(o: ControlEvents["resume"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
489
|
+
b.clear();
|
|
490
|
+
b.finishSizePrefixed(buildResumeT(o).pack(b));
|
|
491
|
+
return b.asUint8Array();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
495
|
+
export function encodeResumedPayload(o: ControlEvents["resumed"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
496
|
+
b.clear();
|
|
497
|
+
b.finishSizePrefixed(buildResumedT(o).pack(b));
|
|
498
|
+
return b.asUint8Array();
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
502
|
+
export function encodeRpcCallPayload(o: ControlEvents["rpcCall"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
503
|
+
b.clear();
|
|
504
|
+
b.finishSizePrefixed(buildRpcCallT(o).pack(b));
|
|
505
|
+
return b.asUint8Array();
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
509
|
+
export function encodeRpcResultPayload(o: ControlEvents["rpcResult"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
510
|
+
b.clear();
|
|
511
|
+
b.finishSizePrefixed(buildRpcResultT(o).pack(b));
|
|
512
|
+
return b.asUint8Array();
|
|
513
|
+
}
|
|
514
|
+
|
|
429
515
|
export type JsEncoder = (o: unknown, b?: flatbuffers.Builder) => Uint8Array;
|
|
430
516
|
|
|
431
517
|
export const jsEncoders: Record<string, JsEncoder> = {
|
|
432
|
-
quote: encodeQuotePayload as JsEncoder,
|
|
433
|
-
trade: encodeTradePayload as JsEncoder,
|
|
434
|
-
portfolio: encodePortfolioPayload as JsEncoder,
|
|
435
|
-
complex: encodeComplexPayload as JsEncoder,
|
|
436
|
-
order: encodeOrderPayload as JsEncoder,
|
|
437
|
-
bigVal: encodeBigValPayload as JsEncoder,
|
|
438
|
-
hello: encodeHelloPayload as JsEncoder,
|
|
439
|
-
welcome: encodeWelcomePayload as JsEncoder,
|
|
440
|
-
subscribe: encodeSubscribePayload as JsEncoder,
|
|
441
|
-
unsubscribe: encodeUnsubscribePayload as JsEncoder,
|
|
442
|
-
joinGroup: encodeJoinGroupPayload as JsEncoder,
|
|
443
|
-
leaveGroup: encodeLeaveGroupPayload as JsEncoder,
|
|
444
|
-
snapshotRequest: encodeSnapshotRequestPayload as JsEncoder,
|
|
445
|
-
ping: encodePingPayload as JsEncoder,
|
|
446
|
-
pong: encodePongPayload as JsEncoder,
|
|
518
|
+
"quote": encodeQuotePayload as JsEncoder,
|
|
519
|
+
"trade": encodeTradePayload as JsEncoder,
|
|
520
|
+
"portfolio": encodePortfolioPayload as JsEncoder,
|
|
521
|
+
"complex": encodeComplexPayload as JsEncoder,
|
|
522
|
+
"order": encodeOrderPayload as JsEncoder,
|
|
523
|
+
"bigVal": encodeBigValPayload as JsEncoder,
|
|
524
|
+
"hello": encodeHelloPayload as JsEncoder,
|
|
525
|
+
"welcome": encodeWelcomePayload as JsEncoder,
|
|
526
|
+
"subscribe": encodeSubscribePayload as JsEncoder,
|
|
527
|
+
"unsubscribe": encodeUnsubscribePayload as JsEncoder,
|
|
528
|
+
"joinGroup": encodeJoinGroupPayload as JsEncoder,
|
|
529
|
+
"leaveGroup": encodeLeaveGroupPayload as JsEncoder,
|
|
530
|
+
"snapshotRequest": encodeSnapshotRequestPayload as JsEncoder,
|
|
531
|
+
"ping": encodePingPayload as JsEncoder,
|
|
532
|
+
"pong": encodePongPayload as JsEncoder,
|
|
533
|
+
"resume": encodeResumePayload as JsEncoder,
|
|
534
|
+
"resumed": encodeResumedPayload as JsEncoder,
|
|
535
|
+
"rpcCall": encodeRpcCallPayload as JsEncoder,
|
|
536
|
+
"rpcResult": encodeRpcResultPayload as JsEncoder,
|
|
447
537
|
};
|
|
448
538
|
|
|
449
539
|
/** Encode a payload (app or control event) → size-prefixed FlatBuffer. */
|
|
@@ -453,13 +543,16 @@ export function encodeJsPayload(name: AnyEventName, o: unknown, b?: flatbuffers.
|
|
|
453
543
|
return enc(o, b);
|
|
454
544
|
}
|
|
455
545
|
|
|
456
|
-
/** Encode a payload into a full wire frame `[version][event_id:u32][size-prefixed FB]`. */
|
|
546
|
+
/** Encode a payload into a full wire frame `[version][event_id:u32][flags:1][seq:u64 LE][size-prefixed FB]`. */
|
|
457
547
|
export function encodeEventFrame(name: AnyEventName, o: unknown, b?: flatbuffers.Builder): Uint8Array {
|
|
458
548
|
const payload = encodeJsPayload(name, o, b);
|
|
459
549
|
const id = anyEventNameToId[name]!;
|
|
460
550
|
const frame = new Uint8Array(WIRE_HEADER_LEN + payload.byteLength);
|
|
461
551
|
frame[0] = WIRE_VERSION;
|
|
462
552
|
new DataView(frame.buffer).setUint32(1, id, true);
|
|
553
|
+
// pristine delivery header (flags=0, seq=0) — client-sent frames are not stamped
|
|
554
|
+
frame[WIRE_HEADER_LEN - 9] = 0;
|
|
555
|
+
new DataView(frame.buffer).setBigUint64(WIRE_HEADER_LEN - 8, 0n, true);
|
|
463
556
|
frame.set(payload, WIRE_HEADER_LEN);
|
|
464
557
|
return frame;
|
|
465
558
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version":
|
|
3
|
-
"fingerprint":
|
|
2
|
+
"version": 2,
|
|
3
|
+
"fingerprint": 3647747841,
|
|
4
4
|
"events": {
|
|
5
5
|
"quote": 2995289047,
|
|
6
6
|
"trade": 1362521689,
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
"leaveGroup": 3755061443,
|
|
17
17
|
"snapshotRequest": 1249175018,
|
|
18
18
|
"ping": 375255177,
|
|
19
|
-
"pong": 2061178551
|
|
19
|
+
"pong": 2061178551,
|
|
20
|
+
"resume": 4281967466,
|
|
21
|
+
"resumed": 3585847050,
|
|
22
|
+
"rpcCall": 986404564,
|
|
23
|
+
"rpcResult": 648609069
|
|
20
24
|
}
|
|
21
25
|
}
|
package/src/schema/index.ts
CHANGED
|
@@ -183,7 +183,14 @@ export const JoinGroup = Type.Object({ group: Type.String() }, { additionalPrope
|
|
|
183
183
|
export const LeaveGroup = Type.Object({ group: Type.String() }, { additionalProperties: false });
|
|
184
184
|
|
|
185
185
|
export const SnapshotRequest = Type.Object(
|
|
186
|
-
{
|
|
186
|
+
{
|
|
187
|
+
topic: Type.String(),
|
|
188
|
+
/**
|
|
189
|
+
* Resume point: serve recorded history STRICTLY AFTER this topic seq
|
|
190
|
+
* (0 = from the beginning of retained history — the v1 behavior).
|
|
191
|
+
*/
|
|
192
|
+
fromSeq: Type.Integer(),
|
|
193
|
+
},
|
|
187
194
|
{ additionalProperties: false },
|
|
188
195
|
);
|
|
189
196
|
|
|
@@ -191,6 +198,39 @@ export const Ping = Type.Object({ ts: Type.Integer() }, { additionalProperties:
|
|
|
191
198
|
|
|
192
199
|
export const Pong = Type.Object({ ts: Type.Integer() }, { additionalProperties: false });
|
|
193
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Client → server: resume missed delivery-seq frames after a gap or
|
|
203
|
+
* reconnect. The server replays everything it still holds strictly after
|
|
204
|
+
* `lastSeq` from the per-connection history ring, prefixed by a `resumed`
|
|
205
|
+
* control frame (`ok:false` when the hole is older than the ring).
|
|
206
|
+
*/
|
|
207
|
+
export const Resume = Type.Object(
|
|
208
|
+
{ lastSeq: Type.Integer() }, // last CONTIGUOUS delivery seq the client has
|
|
209
|
+
{ additionalProperties: false },
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
/** Server → client: ack before replayed frames (`ok:false` → resubscribe topics). */
|
|
213
|
+
export const Resumed = Type.Object(
|
|
214
|
+
{ ok: Type.Boolean(), from: Type.Integer() }, // first seq being replayed
|
|
215
|
+
{ additionalProperties: false },
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Request/response over the event wire (correlation id + timeout live on the
|
|
220
|
+
* caller side). `name` is the app-event name being requested; `payload` is the
|
|
221
|
+
* base64 of a full wire frame encoded with that same event's schema — the
|
|
222
|
+
* response reuses the SAME event schema both directions.
|
|
223
|
+
*/
|
|
224
|
+
export const RpcCall = Type.Object(
|
|
225
|
+
{ id: Type.String(), name: Type.String(), payloadB64: Type.String() },
|
|
226
|
+
{ additionalProperties: false },
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
export const RpcResult = Type.Object(
|
|
230
|
+
{ id: Type.String(), ok: Type.Boolean(), err: Type.String(), payloadB64: Type.String() },
|
|
231
|
+
{ additionalProperties: false },
|
|
232
|
+
);
|
|
233
|
+
|
|
194
234
|
/** Server→client identity assignment (sent right after `hello` on open). */
|
|
195
235
|
export const Welcome = Type.Object(
|
|
196
236
|
{
|
|
@@ -211,6 +251,10 @@ export const controlEvents = {
|
|
|
211
251
|
snapshotRequest: SnapshotRequest,
|
|
212
252
|
ping: Ping,
|
|
213
253
|
pong: Pong,
|
|
254
|
+
resume: Resume,
|
|
255
|
+
resumed: Resumed,
|
|
256
|
+
rpcCall: RpcCall,
|
|
257
|
+
rpcResult: RpcResult,
|
|
214
258
|
} as const;
|
|
215
259
|
|
|
216
260
|
export type EventName = keyof typeof events;
|