jspurefix 5.9.1 → 5.9.2
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/BACKPORT_PLAN.md +20 -7
- package/WORKLOG.md +119 -0
- package/dist/benchmark/bench-report.d.ts +5 -0
- package/dist/benchmark/bench-report.js +91 -0
- package/dist/benchmark/bench-report.js.map +1 -0
- package/dist/benchmark/bench-runner.d.ts +12 -0
- package/dist/benchmark/bench-runner.js +193 -0
- package/dist/benchmark/bench-runner.js.map +1 -0
- package/dist/benchmark/bench-stats.d.ts +10 -0
- package/dist/benchmark/bench-stats.js +56 -0
- package/dist/benchmark/bench-stats.js.map +1 -0
- package/dist/benchmark/bench-types.d.ts +74 -0
- package/dist/benchmark/bench-types.js +3 -0
- package/dist/benchmark/bench-types.js.map +1 -0
- package/dist/benchmark/gc-probe.d.ts +18 -0
- package/dist/benchmark/gc-probe.js +103 -0
- package/dist/benchmark/gc-probe.js.map +1 -0
- package/dist/benchmark/index.d.ts +6 -0
- package/dist/benchmark/index.js +23 -0
- package/dist/benchmark/index.js.map +1 -0
- package/dist/benchmark/parse-bench.d.ts +28 -0
- package/dist/benchmark/parse-bench.js +85 -0
- package/dist/benchmark/parse-bench.js.map +1 -0
- package/dist/buffer/ascii/ascii-parser.d.ts +1 -0
- package/dist/buffer/ascii/ascii-parser.js +4 -1
- package/dist/buffer/ascii/ascii-parser.js.map +1 -1
- package/dist/buffer/ascii/ascii-segment-parser.js +3 -2
- package/dist/buffer/ascii/ascii-segment-parser.js.map +1 -1
- package/dist/buffer/ascii/tag-index.js.map +1 -1
- package/dist/buffer/msg-view.d.ts +1 -0
- package/dist/buffer/msg-view.js +25 -19
- package/dist/buffer/msg-view.js.map +1 -1
- package/dist/dictionary/parser/quickfix/dictionary-validator.d.ts +1 -1
- package/dist/dictionary/parser/quickfix/dictionary-validator.js.map +1 -1
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.d.ts +1 -1
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js +1 -2
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js.map +1 -1
- package/dist/dictionary/parser/quickfix/validation-error.d.ts +2 -2
- package/dist/dictionary/parser/quickfix/validation-error.js.map +1 -1
- package/dist/jsfix-bench.d.ts +1 -0
- package/dist/jsfix-bench.js +213 -0
- package/dist/jsfix-bench.js.map +1 -0
- package/dist/store/file-session-store.js +1 -1
- package/dist/store/file-session-store.js.map +1 -1
- package/dist/store/file-session-stream-provider.d.ts +1 -0
- package/dist/store/file-session-stream-provider.js +13 -13
- package/dist/store/file-session-stream-provider.js.map +1 -1
- package/dist/store/fix-session-store-factory.d.ts +1 -1
- package/dist/store/fix-session-store-factory.js.map +1 -1
- package/dist/store/fix-session-store.d.ts +11 -11
- package/dist/store/fix-session-store.js.map +1 -1
- package/dist/store/memory-session-store.js.map +1 -1
- package/dist/store/session-stream-provider.d.ts +13 -13
- package/dist/store/session-stream-provider.js.map +1 -1
- package/dist/transport/session/fix-clock.d.ts +1 -1
- package/dist/transport/session/fix-clock.js.map +1 -1
- package/dist/transport/session/resend-request-manager.d.ts +2 -2
- package/dist/transport/session/resend-request-manager.js.map +1 -1
- package/dist/transport/session/session-sequence-coordinator.d.ts +1 -1
- package/dist/transport/session/session-sequence-coordinator.js.map +1 -1
- package/dist/transport/session/session-sequence-store.d.ts +3 -3
- package/dist/transport/session/session-sequence-store.js.map +1 -1
- package/dist/transport/tcp/tcp-initiator.js.map +1 -1
- package/docs/benchmarking.md +117 -0
- package/eslint.config.mjs +15 -1
- package/jsfix.test_client.txt +62 -62
- package/jsfix.test_server.txt +72 -72
- package/package.json +9 -1
- package/src/benchmark/bench-report.ts +101 -0
- package/src/benchmark/bench-runner.ts +196 -0
- package/src/benchmark/bench-stats.ts +86 -0
- package/src/benchmark/bench-types.ts +110 -0
- package/src/benchmark/gc-probe.ts +145 -0
- package/src/benchmark/index.ts +6 -0
- package/src/benchmark/parse-bench.ts +144 -0
- package/src/buffer/ascii/ascii-parser.ts +16 -1
- package/src/buffer/ascii/ascii-segment-parser.ts +9 -6
- package/src/buffer/ascii/tag-index.ts +3 -3
- package/src/buffer/msg-view.ts +35 -18
- package/src/dictionary/parser/quickfix/dictionary-validator.ts +1 -1
- package/src/dictionary/parser/quickfix/quick-fix-graph-parser.ts +2 -3
- package/src/dictionary/parser/quickfix/validation-error.ts +1 -1
- package/src/jsfix-bench.ts +204 -0
- package/src/store/file-session-store.ts +2 -2
- package/src/store/file-session-stream-provider.ts +17 -11
- package/src/store/fix-session-store-factory.ts +1 -1
- package/src/store/fix-session-store.ts +11 -11
- package/src/store/memory-session-store.ts +1 -1
- package/src/store/session-stream-provider.ts +13 -13
- package/src/transport/session/fix-clock.ts +1 -1
- package/src/transport/session/resend-request-manager.ts +4 -4
- package/src/transport/session/session-sequence-coordinator.ts +1 -1
- package/src/transport/session/session-sequence-store.ts +3 -3
- package/src/transport/tcp/tcp-initiator.ts +1 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import 'reflect-metadata'
|
|
2
|
+
|
|
3
|
+
import * as path from 'path'
|
|
4
|
+
import * as fs from 'fs'
|
|
5
|
+
import minimist = require('minimist')
|
|
6
|
+
import buildOptions from 'minimist-options'
|
|
7
|
+
|
|
8
|
+
import { AsciiChars } from './buffer/ascii'
|
|
9
|
+
import { IJsFixConfig } from './config'
|
|
10
|
+
import { DefinitionFactory } from './util'
|
|
11
|
+
import { SessionContainer } from './runtime'
|
|
12
|
+
import { DITokens } from './runtime/di-tokens'
|
|
13
|
+
import {
|
|
14
|
+
BenchRunner,
|
|
15
|
+
IBenchCase,
|
|
16
|
+
IBenchOptions,
|
|
17
|
+
IBenchSuiteResult,
|
|
18
|
+
ParseCase,
|
|
19
|
+
ParseDepth,
|
|
20
|
+
defaultBenchOptions,
|
|
21
|
+
formatComparison,
|
|
22
|
+
formatSuite
|
|
23
|
+
} from './benchmark'
|
|
24
|
+
|
|
25
|
+
const options = buildOptions({
|
|
26
|
+
dict: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
alias: 'd',
|
|
29
|
+
default: 'qf44'
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
fix: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
alias: 'f',
|
|
35
|
+
default: 'data/examples/FIX.4.4/quickfix/execution-report/fix.txt'
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
session: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
alias: 's',
|
|
41
|
+
default: 'data/session/test-initiator.json'
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
delimiter: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
alias: 'l',
|
|
47
|
+
default: '|'
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
depth: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
default: 'view,object'
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
rounds: {
|
|
56
|
+
type: 'number',
|
|
57
|
+
default: defaultBenchOptions.rounds
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
msgs: {
|
|
61
|
+
type: 'number',
|
|
62
|
+
default: defaultBenchOptions.operationsPerRound
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
warmup: {
|
|
66
|
+
type: 'number',
|
|
67
|
+
default: defaultBenchOptions.warmupOperations
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
label: {
|
|
71
|
+
type: 'string',
|
|
72
|
+
default: 'jspurefix'
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
save: {
|
|
76
|
+
type: 'string'
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
baseline: {
|
|
80
|
+
type: 'string'
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
json: {
|
|
84
|
+
type: 'boolean',
|
|
85
|
+
default: false
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
help: {
|
|
89
|
+
type: 'boolean',
|
|
90
|
+
alias: 'h',
|
|
91
|
+
default: false
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const argv: any = minimist(process.argv.slice(2), options)
|
|
96
|
+
|
|
97
|
+
const root: string = path.join(__dirname, '../')
|
|
98
|
+
|
|
99
|
+
function norm (p: string): string {
|
|
100
|
+
return path.isAbsolute(p) ? p : path.join(root, p)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function usage (): void {
|
|
104
|
+
console.log('measure the parse path and what it costs in time and in garbage')
|
|
105
|
+
console.log()
|
|
106
|
+
console.log(' --fix=<path> fix log to parse, defaults to a 4.4 execution report')
|
|
107
|
+
console.log(' --dict=<name> dictionary, e.g. qf44, repo44, qf50sp2')
|
|
108
|
+
console.log(' --delimiter=<char> field delimiter in the log, defaults to |')
|
|
109
|
+
console.log(' --depth=view,object which stages to measure, comma separated')
|
|
110
|
+
console.log(' --rounds=<n> measured rounds, one sample each')
|
|
111
|
+
console.log(' --msgs=<n> messages per round')
|
|
112
|
+
console.log(' --warmup=<n> messages discarded before measuring')
|
|
113
|
+
console.log(' --save=<path> write the suite to json')
|
|
114
|
+
console.log(' --baseline=<path> compare against a previously saved suite')
|
|
115
|
+
console.log(' --json print the suite as json instead of a report')
|
|
116
|
+
console.log()
|
|
117
|
+
console.log('run under --expose-gc so rounds can be isolated and heap read cleanly:')
|
|
118
|
+
console.log(' node --expose-gc dist/jsfix-bench --fix=data/examples/FIX.4.4/quickfix/execution-report/fix.txt')
|
|
119
|
+
console.log(' npm run bench')
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function makeConfig (): Promise<IJsFixConfig> {
|
|
123
|
+
const sys = new SessionContainer()
|
|
124
|
+
sys.registerGlobal('error')
|
|
125
|
+
const sessionDescription = require(norm(argv.session))
|
|
126
|
+
const container = await sys.makeSystem(sessionDescription)
|
|
127
|
+
const config = container.resolve<IJsFixConfig>(DITokens.IJsFixConfig)
|
|
128
|
+
config.definitions = await new DefinitionFactory().getDefinitions(argv.dict)
|
|
129
|
+
// the parser reads the delimiter when it is constructed, so this has to be
|
|
130
|
+
// settled before any case is built
|
|
131
|
+
config.delimiter = AsciiChars.firstChar(argv.delimiter)
|
|
132
|
+
return config
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function requestedDepths (): ParseDepth[] {
|
|
136
|
+
const known = new Map<string, ParseDepth>([
|
|
137
|
+
['view', ParseDepth.View],
|
|
138
|
+
['object', ParseDepth.Object]
|
|
139
|
+
])
|
|
140
|
+
const asked = String(argv.depth).split(',').map(d => d.trim().toLowerCase()).filter(d => d.length > 0)
|
|
141
|
+
return asked.map(d => {
|
|
142
|
+
const depth = known.get(d)
|
|
143
|
+
if (!depth) {
|
|
144
|
+
throw new Error(`unknown depth ${d}, expected view or object`)
|
|
145
|
+
}
|
|
146
|
+
return depth
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function readSuite (p: string): IBenchSuiteResult {
|
|
151
|
+
return JSON.parse(fs.readFileSync(norm(p), 'utf8'))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function main (): Promise<void> {
|
|
155
|
+
if (argv.help) {
|
|
156
|
+
usage()
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
const fixPath = norm(argv.fix)
|
|
160
|
+
if (!fs.existsSync(fixPath)) {
|
|
161
|
+
throw new Error(`no such fix log ${fixPath}`)
|
|
162
|
+
}
|
|
163
|
+
const contents = fs.readFileSync(fixPath, 'utf8')
|
|
164
|
+
const config = await makeConfig()
|
|
165
|
+
|
|
166
|
+
const cases: ParseCase[] = requestedDepths().map(depth =>
|
|
167
|
+
new ParseCase(`parse:${depth}`, { config, contents, depth }))
|
|
168
|
+
|
|
169
|
+
// every case walks the same input, so one alignment covers the suite and all
|
|
170
|
+
// of them stay directly comparable
|
|
171
|
+
const perInvocation = cases[0].operationsPerInvocation
|
|
172
|
+
const operationsPerRound = cases[0].alignOperations(argv.msgs)
|
|
173
|
+
const benchOptions: IBenchOptions = {
|
|
174
|
+
warmupOperations: cases[0].alignOperations(argv.warmup),
|
|
175
|
+
rounds: argv.rounds,
|
|
176
|
+
operationsPerRound,
|
|
177
|
+
gcBetweenRounds: true
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log(`${path.relative(root, fixPath)} ${perInvocation} msg/pass dict ${argv.dict}`)
|
|
181
|
+
const suite = await new BenchRunner(benchOptions).runAll(argv.label, cases as IBenchCase[])
|
|
182
|
+
|
|
183
|
+
if (argv.json) {
|
|
184
|
+
console.log(JSON.stringify(suite, null, 2))
|
|
185
|
+
} else {
|
|
186
|
+
console.log()
|
|
187
|
+
console.log(formatSuite(suite))
|
|
188
|
+
}
|
|
189
|
+
if (argv.baseline) {
|
|
190
|
+
console.log()
|
|
191
|
+
console.log(formatComparison(readSuite(argv.baseline), suite))
|
|
192
|
+
}
|
|
193
|
+
if (argv.save) {
|
|
194
|
+
const target = norm(argv.save)
|
|
195
|
+
fs.mkdirSync(path.dirname(target), { recursive: true })
|
|
196
|
+
fs.writeFileSync(target, JSON.stringify(suite, null, 2), 'utf8')
|
|
197
|
+
console.log(`saved ${path.relative(root, target)}`)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
main().catch(e => {
|
|
202
|
+
console.error(e instanceof Error ? e.message : e)
|
|
203
|
+
process.exit(1)
|
|
204
|
+
})
|
|
@@ -22,7 +22,7 @@ export class FileSessionStore implements IFixSessionStore {
|
|
|
22
22
|
private creationTimeValue: Date = new Date()
|
|
23
23
|
|
|
24
24
|
// In-memory index: seqnum -> { offset, length }
|
|
25
|
-
private readonly headerIndex
|
|
25
|
+
private readonly headerIndex = new Map<number, { offset: number, length: number }>()
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Creates a FileSessionStore with the default file-based stream provider.
|
|
@@ -285,7 +285,7 @@ export class FileSessionStore implements IFixSessionStore {
|
|
|
285
285
|
*/
|
|
286
286
|
static parseSessionTime (str: string): Date | null {
|
|
287
287
|
// Format: YYYYMMDD-HH:MM:SS.ffffff
|
|
288
|
-
const match =
|
|
288
|
+
const match = /^(\d{4})(\d{2})(\d{2})-(\d{2}):(\d{2}):(\d{2})\.(\d{3,6})$/.exec(str)
|
|
289
289
|
if (!match) return null
|
|
290
290
|
const [, y, M, d, h, m, s, frac] = match
|
|
291
291
|
const ms = parseInt(frac.substring(0, 3), 10)
|
|
@@ -32,28 +32,34 @@ export class FileSessionStreamProvider implements ISessionStreamProvider {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
openBody (): void {
|
|
35
|
-
|
|
36
|
-
this.bodyFd = fs.openSync(this.bodyPath, 'a+')
|
|
37
|
-
const stat = fs.fstatSync(this.bodyFd)
|
|
38
|
-
this.bodySize = stat.size
|
|
35
|
+
this.openBodyFd()
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
|
|
38
|
+
/**
|
|
39
|
+
* open the body file on first use and hand back the descriptor - returning it
|
|
40
|
+
* keeps callers free of a null check the compiler cannot see through.
|
|
41
|
+
*/
|
|
42
|
+
private openBodyFd (): number {
|
|
42
43
|
if (this.bodyFd === null) {
|
|
43
|
-
this.
|
|
44
|
+
this.bodyFd = fs.openSync(this.bodyPath, 'a+')
|
|
45
|
+
const stat = fs.fstatSync(this.bodyFd)
|
|
46
|
+
this.bodySize = stat.size
|
|
44
47
|
}
|
|
48
|
+
return this.bodyFd
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async appendBody (data: Buffer): Promise<number> {
|
|
52
|
+
const fd = this.openBodyFd()
|
|
45
53
|
const offset = this.bodySize
|
|
46
|
-
fs.writeSync(
|
|
54
|
+
fs.writeSync(fd, data, 0, data.length, offset)
|
|
47
55
|
this.bodySize += data.length
|
|
48
56
|
return offset
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
async readBody (offset: number, length: number): Promise<Buffer> {
|
|
52
|
-
|
|
53
|
-
this.openBody()
|
|
54
|
-
}
|
|
60
|
+
const fd = this.openBodyFd()
|
|
55
61
|
const buf = Buffer.alloc(length)
|
|
56
|
-
fs.readSync(
|
|
62
|
+
fs.readSync(fd, buf, 0, length, offset)
|
|
57
63
|
return buf
|
|
58
64
|
}
|
|
59
65
|
|
|
@@ -7,7 +7,7 @@ import { FileSessionStore } from './file-session-store'
|
|
|
7
7
|
* Factory for creating session stores.
|
|
8
8
|
*/
|
|
9
9
|
export interface IFixSessionStoreFactory {
|
|
10
|
-
create (sessionId: SessionId)
|
|
10
|
+
create: (sessionId: SessionId) => IFixSessionStore
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -14,24 +14,24 @@ export interface IFixSessionStore {
|
|
|
14
14
|
readonly sessionId: SessionId
|
|
15
15
|
|
|
16
16
|
// Message Operations
|
|
17
|
-
put (record: IFixMsgStoreRecord)
|
|
18
|
-
get (seqNum: number)
|
|
19
|
-
getRange (fromSeqNum: number, toSeqNum: number)
|
|
17
|
+
put: (record: IFixMsgStoreRecord) => Promise<void>
|
|
18
|
+
get: (seqNum: number) => Promise<IFixMsgStoreRecord | null>
|
|
19
|
+
getRange: (fromSeqNum: number, toSeqNum: number) => Promise<IFixMsgStoreRecord[]>
|
|
20
20
|
|
|
21
21
|
// Sequence Number Operations
|
|
22
22
|
senderSeqNum: number
|
|
23
23
|
targetSeqNum: number
|
|
24
|
-
setSenderSeqNum (value: number)
|
|
25
|
-
setTargetSeqNum (value: number)
|
|
26
|
-
nextSenderSeqNum ()
|
|
27
|
-
nextTargetSeqNum ()
|
|
24
|
+
setSenderSeqNum: (value: number) => Promise<void>
|
|
25
|
+
setTargetSeqNum: (value: number) => Promise<void>
|
|
26
|
+
nextSenderSeqNum: () => Promise<number>
|
|
27
|
+
nextTargetSeqNum: () => Promise<number>
|
|
28
28
|
|
|
29
29
|
// Session Operations
|
|
30
30
|
readonly creationTime: Date
|
|
31
|
-
reset ()
|
|
31
|
+
reset: () => Promise<void>
|
|
32
32
|
|
|
33
33
|
// Lifecycle
|
|
34
|
-
initialize ()
|
|
35
|
-
flush ()
|
|
36
|
-
dispose ()
|
|
34
|
+
initialize: () => Promise<void>
|
|
35
|
+
flush: () => Promise<void>
|
|
36
|
+
dispose: () => Promise<void>
|
|
37
37
|
}
|
|
@@ -7,7 +7,7 @@ import { IFixMsgStoreRecord } from './fix-msg-store-record'
|
|
|
7
7
|
* Not persistent - all data lost on dispose.
|
|
8
8
|
*/
|
|
9
9
|
export class MemorySessionStore implements IFixSessionStore {
|
|
10
|
-
private readonly messages
|
|
10
|
+
private readonly messages = new Map<number, IFixMsgStoreRecord>()
|
|
11
11
|
private senderSeqNumValue: number = 1
|
|
12
12
|
private targetSeqNumValue: number = 1
|
|
13
13
|
private creationTimeValue: Date = new Date()
|
|
@@ -7,68 +7,68 @@ export interface ISessionStreamProvider {
|
|
|
7
7
|
* Opens or creates a read-write buffer for the message body file.
|
|
8
8
|
* Must support random-access reads (by offset+length).
|
|
9
9
|
*/
|
|
10
|
-
openBody ()
|
|
10
|
+
openBody: () => void
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Appends data to the body. Returns the offset at which data was written.
|
|
14
14
|
*/
|
|
15
|
-
appendBody (data: Buffer)
|
|
15
|
+
appendBody: (data: Buffer) => Promise<number>
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Reads data from the body at the given offset and length.
|
|
19
19
|
*/
|
|
20
|
-
readBody (offset: number, length: number)
|
|
20
|
+
readBody: (offset: number, length: number) => Promise<Buffer>
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Gets the current body size (for calculating offsets).
|
|
24
24
|
*/
|
|
25
|
-
getBodySize ()
|
|
25
|
+
getBodySize: () => number
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Appends a line to the header index file.
|
|
29
29
|
*/
|
|
30
|
-
appendHeaderLine (line: string)
|
|
30
|
+
appendHeaderLine: (line: string) => Promise<void>
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Reads all lines from the header index file.
|
|
34
34
|
* Returns empty array if no data exists.
|
|
35
35
|
*/
|
|
36
|
-
readHeaderLines ()
|
|
36
|
+
readHeaderLines: () => Promise<string[]>
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Reads the sequence numbers string.
|
|
40
40
|
* Returns null if no data exists.
|
|
41
41
|
*/
|
|
42
|
-
readSeqNums ()
|
|
42
|
+
readSeqNums: () => Promise<string | null>
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Writes the sequence numbers string.
|
|
46
46
|
*/
|
|
47
|
-
writeSeqNums (content: string)
|
|
47
|
+
writeSeqNums: (content: string) => Promise<void>
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Reads the session time string.
|
|
51
51
|
* Returns null if no data exists.
|
|
52
52
|
*/
|
|
53
|
-
readSessionTime ()
|
|
53
|
+
readSessionTime: () => Promise<string | null>
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Writes the session time string.
|
|
57
57
|
*/
|
|
58
|
-
writeSessionTime (content: string)
|
|
58
|
+
writeSessionTime: (content: string) => Promise<void>
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Resets all streams/files for a new session.
|
|
62
62
|
*/
|
|
63
|
-
reset ()
|
|
63
|
+
reset: () => Promise<void>
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Flushes any pending writes.
|
|
67
67
|
*/
|
|
68
|
-
flush ()
|
|
68
|
+
flush: () => Promise<void>
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* Disposes of all resources.
|
|
72
72
|
*/
|
|
73
|
-
dispose ()
|
|
73
|
+
dispose: () => Promise<void>
|
|
74
74
|
}
|
|
@@ -46,7 +46,7 @@ export class ResendAction {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export class PendingResendRange {
|
|
49
|
-
private readonly receivedSeqs
|
|
49
|
+
private readonly receivedSeqs = new Set<number>()
|
|
50
50
|
|
|
51
51
|
constructor (
|
|
52
52
|
public readonly begin: number,
|
|
@@ -190,11 +190,11 @@ export class ResendRequestManager {
|
|
|
190
190
|
// keep requestHistory for debugging
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
get pending ():
|
|
193
|
+
get pending (): readonly PendingResendRange[] {
|
|
194
194
|
return this.pendingRequests.slice()
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
get history ():
|
|
197
|
+
get history (): readonly ResendRequestRecord[] {
|
|
198
198
|
return this.requestHistory.slice()
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -240,7 +240,7 @@ export class ResendRequestManager {
|
|
|
240
240
|
return { begin: gapBegin, end: gapEnd }
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
const covered
|
|
243
|
+
const covered = new Set<number>()
|
|
244
244
|
for (const pending of this.pendingRequests) {
|
|
245
245
|
for (let seq = pending.begin; seq <= pending.end; seq++) {
|
|
246
246
|
covered.add(seq)
|
|
@@ -160,7 +160,7 @@ export class SessionSequenceCoordinator {
|
|
|
160
160
|
this.resendManager.recordRequestSent(begin, end, now)
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
get pendingResendRequests ():
|
|
163
|
+
get pendingResendRequests (): readonly PendingResendRange[] {
|
|
164
164
|
return this.resendManager.pending
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
export interface ISessionSequenceStore {
|
|
7
7
|
senderSeqNum: number
|
|
8
8
|
targetSeqNum: number
|
|
9
|
-
setSenderSeqNum (value: number)
|
|
10
|
-
setTargetSeqNum (value: number)
|
|
11
|
-
reset ()
|
|
9
|
+
setSenderSeqNum: (value: number) => Promise<void>
|
|
10
|
+
setTargetSeqNum: (value: number) => Promise<void>
|
|
11
|
+
reset: () => Promise<void>
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -198,7 +198,7 @@ export class TcpInitiator extends FixInitiator {
|
|
|
198
198
|
const timeoutPromise = promisify(setTimeout)
|
|
199
199
|
const reconnectSeconds = application?.reconnectSeconds ?? 5
|
|
200
200
|
let retries = 0
|
|
201
|
-
let lastError: Error = initialError
|
|
201
|
+
let lastError: Error | undefined = initialError
|
|
202
202
|
const name = application?.name ?? 'initiator'
|
|
203
203
|
this.th = setInterval(() => {
|
|
204
204
|
++retries
|