Skip to content

Releases: sylvioCampos/fix-session-lab

v0.1.0 — eleven drills

Choose a tag to compare

@sylvioCampos sylvioCampos released this 03 Aug 20:24
9e9d498

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. session is unexported and Initiator.Stop() unregisters everything it owns, so a forced reconnect means building a new Initiator. The QuickFIX/J logout()-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 -race will catch.
  • Never reject a reject. Two applications that each reject unknown message types will ping-pong 35=j at 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 gives 35=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.