Releases: sylvioCampos/fix-session-lab
Release list
v0.1.0 — eleven drills
First tagged release. All eleven planned drills implemented, tested and documented.
What this is
A FIX 4.4 session boilerplate in Go built around a fake exchange you can command over HTTP. The session-layer failures you normally meet during a certification window — sequence gaps, resends, replayed messages, a session that is logged on and silent — reproduced with curl.
make up
curl -XPOST "localhost:8081/admin/gap?n=2000"The drills
| # | Drill |
|---|---|
| 01 | First logon — RawData auth, Text on Logon, keeping the password out of logs |
| 02 | Heartbeat & TestRequest — what "alive" proves, and what it does not |
| 03 | Rejected logon — why a refusal looks like a network fault |
| 04 | Order round trip — ExecType vs OrdStatus, cumulative vs incremental fields |
| 05 | Drop-copy fanout & dedup — why ExecID is the field everything hangs on |
| 06 | Sequence persistence — ResetOnLogon Y vs N |
| 07 | Gap & ResendRequest — recovery, and surviving PossDupFlag=Y |
| 08 | SequenceReset / GapFill — why admin messages are not replayed |
| 09 | Silent session & watchdog — the failure no FIX engine detects for you |
| 10 | Cancel on disconnect — and why the timeout window exists |
| 11 | Session-level Reject — 35=3 vs 35=j, and never rejecting a reject |
Findings that are not documented elsewhere
- quickfixgo has no per-session disconnect.
sessionis unexported andInitiator.Stop()unregisters everything it owns, so a forced reconnect means building a newInitiator. The QuickFIX/Jlogout()-vs-disconnect()trap cannot be written in Go; the Go trap is that you have no handle at all. Settings.SessionSettings()returns clones. Mutating what it hands back is a silent no-op.- The message stores carry no synchronization. Reading a sequence number from another goroutine is a data race
-racewill catch. - Never reject a reject. Two applications that each reject unknown message types will ping-pong
35=jat wire speed — 13,000 messages in six seconds, observed here. - Rejects split by reject reason, not severity. An out-of-range value gives
35=3; a missing conditionally-required field on the same message gives35=j.
Verified
CI runs the drills under -race and separately stands up the docker-compose stack, asserting both sessions log on, the fill reaches the drop copy, the password never appears unmasked, the drop-copy session emits no rejects, and sequence numbers survive docker compose restart.
Coverage 61.8%, measured with -coverpkg=./....
Not included
Throttling, scheduled session resets, NextExpectedMsgSeqNum (789) and TLS are tracked as issues #5–#8.
Attribution
MIT. Includes software developed by quickfixengine.org. Modeled on B3 EntryPoint; not affiliated with B3, and B3 specifications are referenced rather than reproduced.