jspurefix 5.10.1 → 5.10.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/ATDL_PLAN.md +109 -0
- package/WORKLOG.md +108 -13
- package/dist/runtime/session-launcher.d.ts +2 -0
- package/dist/runtime/session-launcher.js +10 -1
- package/dist/runtime/session-launcher.js.map +1 -1
- package/docs/acceptor.md +32 -0
- package/jsfix.test_client.txt +62 -62
- package/jsfix.test_server.txt +72 -72
- package/package.json +1 -1
- package/src/runtime/session-launcher.ts +29 -1
package/ATDL_PLAN.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# FIXatdl renderer and end-to-end test harness
|
|
2
|
+
|
|
3
|
+
Design notes from 2026-08-08. Nothing is built yet. This exists so the next session
|
|
4
|
+
can start from the thinking rather than redo it.
|
|
5
|
+
|
|
6
|
+
**First decision to settle:** this is not jspurefix work and should almost certainly
|
|
7
|
+
live in its own repository (`jspf-atdl`, or similar). The plan is parked here because
|
|
8
|
+
it is where the conversation happened and because the back-end half does use the
|
|
9
|
+
engine. Move it when the code starts.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## The problem
|
|
14
|
+
|
|
15
|
+
A broker publishes a FIXatdl document per algorithm: an XML definition of its
|
|
16
|
+
parameters and the order ticket used to fill them in. An EMS — Bloomberg EMSX,
|
|
17
|
+
Flextrade, Portware, Fidessa, ITG Triton — renders the ticket from that document, and
|
|
18
|
+
the values map onto FIX tags, usually the `NoStrategyParameters` group.
|
|
19
|
+
|
|
20
|
+
The observed pain, in more than one shop: getting a definition rendered is cobbled
|
|
21
|
+
together, and **you cannot tell whether a definition is sound until a vendor renders
|
|
22
|
+
it**. The loop is write it, send it, wait, discover it renders differently in EMSX
|
|
23
|
+
than in Triton, repeat. Nothing good and open exists to shorten that.
|
|
24
|
+
|
|
25
|
+
The goal is to close the loop locally, and then go one step further than any renderer
|
|
26
|
+
does — send the resulting order to a back end that answers, so a definition can be
|
|
27
|
+
proved end to end before it goes to clients.
|
|
28
|
+
|
|
29
|
+
## What it actually is
|
|
30
|
+
|
|
31
|
+
**An interpreter, not an application.** The UI is entirely data driven: you never
|
|
32
|
+
hand-write a component per algorithm, you walk the layout tree. That single
|
|
33
|
+
observation drives every technology choice below.
|
|
34
|
+
|
|
35
|
+
The state is a flat map of control id to value. There is no routing, no server state,
|
|
36
|
+
no virtualised list, no async rendering. Almost nothing a UI framework is good at is
|
|
37
|
+
in play.
|
|
38
|
+
|
|
39
|
+
## Technology
|
|
40
|
+
|
|
41
|
+
Deliberately small. FIXatdl is *already* a declarative UI description — wrapping it in
|
|
42
|
+
React means writing a compiler from one declarative tree into another and inheriting a
|
|
43
|
+
second lifecycle model, build chain and version churn, for a form with thirty
|
|
44
|
+
controls.
|
|
45
|
+
|
|
46
|
+
- **`DOMParser` for the XML.** ATDL is split across several namespaces — core,
|
|
47
|
+
layout, validation, flow control — and `getElementsByTagNameNS` is exactly the tool
|
|
48
|
+
for that. Built into every browser, zero dependencies.
|
|
49
|
+
- **Plain DOM for rendering.** Walk the layout tree, emit a label and an input per
|
|
50
|
+
control. On any change, re-evaluate every state rule and edit, then toggle
|
|
51
|
+
`disabled` / `hidden`. Tens of rules, not thousands — a full re-evaluation is
|
|
52
|
+
microseconds, so the machinery that exists to avoid one is dead weight.
|
|
53
|
+
- **TypeScript for the model and interpreter**, built to a single ESM module. A build
|
|
54
|
+
step for the author, not for anyone using it.
|
|
55
|
+
- **Static hosting, dynamic page.** One HTML file plus one module, opening from
|
|
56
|
+
`file://` if need be. Drag an ATDL file on, see it render, edit the XML, drop it
|
|
57
|
+
again.
|
|
58
|
+
|
|
59
|
+
Note the distinction that matters: static **hosting**, not static **generation**.
|
|
60
|
+
Generating HTML at build time would need a rebuild per edit, and the tight edit loop
|
|
61
|
+
is the entire product.
|
|
62
|
+
|
|
63
|
+
## Build order
|
|
64
|
+
|
|
65
|
+
**The expression engine first, headless, with tests.** `StateRule` and `StrategyEdit`
|
|
66
|
+
form a small expression language — operators, logical combinators, references to other
|
|
67
|
+
controls — and that is where the time will go and where correctness actually matters.
|
|
68
|
+
Unit-test it against real broker ATDL documents before drawing a single widget. If
|
|
69
|
+
that engine is right the tool is good; if it is approximate, it is one more
|
|
70
|
+
cobbled-together thing.
|
|
71
|
+
|
|
72
|
+
Controls are the easy half and should come second.
|
|
73
|
+
|
|
74
|
+
## Pluggable skins
|
|
75
|
+
|
|
76
|
+
Part of the value is answering "roughly how will EMSX lay this out, versus Fidessa" —
|
|
77
|
+
the question people genuinely cannot answer today. Keep layout strategy and CSS behind
|
|
78
|
+
an adapter so the same definition can render two ways side by side. CSS custom
|
|
79
|
+
properties cover it; still no framework.
|
|
80
|
+
|
|
81
|
+
## The back end
|
|
82
|
+
|
|
83
|
+
A browser cannot open a TCP FIX session, so:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
page --(WebSocket, composed order as JSON)--> bridge --(FIX)--> test acceptor
|
|
87
|
+
<--(ExecutionReports)---------------------
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The bridge owns a jspurefix initiator; the acceptor validates the strategy parameters
|
|
91
|
+
against the same ATDL definition and answers. This keeps the page genuinely static and
|
|
92
|
+
the FIX where it belongs.
|
|
93
|
+
|
|
94
|
+
A thin WebSocket server is the right shape here — the engine's existing HTTP acceptor
|
|
95
|
+
is FIXML-shaped and is not a good fit for this.
|
|
96
|
+
|
|
97
|
+
## Rough size
|
|
98
|
+
|
|
99
|
+
~1,500 lines of interpreter, zero runtime dependencies.
|
|
100
|
+
|
|
101
|
+
## Open questions for next session
|
|
102
|
+
|
|
103
|
+
1. Own repository or a folder here? (Recommendation: own repository.)
|
|
104
|
+
2. Which real ATDL documents can be used as test fixtures? The expression engine is
|
|
105
|
+
only as good as what it is tested against, and broker-published files vary a lot.
|
|
106
|
+
3. Which FIXatdl version to target. 1.1 is the one in widespread use; confirm before
|
|
107
|
+
writing the parser rather than after.
|
|
108
|
+
4. How strategy parameters map onto the outbound order — the `NoStrategyParameters`
|
|
109
|
+
group versus direct custom tags — likely needs to be configurable per broker.
|
package/WORKLOG.md
CHANGED
|
@@ -2,7 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
Running notes on what has been done and what is worth doing next, so a session can
|
|
4
4
|
be resumed cold. The long-form plans live in `BACKPORT_PLAN.md` (engine, cspurefix →
|
|
5
|
-
jspurefix)
|
|
5
|
+
jspurefix), `DEMO_PORT_PLAN.md` (the jspf-demo reference app) and `ATDL_PLAN.md` (a
|
|
6
|
+
FIXatdl renderer and test harness — a prospective sibling project, not engine work).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 2026-08-08 — closing the acceptor's listener
|
|
11
|
+
|
|
12
|
+
Reported from jspf-demo: `npm run custom-logon` never exits. The logs say everything
|
|
13
|
+
shut down — sessions logged out, transports harvested, registry empty, `.. done` —
|
|
14
|
+
and the node process sits there.
|
|
15
|
+
|
|
16
|
+
Diagnosed by dumping `process._getActiveHandles()` after the run. Session and
|
|
17
|
+
transport teardown is complete; the only handle left is the listening `net.Server`.
|
|
18
|
+
A listening socket keeps node alive by itself, and nothing ever closed it.
|
|
19
|
+
|
|
20
|
+
`TcpAcceptorListener.stop()` has always existed and does the right thing. What was
|
|
21
|
+
missing was any way to *call* it: `SessionLauncher.stopAcceptor()` was private and
|
|
22
|
+
reached only from the branch where one launcher holds both roles. An application that
|
|
23
|
+
gives its acceptor a launcher of its own — which jspf-demo started doing on 2026-08-01
|
|
24
|
+
so the acceptor would survive any one client — could not close its listener at all.
|
|
25
|
+
|
|
26
|
+
**Changed:** `SessionLauncher.stop()`, public. Remembers a stop that arrives before
|
|
27
|
+
the acceptor has started (`makeSystem` is async, so that window is real) and never
|
|
28
|
+
opens the listener in that case. `run()` resolves once the listener has closed.
|
|
29
|
+
Pinned by `src/test/session/launcher-stop.test.ts`.
|
|
30
|
+
|
|
31
|
+
Worth checking against
|
|
32
|
+
[#72](https://github.com/TimelordUK/jspurefix/issues/72) ("`session-launcher.run()`
|
|
33
|
+
never resolves when connection established") before that issue is next looked at —
|
|
34
|
+
for an acceptor, run() not resolving was the designed behaviour with no way out, and
|
|
35
|
+
now there is one.
|
|
36
|
+
|
|
37
|
+
`docs/acceptor.md` gained a "Closing the listener" section, because from the outside
|
|
38
|
+
this reads as a hang rather than as a decision.
|
|
6
39
|
|
|
7
40
|
---
|
|
8
41
|
|
|
@@ -37,6 +70,62 @@ confirmation — see below).
|
|
|
37
70
|
|
|
38
71
|
---
|
|
39
72
|
|
|
73
|
+
## 2026-08-08 — customising the Logon, and making silent drops visible, released as 5.10.0
|
|
74
|
+
|
|
75
|
+
Started from [#93](https://github.com/TimelordUK/jspurefix/issues/93), open since
|
|
76
|
+
December 2024, and ended up somewhere broader. Two issues that look unrelated turned
|
|
77
|
+
out to share a theme: **the engine failed quietly in several places, and nobody could
|
|
78
|
+
see it.**
|
|
79
|
+
|
|
80
|
+
**Merged (PR #164):**
|
|
81
|
+
|
|
82
|
+
- a `Logon` block in the session description, merged over the fields the engine
|
|
83
|
+
derives. `AsciiSessionMsgFactory.logon()` had read exactly five values off the
|
|
84
|
+
description and ignored everything else, so an `"Account"` in the config was never
|
|
85
|
+
looked at. A null in the block suppresses a field.
|
|
86
|
+
- `AsciiEncoder` now reports a key it cannot resolve, via
|
|
87
|
+
`MsgEncoder.onUnknownField`. This was the real cause of the confusion: `Account` is
|
|
88
|
+
tag 1 but is not a field of FIX 4.4 `Logon`, so it was discarded with no error and
|
|
89
|
+
no log line. Only runs on the miss path — a key that resolves costs nothing.
|
|
90
|
+
- `SessionContainer(provider)` and `SessionLauncher.makeSessionMsgFactory()`, so
|
|
91
|
+
supplying a factory no longer needs a `SessionContainer` subclass
|
|
92
|
+
- `AsciiSessionMsgFactory` / `FixmlSessionMsgFactory` exported from the package root.
|
|
93
|
+
Extending the ascii factory — the thing every previous answer to these issues told
|
|
94
|
+
people to do — used to require importing through `dist/transport/ascii/...`.
|
|
95
|
+
- an optional callback on `send`, giving back the stamped `StandardHeader` (and so
|
|
96
|
+
the sequence number) or an error. Writing it exposed three drops that told nobody:
|
|
97
|
+
`encodeMessage` returning null for an unknown msgType, a session in state
|
|
98
|
+
`Stopped`, and no transport at all. All three still reach the error channel; the
|
|
99
|
+
callback is additive.
|
|
100
|
+
|
|
101
|
+
**Issues resolved:** #93, #86, #39, #96 (all commented with the full explanation).
|
|
102
|
+
#69 verified fixed — `SenderSubID` has been in the header since `dd9a540` — and left
|
|
103
|
+
open pending the reporter, since their actual complaint was "no response from the
|
|
104
|
+
server".
|
|
105
|
+
|
|
106
|
+
**Docs:** `docs/custom-logon.md`, plus README sections on the `Logon` block and on
|
|
107
|
+
send callbacks.
|
|
108
|
+
|
|
109
|
+
**Perf:** flat. Parse benchmarks moved inside the noise floor; Logon encode 2.26
|
|
110
|
+
µs/msg against the 2.3 in the README table. The encoder change is genuinely off the
|
|
111
|
+
hot path.
|
|
112
|
+
|
|
113
|
+
**Demos:** `jspf-demo` gained a `custom-logon` mode (config block + generated
|
|
114
|
+
dictionary + run-time factory, and one field deliberately left undeclared so the new
|
|
115
|
+
warning is visible). `jspf-md-demo`'s `Msg44Fact` had a `logon()` that was a verbatim
|
|
116
|
+
copy of the stock one — it showed the hook and never the point — and now sends a real
|
|
117
|
+
bespoke tag; its generated types were regenerated in a separate commit, having
|
|
118
|
+
drifted a long way behind the generator.
|
|
119
|
+
|
|
120
|
+
**Found along the way:** jspf-demo had been sending every `TradeCaptureReportRequest`
|
|
121
|
+
without its dates for as long as the demo has existed. `TrdCapDtGrp` was built as a
|
|
122
|
+
flat array, which is how the FIX repository models it, but those sessions load the
|
|
123
|
+
QuickFIX dictionary where it is a component wrapping `NoDates`. The encoder dropped
|
|
124
|
+
it silently. The new warning is what caught it, about an hour after it existed — a
|
|
125
|
+
fair advertisement for the feature.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
40
129
|
## Next up
|
|
41
130
|
|
|
42
131
|
### 1. Toolchain major bumps
|
|
@@ -49,10 +138,9 @@ acceptor work:
|
|
|
49
138
|
- `eslint-config-love` 151 → 154
|
|
50
139
|
- `@types/node` 25 → 26
|
|
51
140
|
|
|
52
|
-
Expect lint churn.
|
|
53
|
-
`
|
|
54
|
-
|
|
55
|
-
currently clean.
|
|
141
|
+
Expect lint churn. The 17 pre-existing lint errors noted here were cleared in
|
|
142
|
+
`1d2f267` — `npx eslint src/` is clean on master as of 5.10.0, so any churn from the
|
|
143
|
+
bump is genuinely new and worth reading. `npm audit` is clean.
|
|
56
144
|
|
|
57
145
|
### 2. #77 — confirm or close
|
|
58
146
|
|
|
@@ -76,14 +164,21 @@ reproduced.
|
|
|
76
164
|
|
|
77
165
|
### 3. Other open issues worth a look
|
|
78
166
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
|
|
167
|
+
Most of this list was cleared in 5.10.0. What remains:
|
|
168
|
+
|
|
169
|
+
- **#69** — verified fixed and commented; awaiting the reporter before closing. Their
|
|
170
|
+
literal question (`SenderSubID`) works; their real complaint was silence from
|
|
171
|
+
cServer, which is a different problem.
|
|
172
|
+
- **#85** — `ASessionMsgFactory` types patch. Possibly superseded twice over now, by
|
|
173
|
+
`cloneFor` and by the root exports added in 5.10.0. Worth reading the patch against
|
|
174
|
+
current master before doing anything.
|
|
175
|
+
- **#72** — `session-launcher.run()` never resolves when the connection is
|
|
176
|
+
established. Not looked at. Given how #140 and #77 went, verify against 5.10.0
|
|
177
|
+
before trusting the thread.
|
|
178
|
+
|
|
179
|
+
The lesson from this batch, worth repeating: **several of these were already fixed,
|
|
180
|
+
or were one line plus a docs gap.** Reading the thread is a poor substitute for
|
|
181
|
+
running the reporter's config.
|
|
87
182
|
|
|
88
183
|
### 4. Small things noticed, none urgent
|
|
89
184
|
|
|
@@ -14,9 +14,11 @@ export declare abstract class SessionLauncher {
|
|
|
14
14
|
protected makeSessionMsgFactory(_description: ISessionDescription): ISessionMsgFactory | null;
|
|
15
15
|
private empty;
|
|
16
16
|
private acceptorEntity;
|
|
17
|
+
private stopRequested;
|
|
17
18
|
protected getAcceptor(sessionContainer: DependencyContainer): Promise<any>;
|
|
18
19
|
protected getInitiator(sessionContainer: DependencyContainer): Promise<any>;
|
|
19
20
|
protected makeFactory(config: IJsFixConfig): EngineFactory | null;
|
|
21
|
+
stop(): void;
|
|
20
22
|
run(): Promise<boolean>;
|
|
21
23
|
exec(): void;
|
|
22
24
|
isAscii(description: ISessionDescription): boolean;
|
|
@@ -54,6 +54,7 @@ class SessionLauncher {
|
|
|
54
54
|
this.root = '../../';
|
|
55
55
|
this.sessionContainer = new session_container_1.SessionContainer((d) => this.makeSessionMsgFactory(d));
|
|
56
56
|
this.acceptorEntity = null;
|
|
57
|
+
this.stopRequested = false;
|
|
57
58
|
this.logger = this.loggerFactory.logger('launcher');
|
|
58
59
|
this.initiatorConfig = initiatorConfig ? this.loadConfig(initiatorConfig) : null;
|
|
59
60
|
this.acceptorConfig = acceptorConfig ? this.loadConfig(acceptorConfig) : null;
|
|
@@ -81,6 +82,10 @@ class SessionLauncher {
|
|
|
81
82
|
if (sessionContainer.isRegistered(di_tokens_1.DITokens.FixEntity)) {
|
|
82
83
|
const entity = sessionContainer.resolve(di_tokens_1.DITokens.FixEntity);
|
|
83
84
|
this.acceptorEntity = entity;
|
|
85
|
+
if (this.stopRequested) {
|
|
86
|
+
this.logger.info('stop requested before the acceptor started - not listening');
|
|
87
|
+
return this.empty();
|
|
88
|
+
}
|
|
84
89
|
return entity.start();
|
|
85
90
|
}
|
|
86
91
|
else {
|
|
@@ -102,6 +107,10 @@ class SessionLauncher {
|
|
|
102
107
|
makeFactory(config) {
|
|
103
108
|
return null;
|
|
104
109
|
}
|
|
110
|
+
stop() {
|
|
111
|
+
this.stopRequested = true;
|
|
112
|
+
this.stopAcceptor();
|
|
113
|
+
}
|
|
105
114
|
run() {
|
|
106
115
|
return __awaiter(this, void 0, void 0, function* () {
|
|
107
116
|
return yield new Promise((resolve, reject) => {
|
|
@@ -195,7 +204,7 @@ class SessionLauncher {
|
|
|
195
204
|
if (this.acceptorConfig && this.initiatorConfig) {
|
|
196
205
|
yield client;
|
|
197
206
|
this.logger.info('client finished, stopping acceptor');
|
|
198
|
-
this.
|
|
207
|
+
this.stop();
|
|
199
208
|
return true;
|
|
200
209
|
}
|
|
201
210
|
return yield Promise.all([server, client]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-launcher.js","sourceRoot":"","sources":["../../src/runtime/session-launcher.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path'\nimport { IJsFixConfig, IJsFixLogger, JsFixLoggerFactory, JsFixWinstonLogFactory, WinstonLogger } from '../config'\nimport { FixEntity, FixSession, ISessionDescription, ISessionMsgFactory } from '../transport'\nimport { DependencyContainer } from 'tsyringe'\nimport { EngineFactory } from './engine-factory'\nimport { SessionContainer } from './session-container'\nimport { DITokens } from './di-tokens'\n\nconst defaultLoggerFactory = new JsFixWinstonLogFactory(WinstonLogger.consoleOptions('info'))\n\nexport abstract class SessionLauncher {\n public root: string = '../../'\n protected readonly logger: IJsFixLogger\n public readonly initiatorConfig: ISessionDescription | null\n public readonly acceptorConfig: ISessionDescription | null\n\n protected constructor (\n initiatorConfig: string | ISessionDescription | null = null,\n acceptorConfig: string | ISessionDescription | null = null,\n private readonly loggerFactory: JsFixLoggerFactory = defaultLoggerFactory\n ) {\n this.logger = this.loggerFactory.logger('launcher')\n this.initiatorConfig = initiatorConfig ? this.loadConfig(initiatorConfig) : null\n this.acceptorConfig = acceptorConfig ? this.loadConfig(acceptorConfig) : null\n }\n\n // the arrow defers to makeSessionMsgFactory at resolve time, so a subclass need\n // only override that one method - no SessionContainer subclass required\n protected sessionContainer: SessionContainer =\n new SessionContainer((d: ISessionDescription) => this.makeSessionMsgFactory(d))\n\n /**\n * Override to supply this application's own session message factory - the place to\n * put a Logon carrying tags the standard message does not, or a header a\n * counterparty stamps differently. Return null (the default) for the stock\n * factory.\n *\n * For a Logon that only needs extra fields, prefer the \"Logon\" block in the session\n * description - it needs no code at all. Reach for a factory when the values are\n * computed at run time (a signature, a nonce, a token fetched at start up).\n */\n protected makeSessionMsgFactory (_description: ISessionDescription): ISessionMsgFactory | null {\n return null\n }\n\n private async empty (): Promise<any> {\n return await new Promise((resolve, reject) => {\n try {\n setImmediate(() => {\n this.logger.info('resolving an empty promise')\n resolve(null)\n })\n } catch (e) {\n reject(e)\n }\n })\n }\n\n private acceptorEntity: FixEntity | null = null\n\n protected async getAcceptor (sessionContainer: DependencyContainer): Promise<any> {\n if (sessionContainer.isRegistered<FixEntity>(DITokens.FixEntity)) {\n const entity = sessionContainer.resolve<FixEntity>(DITokens.FixEntity)\n this.acceptorEntity = entity\n return entity.start()\n } else {\n return this.empty()\n }\n }\n\n protected async getInitiator (sessionContainer: DependencyContainer): Promise<any> {\n if (sessionContainer.isRegistered<FixEntity>(DITokens.FixEntity)) {\n const entity = sessionContainer.resolve<FixEntity>(DITokens.FixEntity)\n return entity.start()\n } else {\n return this.empty()\n }\n }\n\n /**\n * provide a factory which will be invoked with a config where an instance of the application\n * should be constructed and returned.\n * @param config to be provided to the constucted application representing this session\n * @protected\n */\n protected makeFactory (config: IJsFixConfig): EngineFactory | null {\n return null\n }\n\n public async run (): Promise<boolean> {\n return await new Promise<any>((resolve, reject) => {\n const logger = this.logger\n logger.info('launching ..')\n this.setup().then(() => {\n logger.info('.. done')\n resolve(true)\n }).catch((e: Error) => {\n logger.error(e)\n reject(e)\n })\n })\n }\n\n public exec (): void {\n this.run().then(() => {\n console.log('finished.')\n }).catch(e => {\n console.error(e)\n })\n }\n\n /**\n * is this session config representing an ascii based session\n * @param description config to be tested.\n */\n public isAscii (description: ISessionDescription): boolean {\n return this.sessionContainer.isAscii(description)\n }\n\n /**\n * is this session config representing an initiator based session\n * @param description config to be tested.\n */\n public isInitiator (description: ISessionDescription): boolean {\n return this.sessionContainer.isInitiator(description)\n }\n\n protected registerApplication (_: DependencyContainer): void {\n this.logger.info('bypass register via DI')\n }\n\n private async makeSystem (description: ISessionDescription): Promise<DependencyContainer> {\n const name = description.application?.name ?? 'na'\n const protocol = description.application?.protocol ?? 'ascii'\n this.logger.info(`creating app ${name} [protocol ${protocol}]`)\n return await this.sessionContainer.makeSystem(description)\n }\n\n private register (container: DependencyContainer): void {\n const config = container.resolve<IJsFixConfig>(DITokens.IJsFixConfig)\n const factory = this.makeFactory(config)\n if (!factory) {\n this.registerApplication(container)\n } else {\n if (factory.makeSession) {\n // resolve the config from the container doing the resolving, not the one\n // captured here. An acceptor resolves each session from a per-connection\n // child scope which re-registers IJsFixConfig, so this is how an application\n // receives that session's own description, store and message factory.\n container.register<FixSession>(DITokens.FixSession, {\n useFactory: (c) => factory.makeSession(c.resolve<IJsFixConfig>(DITokens.IJsFixConfig))\n })\n }\n }\n }\n\n private async makeClient (): Promise<any> {\n if (!this.initiatorConfig) return\n const sessionContainer = await this.makeSystem(this.initiatorConfig)\n this.register(sessionContainer)\n this.logger.info('create initiator')\n return await this.getInitiator(sessionContainer)\n }\n\n private async makeServer (): Promise<any> {\n if (!this.acceptorConfig) return\n const sessionContainer = await this.makeSystem(this.acceptorConfig)\n this.register(sessionContainer)\n this.logger.info('create acceptor')\n return await this.getAcceptor(sessionContainer)\n }\n\n async serverOrEmpty (): Promise<any> {\n return this.acceptorConfig ? this.makeServer() : this.empty()\n }\n\n async clientOrEmpty (): Promise<any> {\n return this.initiatorConfig ? this.makeClient() : this.empty()\n }\n\n private async setup (): Promise<any> {\n this.sessionContainer.registerGlobal(this.loggerFactory)\n const server = this.serverOrEmpty()\n const client = this.clientOrEmpty()\n this.logger.info('launching ....')\n if (this.acceptorConfig && this.initiatorConfig) {\n // Both mode: client drives the lifecycle. When client finishes,\n // stop the acceptor so the process can exit cleanly.\n await client\n this.logger.info('client finished, stopping acceptor')\n this.stopAcceptor()\n return true\n }\n return await Promise.all([server, client])\n }\n\n private stopAcceptor (): void {\n const entity = this.acceptorEntity as any\n if (entity && typeof entity.stop === 'function') {\n entity.stop()\n }\n }\n\n private loadConfig (config: string | ISessionDescription): ISessionDescription {\n if (typeof config === 'string') {\n return require(path.join(this.root, config))\n }\n return config\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-launcher.js","sourceRoot":"","sources":["../../src/runtime/session-launcher.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path'\nimport { IJsFixConfig, IJsFixLogger, JsFixLoggerFactory, JsFixWinstonLogFactory, WinstonLogger } from '../config'\nimport { FixEntity, FixSession, ISessionDescription, ISessionMsgFactory } from '../transport'\nimport { DependencyContainer } from 'tsyringe'\nimport { EngineFactory } from './engine-factory'\nimport { SessionContainer } from './session-container'\nimport { DITokens } from './di-tokens'\n\nconst defaultLoggerFactory = new JsFixWinstonLogFactory(WinstonLogger.consoleOptions('info'))\n\nexport abstract class SessionLauncher {\n public root: string = '../../'\n protected readonly logger: IJsFixLogger\n public readonly initiatorConfig: ISessionDescription | null\n public readonly acceptorConfig: ISessionDescription | null\n\n protected constructor (\n initiatorConfig: string | ISessionDescription | null = null,\n acceptorConfig: string | ISessionDescription | null = null,\n private readonly loggerFactory: JsFixLoggerFactory = defaultLoggerFactory\n ) {\n this.logger = this.loggerFactory.logger('launcher')\n this.initiatorConfig = initiatorConfig ? this.loadConfig(initiatorConfig) : null\n this.acceptorConfig = acceptorConfig ? this.loadConfig(acceptorConfig) : null\n }\n\n // the arrow defers to makeSessionMsgFactory at resolve time, so a subclass need\n // only override that one method - no SessionContainer subclass required\n protected sessionContainer: SessionContainer =\n new SessionContainer((d: ISessionDescription) => this.makeSessionMsgFactory(d))\n\n /**\n * Override to supply this application's own session message factory - the place to\n * put a Logon carrying tags the standard message does not, or a header a\n * counterparty stamps differently. Return null (the default) for the stock\n * factory.\n *\n * For a Logon that only needs extra fields, prefer the \"Logon\" block in the session\n * description - it needs no code at all. Reach for a factory when the values are\n * computed at run time (a signature, a nonce, a token fetched at start up).\n */\n protected makeSessionMsgFactory (_description: ISessionDescription): ISessionMsgFactory | null {\n return null\n }\n\n private async empty (): Promise<any> {\n return await new Promise((resolve, reject) => {\n try {\n setImmediate(() => {\n this.logger.info('resolving an empty promise')\n resolve(null)\n })\n } catch (e) {\n reject(e)\n }\n })\n }\n\n private acceptorEntity: FixEntity | null = null\n private stopRequested: boolean = false\n\n protected async getAcceptor (sessionContainer: DependencyContainer): Promise<any> {\n if (sessionContainer.isRegistered<FixEntity>(DITokens.FixEntity)) {\n const entity = sessionContainer.resolve<FixEntity>(DITokens.FixEntity)\n this.acceptorEntity = entity\n // a stop can arrive while the container is still being built - the listener has\n // no existence yet to close, so honour the request by never opening it\n if (this.stopRequested) {\n this.logger.info('stop requested before the acceptor started - not listening')\n return this.empty()\n }\n return entity.start()\n } else {\n return this.empty()\n }\n }\n\n protected async getInitiator (sessionContainer: DependencyContainer): Promise<any> {\n if (sessionContainer.isRegistered<FixEntity>(DITokens.FixEntity)) {\n const entity = sessionContainer.resolve<FixEntity>(DITokens.FixEntity)\n return entity.start()\n } else {\n return this.empty()\n }\n }\n\n /**\n * provide a factory which will be invoked with a config where an instance of the application\n * should be constructed and returned.\n * @param config to be provided to the constucted application representing this session\n * @protected\n */\n protected makeFactory (config: IJsFixConfig): EngineFactory | null {\n return null\n }\n\n /**\n * Stop what this launcher started - in practice, close the acceptor's listener.\n *\n * An acceptor is meant to outlive any one counterparty, so nothing closes its\n * listener on its own. That is right for a venue and wrong for an application\n * which knows it is finished: the listening socket alone keeps node alive, long\n * after every session has logged out and every transport has been harvested.\n *\n * Until now the only caller was the both-roles branch of setup() below, which an\n * application cannot reach once it gives the acceptor a launcher of its own - the\n * usual arrangement as soon as more than one client is involved. There was then\n * no way to shut a listener down short of killing the process.\n *\n * Safe before start (the request is remembered and the listener never opens), and\n * safe to call twice. run() resolves once the listener has closed.\n */\n public stop (): void {\n this.stopRequested = true\n this.stopAcceptor()\n }\n\n public async run (): Promise<boolean> {\n return await new Promise<any>((resolve, reject) => {\n const logger = this.logger\n logger.info('launching ..')\n this.setup().then(() => {\n logger.info('.. done')\n resolve(true)\n }).catch((e: Error) => {\n logger.error(e)\n reject(e)\n })\n })\n }\n\n public exec (): void {\n this.run().then(() => {\n console.log('finished.')\n }).catch(e => {\n console.error(e)\n })\n }\n\n /**\n * is this session config representing an ascii based session\n * @param description config to be tested.\n */\n public isAscii (description: ISessionDescription): boolean {\n return this.sessionContainer.isAscii(description)\n }\n\n /**\n * is this session config representing an initiator based session\n * @param description config to be tested.\n */\n public isInitiator (description: ISessionDescription): boolean {\n return this.sessionContainer.isInitiator(description)\n }\n\n protected registerApplication (_: DependencyContainer): void {\n this.logger.info('bypass register via DI')\n }\n\n private async makeSystem (description: ISessionDescription): Promise<DependencyContainer> {\n const name = description.application?.name ?? 'na'\n const protocol = description.application?.protocol ?? 'ascii'\n this.logger.info(`creating app ${name} [protocol ${protocol}]`)\n return await this.sessionContainer.makeSystem(description)\n }\n\n private register (container: DependencyContainer): void {\n const config = container.resolve<IJsFixConfig>(DITokens.IJsFixConfig)\n const factory = this.makeFactory(config)\n if (!factory) {\n this.registerApplication(container)\n } else {\n if (factory.makeSession) {\n // resolve the config from the container doing the resolving, not the one\n // captured here. An acceptor resolves each session from a per-connection\n // child scope which re-registers IJsFixConfig, so this is how an application\n // receives that session's own description, store and message factory.\n container.register<FixSession>(DITokens.FixSession, {\n useFactory: (c) => factory.makeSession(c.resolve<IJsFixConfig>(DITokens.IJsFixConfig))\n })\n }\n }\n }\n\n private async makeClient (): Promise<any> {\n if (!this.initiatorConfig) return\n const sessionContainer = await this.makeSystem(this.initiatorConfig)\n this.register(sessionContainer)\n this.logger.info('create initiator')\n return await this.getInitiator(sessionContainer)\n }\n\n private async makeServer (): Promise<any> {\n if (!this.acceptorConfig) return\n const sessionContainer = await this.makeSystem(this.acceptorConfig)\n this.register(sessionContainer)\n this.logger.info('create acceptor')\n return await this.getAcceptor(sessionContainer)\n }\n\n async serverOrEmpty (): Promise<any> {\n return this.acceptorConfig ? this.makeServer() : this.empty()\n }\n\n async clientOrEmpty (): Promise<any> {\n return this.initiatorConfig ? this.makeClient() : this.empty()\n }\n\n private async setup (): Promise<any> {\n this.sessionContainer.registerGlobal(this.loggerFactory)\n const server = this.serverOrEmpty()\n const client = this.clientOrEmpty()\n this.logger.info('launching ....')\n if (this.acceptorConfig && this.initiatorConfig) {\n // Both mode: client drives the lifecycle. When client finishes,\n // stop the acceptor so the process can exit cleanly.\n await client\n this.logger.info('client finished, stopping acceptor')\n this.stop()\n return true\n }\n return await Promise.all([server, client])\n }\n\n private stopAcceptor (): void {\n const entity = this.acceptorEntity as any\n if (entity && typeof entity.stop === 'function') {\n entity.stop()\n }\n }\n\n private loadConfig (config: string | ISessionDescription): ISessionDescription {\n if (typeof config === 'string') {\n return require(path.join(this.root, config))\n }\n return config\n }\n}\n"]}
|
package/docs/acceptor.md
CHANGED
|
@@ -199,6 +199,38 @@ asks for a resend, the stored bodies are replayed with `PossDupFlag=Y`.
|
|
|
199
199
|
Because the store is keyed on `SessionId`, a wildcard acceptor recovers each
|
|
200
200
|
counterparty independently.
|
|
201
201
|
|
|
202
|
+
## Closing the listener
|
|
203
|
+
|
|
204
|
+
An acceptor outlives its counterparties. A session ending closes nothing: the
|
|
205
|
+
listener stays up, waiting for the next connection, which is the whole point of a
|
|
206
|
+
venue and why `TcpAcceptorListener` never stops itself.
|
|
207
|
+
|
|
208
|
+
The consequence is worth stating plainly, because it does not look like a decision
|
|
209
|
+
from the outside — **a listening socket keeps node alive on its own**. Every session
|
|
210
|
+
can log out, every transport can be harvested, the census can read `transports=0
|
|
211
|
+
sessions=0`, and the process still will not exit. Nothing is stuck; there is simply
|
|
212
|
+
one handle left, and only the application knows when it no longer wants it.
|
|
213
|
+
|
|
214
|
+
`SessionLauncher.stop()` closes it:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
const venue = new MyLauncher(null, acceptorDescription)
|
|
218
|
+
const run = venue.run() // resolves when the listener closes, not before
|
|
219
|
+
|
|
220
|
+
process.once('SIGINT', () => { venue.stop() })
|
|
221
|
+
await run // ... and now the process can end
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`stop()` releases any live transports rather than waiting on them — `net.Server.close`
|
|
225
|
+
alone would block on whichever counterparty happened to be connected, and forever on
|
|
226
|
+
a half-open one. It is safe before the listener has opened (the request is remembered
|
|
227
|
+
and it never opens) and safe to call twice.
|
|
228
|
+
|
|
229
|
+
A launcher given *both* roles calls this for you when its client finishes, which is
|
|
230
|
+
why a single-launcher sample exits by itself. An application that gives its acceptor a
|
|
231
|
+
launcher of its own — the usual arrangement once more than one client is involved —
|
|
232
|
+
owns that decision, and must say when.
|
|
233
|
+
|
|
202
234
|
## See also
|
|
203
235
|
|
|
204
236
|
- [`src/transport/tcp/tcp-acceptor.ts`](../src/transport/tcp/tcp-acceptor.ts) — listener, transport lifecycle
|
package/jsfix.test_client.txt
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
2
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
3
|
-
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
4
|
-
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-
|
|
5
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
6
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
7
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
8
|
-
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
9
|
-
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-
|
|
10
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
11
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
12
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
13
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
14
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
15
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
16
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
17
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
18
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
19
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
20
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
21
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
22
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
23
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260808-
|
|
24
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
25
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-
|
|
26
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
27
|
-
8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
28
|
-
8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
29
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
30
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
31
|
-
8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
32
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
33
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
34
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
35
|
-
8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
36
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
37
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
38
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
39
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
40
|
-
8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
41
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
42
|
-
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
43
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
44
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
45
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
46
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
47
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
48
|
-
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
49
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
50
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
51
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260808-
|
|
52
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-
|
|
53
|
-
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
54
|
-
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
55
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
56
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
57
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
58
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260808-
|
|
59
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
60
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:
|
|
61
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:
|
|
62
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:
|
|
1
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:10.991|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=101|
|
|
2
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:10.996|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=154|
|
|
3
|
+
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:10.997|7=1|16=1|10=242|
|
|
4
|
+
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-21:05:11.002|122=20260808-21:05:11.001|123=Y|36=2|10=070|
|
|
5
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:13.000|58=5|10=196|
|
|
6
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:15.791|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
|
|
7
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:15.793|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=154|
|
|
8
|
+
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:15.793|7=1|16=0|10=240|
|
|
9
|
+
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-21:05:15.796|122=20260808-21:05:15.795|123=Y|36=2|10=118|
|
|
10
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:17.795|58=5|10=221|
|
|
11
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:20.270|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=092|
|
|
12
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:20.272|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=142|
|
|
13
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:20.272|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=095|
|
|
14
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:20.802|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=093|
|
|
15
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:20.804|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=143|
|
|
16
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:21.806|58=5|10=209|
|
|
17
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:05:22.274|58=5|10=210|
|
|
18
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:24.510|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=093|
|
|
19
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:24.511|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=142|
|
|
20
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:25.513|58=5|10=208|
|
|
21
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:28.267|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
|
|
22
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:28.268|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
|
|
23
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260808-21:05:29.269|58=5|10=218|
|
|
24
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:31.756|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
|
|
25
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-21:05:31.758|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=157|
|
|
26
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:32.760|58=5|10=210|
|
|
27
|
+
8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:35.230|98=0|141=Y|553=js-client|554=pwd-client|10=162|
|
|
28
|
+
8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:35.232|45=1|372=A|373=1|58=msgType A missing required tag 108|10=253|
|
|
29
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:39.805|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
|
|
30
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:39.807|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=156|
|
|
31
|
+
8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:39.809|45=2|372=ZZ|373=11|58=msgType ZZ unknown|10=159|
|
|
32
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:05:41.809|58=5|10=215|
|
|
33
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:44.541|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=099|
|
|
34
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:44.542|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=148|
|
|
35
|
+
8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:44.544|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 143|10=072|
|
|
36
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:05:46.545|58=5|10=217|
|
|
37
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:48.542|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
|
|
38
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:53.038|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=100|
|
|
39
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:53.040|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=141|
|
|
40
|
+
8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:53.041|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 59|10=021|
|
|
41
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:05:55.041|58=5|10=208|
|
|
42
|
+
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:57.513|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=052|
|
|
43
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:57.514|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=151|
|
|
44
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:59.518|112=Sat, 08 Aug 2026 21:05:59 GMT|10=151|
|
|
45
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:06:01.522|112=Sat, 08 Aug 2026 21:06:01 GMT|10=123|
|
|
46
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:06:03.517|58=5|10=209|
|
|
47
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:06:05.983|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=107|
|
|
48
|
+
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:06:05.984|98=0|108=2|141=Y|553=js-server|554=pwd-server|10=106|
|
|
49
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:06:07.988|112=Sat, 08 Aug 2026 21:06:07 GMT|10=150|
|
|
50
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:06:09.990|112=Sat, 08 Aug 2026 21:06:09 GMT|10=148|
|
|
51
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260808-21:06:11.994|112=Sat, 08 Aug 2026 21:06:11 GMT|10=139|
|
|
52
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-21:06:13.987|58=5|10=224|
|
|
53
|
+
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:06:16.697|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=061|
|
|
54
|
+
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:06:16.698|98=0|108=5|141=Y|553=js-server|554=pwd-server|10=113|
|
|
55
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:06:18.703|112=Sat, 08 Aug 2026 21:06:18 GMT|10=139|
|
|
56
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:06:20.707|112=Sat, 08 Aug 2026 21:06:20 GMT|10=130|
|
|
57
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:06:21.711|112=Sat, 08 Aug 2026 21:06:21 GMT|10=126|
|
|
58
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260808-21:06:22.713|112=Sat, 08 Aug 2026 21:06:22 GMT|10=132|
|
|
59
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:06:24.700|58=5|10=207|
|
|
60
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:08:32.932|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
|
|
61
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:08:32.941|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=151|
|
|
62
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:08:33.946|58=5|10=220|
|
package/jsfix.test_server.txt
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
2
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
3
|
-
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
4
|
-
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-
|
|
5
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
6
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
7
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
8
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
9
|
-
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
10
|
-
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-
|
|
11
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
12
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
13
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
14
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
15
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
16
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
17
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
18
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
19
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
20
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
21
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
22
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
23
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
24
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
25
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
26
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260808-
|
|
27
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
28
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-
|
|
29
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
30
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
31
|
-
8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
32
|
-
8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
33
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
34
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
1
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:10.991|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=101|
|
|
2
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:10.996|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=154|
|
|
3
|
+
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:10.997|7=1|16=1|10=242|
|
|
4
|
+
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-21:05:11.002|122=20260808-21:05:11.001|123=Y|36=2|10=070|
|
|
5
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:05:12.999|58=5|10=223|
|
|
6
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:13.000|58=5|10=196|
|
|
7
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:15.791|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
|
|
8
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:15.793|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=154|
|
|
9
|
+
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:15.793|7=1|16=0|10=240|
|
|
10
|
+
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260808-21:05:15.796|122=20260808-21:05:15.795|123=Y|36=2|10=118|
|
|
11
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:05:17.794|58=5|10=221|
|
|
12
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:17.795|58=5|10=221|
|
|
13
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:20.270|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=092|
|
|
14
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:20.272|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=142|
|
|
15
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:20.272|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=095|
|
|
16
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:20.802|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=093|
|
|
17
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:20.804|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=143|
|
|
18
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:21.805|58=5|10=208|
|
|
19
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:21.806|58=5|10=209|
|
|
20
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:24.510|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=093|
|
|
21
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:24.511|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=142|
|
|
22
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:25.512|58=5|10=207|
|
|
23
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:25.513|58=5|10=208|
|
|
24
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:28.267|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
|
|
25
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:28.268|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
|
|
26
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260808-21:05:29.269|58=5|10=218|
|
|
27
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:31.756|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
|
|
28
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-21:05:31.758|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=157|
|
|
29
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:32.759|58=5|10=218|
|
|
30
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:32.760|58=5|10=210|
|
|
31
|
+
8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:35.230|98=0|141=Y|553=js-client|554=pwd-client|10=162|
|
|
32
|
+
8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:35.232|45=1|372=A|373=1|58=msgType A missing required tag 108|10=253|
|
|
33
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:39.805|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
|
|
34
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:39.807|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=156|
|
|
35
35
|
8=FIX4.4|9=0000136|35=ZZ|49=init-comp|56=accept-comp|34=2|57=fix|52=20180902-12:25:28.980|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=177|
|
|
36
|
-
8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
37
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
38
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
39
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
40
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
36
|
+
8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:39.809|45=2|372=ZZ|373=11|58=msgType ZZ unknown|10=159|
|
|
37
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:05:41.808|58=5|10=214|
|
|
38
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:05:41.809|58=5|10=215|
|
|
39
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:44.541|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=099|
|
|
40
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:44.542|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=148|
|
|
41
41
|
8=FIX4.4|9=0000123|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20180902-12:25:59.161|999=Sun, 02 Sep 2018 12:25:59 GMT|10=95|
|
|
42
|
-
8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
43
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
44
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
45
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
46
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
42
|
+
8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:44.544|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 143|10=072|
|
|
43
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:05:46.544|58=5|10=216|
|
|
44
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:05:46.545|58=5|10=217|
|
|
45
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:53.038|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=100|
|
|
46
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:53.040|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=141|
|
|
47
47
|
8=FIX4.4|9=0000123|35=0|49=init-not!|56=accept-comp|34=2|57=fix|52=20180902-12:25:59.161|112=Sun, 02 Sep 2018 12:25:59 GMT|10=95|
|
|
48
|
-
8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
49
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
50
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
51
|
-
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
52
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
53
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
54
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
55
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=4|57=fix|52=20260808-
|
|
56
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
57
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
58
|
-
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
59
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
60
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
61
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260808-
|
|
62
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
63
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-
|
|
64
|
-
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-
|
|
65
|
-
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-
|
|
66
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-
|
|
67
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-
|
|
68
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-
|
|
69
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260808-
|
|
70
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=5|57=fix|52=20260808-
|
|
71
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-
|
|
72
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:
|
|
73
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:
|
|
74
|
-
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:
|
|
75
|
-
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:
|
|
48
|
+
8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:05:53.041|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 59|10=021|
|
|
49
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:05:55.040|58=5|10=207|
|
|
50
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:05:55.041|58=5|10=208|
|
|
51
|
+
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:05:57.513|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=052|
|
|
52
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:05:57.514|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=151|
|
|
53
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:05:59.518|112=Sat, 08 Aug 2026 21:05:59 GMT|10=151|
|
|
54
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:06:01.522|112=Sat, 08 Aug 2026 21:06:01 GMT|10=123|
|
|
55
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=4|57=fix|52=20260808-21:06:03.516|58=5|10=210|
|
|
56
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:06:03.517|58=5|10=209|
|
|
57
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:06:05.983|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=107|
|
|
58
|
+
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:06:05.984|98=0|108=2|141=Y|553=js-server|554=pwd-server|10=106|
|
|
59
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:06:07.988|112=Sat, 08 Aug 2026 21:06:07 GMT|10=150|
|
|
60
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:06:09.990|112=Sat, 08 Aug 2026 21:06:09 GMT|10=148|
|
|
61
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260808-21:06:11.994|112=Sat, 08 Aug 2026 21:06:11 GMT|10=139|
|
|
62
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:06:13.986|58=5|10=220|
|
|
63
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260808-21:06:13.987|58=5|10=224|
|
|
64
|
+
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:06:16.697|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=061|
|
|
65
|
+
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:06:16.698|98=0|108=5|141=Y|553=js-server|554=pwd-server|10=113|
|
|
66
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:06:18.703|112=Sat, 08 Aug 2026 21:06:18 GMT|10=139|
|
|
67
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260808-21:06:20.707|112=Sat, 08 Aug 2026 21:06:20 GMT|10=130|
|
|
68
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:06:21.711|112=Sat, 08 Aug 2026 21:06:21 GMT|10=126|
|
|
69
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260808-21:06:22.713|112=Sat, 08 Aug 2026 21:06:22 GMT|10=132|
|
|
70
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=5|57=fix|52=20260808-21:06:24.699|58=5|10=226|
|
|
71
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260808-21:06:24.700|58=5|10=207|
|
|
72
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260808-21:08:32.932|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
|
|
73
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260808-21:08:32.941|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=151|
|
|
74
|
+
8=FIX.4.4|9=0000075|35=5|49=init-comp|56=accept-comp|34=2|57=fix|52=20260808-21:08:33.944|58=5|10=218|
|
|
75
|
+
8=FIX.4.4|9=0000075|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260808-21:08:33.946|58=5|10=220|
|
package/package.json
CHANGED
|
@@ -57,11 +57,18 @@ export abstract class SessionLauncher {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
private acceptorEntity: FixEntity | null = null
|
|
60
|
+
private stopRequested: boolean = false
|
|
60
61
|
|
|
61
62
|
protected async getAcceptor (sessionContainer: DependencyContainer): Promise<any> {
|
|
62
63
|
if (sessionContainer.isRegistered<FixEntity>(DITokens.FixEntity)) {
|
|
63
64
|
const entity = sessionContainer.resolve<FixEntity>(DITokens.FixEntity)
|
|
64
65
|
this.acceptorEntity = entity
|
|
66
|
+
// a stop can arrive while the container is still being built - the listener has
|
|
67
|
+
// no existence yet to close, so honour the request by never opening it
|
|
68
|
+
if (this.stopRequested) {
|
|
69
|
+
this.logger.info('stop requested before the acceptor started - not listening')
|
|
70
|
+
return this.empty()
|
|
71
|
+
}
|
|
65
72
|
return entity.start()
|
|
66
73
|
} else {
|
|
67
74
|
return this.empty()
|
|
@@ -87,6 +94,27 @@ export abstract class SessionLauncher {
|
|
|
87
94
|
return null
|
|
88
95
|
}
|
|
89
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Stop what this launcher started - in practice, close the acceptor's listener.
|
|
99
|
+
*
|
|
100
|
+
* An acceptor is meant to outlive any one counterparty, so nothing closes its
|
|
101
|
+
* listener on its own. That is right for a venue and wrong for an application
|
|
102
|
+
* which knows it is finished: the listening socket alone keeps node alive, long
|
|
103
|
+
* after every session has logged out and every transport has been harvested.
|
|
104
|
+
*
|
|
105
|
+
* Until now the only caller was the both-roles branch of setup() below, which an
|
|
106
|
+
* application cannot reach once it gives the acceptor a launcher of its own - the
|
|
107
|
+
* usual arrangement as soon as more than one client is involved. There was then
|
|
108
|
+
* no way to shut a listener down short of killing the process.
|
|
109
|
+
*
|
|
110
|
+
* Safe before start (the request is remembered and the listener never opens), and
|
|
111
|
+
* safe to call twice. run() resolves once the listener has closed.
|
|
112
|
+
*/
|
|
113
|
+
public stop (): void {
|
|
114
|
+
this.stopRequested = true
|
|
115
|
+
this.stopAcceptor()
|
|
116
|
+
}
|
|
117
|
+
|
|
90
118
|
public async run (): Promise<boolean> {
|
|
91
119
|
return await new Promise<any>((resolve, reject) => {
|
|
92
120
|
const logger = this.logger
|
|
@@ -188,7 +216,7 @@ export abstract class SessionLauncher {
|
|
|
188
216
|
// stop the acceptor so the process can exit cleanly.
|
|
189
217
|
await client
|
|
190
218
|
this.logger.info('client finished, stopping acceptor')
|
|
191
|
-
this.
|
|
219
|
+
this.stop()
|
|
192
220
|
return true
|
|
193
221
|
}
|
|
194
222
|
return await Promise.all([server, client])
|