From 031416b5fe8a4c2cd9ea55e9a7cdbebbcfd35d39 Mon Sep 17 00:00:00 2001 From: Andreas Meisner Date: Mon, 26 Jan 2026 15:41:35 +0100 Subject: [PATCH 1/3] IMessageStore extended with method SetAndIncrNextSenderMsgSeqNum --- QuickFIXn/Session.cs | 7 +++++-- QuickFIXn/SessionState.cs | 5 +++++ QuickFIXn/Store/IMessageStore.cs | 7 +++++++ UnitTests/FileStoreTests.cs | 26 ++++++++++++++++++++++++++ UnitTests/MemoryStoreTest.cs | 19 +++++++++++++++++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/QuickFIXn/Session.cs b/QuickFIXn/Session.cs index 51c348046..f52a58bfd 100755 --- a/QuickFIXn/Session.cs +++ b/QuickFIXn/Session.cs @@ -1646,9 +1646,12 @@ protected void Persist(Message message, string messageString) if (PersistMessages) { SeqNumType msgSeqNum = message.Header.GetULong(Fields.Tags.MsgSeqNum); - _state.Set(msgSeqNum, messageString); + _state.SetAndIncrNextSenderMsgSeqNum(msgSeqNum, messageString); + } + else + { + _state.IncrNextSenderMsgSeqNum(); } - _state.IncrNextSenderMsgSeqNum(); } protected bool IsGoodTime(Message msg) diff --git a/QuickFIXn/SessionState.cs b/QuickFIXn/SessionState.cs index 38ce466d7..37de81096 100755 --- a/QuickFIXn/SessionState.cs +++ b/QuickFIXn/SessionState.cs @@ -399,6 +399,11 @@ public void Refresh() lock (_sync) { MessageStore.Refresh(); } } + public bool SetAndIncrNextSenderMsgSeqNum(SeqNumType msgSeqNum, string msg) + { + lock (_sync) { return MessageStore.SetAndIncrNextSenderMsgSeqNum(msgSeqNum, msg); } + } + #endregion public void Dispose() diff --git a/QuickFIXn/Store/IMessageStore.cs b/QuickFIXn/Store/IMessageStore.cs index 0a77f3539..3749e0a7b 100755 --- a/QuickFIXn/Store/IMessageStore.cs +++ b/QuickFIXn/Store/IMessageStore.cs @@ -48,4 +48,11 @@ public interface IMessageStore : IDisposable /// or throw an exception. /// void Refresh(); + + public bool SetAndIncrNextSenderMsgSeqNum(SeqNumType msgSeqNum, string msg) + { + bool result = Set(msgSeqNum, msg); + IncrNextSenderMsgSeqNum(); + return result; + } } diff --git a/UnitTests/FileStoreTests.cs b/UnitTests/FileStoreTests.cs index 6264c4d74..58ab063c0 100755 --- a/UnitTests/FileStoreTests.cs +++ b/UnitTests/FileStoreTests.cs @@ -208,4 +208,30 @@ public void GetTest() Assert.That(msgs, Is.EqualTo(expected)); } + + [Test] + public void SetAndIncrNextSenderMsgSeqNumTest() + { + IMessageStore messageStore = _store ?? throw new InvalidProgramException(); + + messageStore.SetAndIncrNextSenderMsgSeqNum(1, "dude"); + messageStore.SetAndIncrNextSenderMsgSeqNum(2, "pude"); + messageStore.SetAndIncrNextSenderMsgSeqNum(3, "ok"); + messageStore.SetAndIncrNextSenderMsgSeqNum(4, "ohai"); + + var msgs = new List(); + _store.Get(2, 3, msgs); + var expected = new List() { "pude", "ok" }; + + Assert.That(msgs, Is.EqualTo(expected)); + Assert.That(_store.NextSenderMsgSeqNum, Is.EqualTo(5)); + + RebuildStore(); + + msgs = new List(); + _store.Get(2, 3, msgs); + + Assert.That(msgs, Is.EqualTo(expected)); + Assert.That(_store.NextSenderMsgSeqNum, Is.EqualTo(5)); + } } diff --git a/UnitTests/MemoryStoreTest.cs b/UnitTests/MemoryStoreTest.cs index 43d521dc9..1512dd0ad 100644 --- a/UnitTests/MemoryStoreTest.cs +++ b/UnitTests/MemoryStoreTest.cs @@ -24,4 +24,23 @@ public void GetTest() store.Get(5, 6, msgs); Assert.That(msgs, Is.Empty); } + + [Test] + public void SetAndIncrNextSenderMsgSeqNumTest() + { + IMessageStore store = new MemoryStore(); + store.SetAndIncrNextSenderMsgSeqNum(1, "dude"); + store.SetAndIncrNextSenderMsgSeqNum(2, "pude"); + store.SetAndIncrNextSenderMsgSeqNum(3, "ok"); + store.SetAndIncrNextSenderMsgSeqNum(4, "ohai"); + var msgs = new List(); + store.Get(2, 3, msgs); + var expected = new List() { "pude", "ok" }; + Assert.That(msgs, Is.EqualTo(expected)); + + msgs = new List(); + store.Get(5, 6, msgs); + Assert.That(msgs, Is.Empty); + Assert.That(store.NextSenderMsgSeqNum, Is.EqualTo(5)); + } } From f82a537548cfd4816855f83cc44650217faadc91 Mon Sep 17 00:00:00 2001 From: Andreas Meisner Date: Mon, 26 Jan 2026 16:27:07 +0100 Subject: [PATCH 2/3] Adding missing documentation. --- QuickFIXn/Store/IMessageStore.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/QuickFIXn/Store/IMessageStore.cs b/QuickFIXn/Store/IMessageStore.cs index 3749e0a7b..7a35fd4ec 100755 --- a/QuickFIXn/Store/IMessageStore.cs +++ b/QuickFIXn/Store/IMessageStore.cs @@ -49,6 +49,16 @@ public interface IMessageStore : IDisposable /// void Refresh(); + /// + /// Adds a raw fix message to the store with the give sequence number + /// and increments the . This method + /// has a default implementation calling + /// and . It is not intended to change + /// this default implementation in custom IMessageStore implementations. + /// + /// the sequence number + /// the raw FIX message string + /// true if successful, false otherwise public bool SetAndIncrNextSenderMsgSeqNum(SeqNumType msgSeqNum, string msg) { bool result = Set(msgSeqNum, msg); From 79336ddad51c7c8c80f31626dba1215e718aed04 Mon Sep 17 00:00:00 2001 From: Grant Birchmeier Date: Wed, 8 Apr 2026 15:06:33 -0500 Subject: [PATCH 3/3] minor changes to IMessageStore.SetAndIncrNextSenderMsgSeqNum issue #987 / PR #993 --- QuickFIXn/SessionState.cs | 10 ++++----- QuickFIXn/Store/IMessageStore.cs | 38 +++++++++++++++++--------------- RELEASE_NOTES.md | 1 + 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/QuickFIXn/SessionState.cs b/QuickFIXn/SessionState.cs index 37de81096..a8cd350fb 100755 --- a/QuickFIXn/SessionState.cs +++ b/QuickFIXn/SessionState.cs @@ -373,6 +373,11 @@ public void IncrNextTargetMsgSeqNum() lock (_sync) { MessageStore.IncrNextTargetMsgSeqNum(); } } + public bool SetAndIncrNextSenderMsgSeqNum(SeqNumType msgSeqNum, string msg) + { + lock (_sync) { return MessageStore.SetAndIncrNextSenderMsgSeqNum(msgSeqNum, msg); } + } + public DateTime? CreationTime { get @@ -399,11 +404,6 @@ public void Refresh() lock (_sync) { MessageStore.Refresh(); } } - public bool SetAndIncrNextSenderMsgSeqNum(SeqNumType msgSeqNum, string msg) - { - lock (_sync) { return MessageStore.SetAndIncrNextSenderMsgSeqNum(msgSeqNum, msg); } - } - #endregion public void Dispose() diff --git a/QuickFIXn/Store/IMessageStore.cs b/QuickFIXn/Store/IMessageStore.cs index 7a35fd4ec..531a3e0d1 100755 --- a/QuickFIXn/Store/IMessageStore.cs +++ b/QuickFIXn/Store/IMessageStore.cs @@ -18,7 +18,7 @@ public interface IMessageStore : IDisposable void Get(SeqNumType startSeqNum, SeqNumType endSeqNum, List messages); /// - /// Adds a raw fix message to the store with the give sequence number + /// Adds a raw fix message to the store with the given sequence number /// /// the sequence number /// the raw FIX message string @@ -31,6 +31,24 @@ public interface IMessageStore : IDisposable void IncrNextSenderMsgSeqNum(); void IncrNextTargetMsgSeqNum(); + /// + /// The purpose of this method is to combine + /// and into one call, for use in situations + /// when these operations should be performed together. + /// The default implementation simply calls those two functions. + /// Certain custom IMessageStore implementations (e.g. DB-backed stores) + /// may need to override the default implementation to ensure that these two behaviors + /// are combined into a single atomic operation. + /// the sequence number + /// the raw FIX message string + /// true if successful, false otherwise + /// + bool SetAndIncrNextSenderMsgSeqNum(SeqNumType msgSeqNum, string msg) + { + bool result = Set(msgSeqNum, msg); + IncrNextSenderMsgSeqNum(); + return result; + } DateTime? CreationTime { get; } @@ -48,21 +66,5 @@ public interface IMessageStore : IDisposable /// or throw an exception. /// void Refresh(); - - /// - /// Adds a raw fix message to the store with the give sequence number - /// and increments the . This method - /// has a default implementation calling - /// and . It is not intended to change - /// this default implementation in custom IMessageStore implementations. - /// - /// the sequence number - /// the raw FIX message string - /// true if successful, false otherwise - public bool SetAndIncrNextSenderMsgSeqNum(SeqNumType msgSeqNum, string msg) - { - bool result = Set(msgSeqNum, msg); - IncrNextSenderMsgSeqNum(); - return result; - } } + diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f0fb39712..3edeb9378 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -38,6 +38,7 @@ What's New * #949 - new settings RedactFieldsInLogs & RedactionLogText (gbirchmeier) * #983 - new MessageFactoryNotFound exception provides better feedback (gbirchmeier) * #1014 - deprecate DateTimeConverter.ParseToTimeOnly (gbirchmeier) +* #987 - new interface method IMessageStore.SetAndIncrNextSenderMsgSeqNum (asmeisne) ### v1.14.0