Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expose state #18

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion in_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

type inSession struct{ loggedOn }

func (state inSession) String() string { return "In Session" }
func (state inSession) String() string { return SessionStateInSession }

func (state inSession) FixMsgIn(session *session, msg *Message) sessionState {
msgType, err := msg.Header.GetBytes(tagMsgType)
Expand Down
18 changes: 18 additions & 0 deletions initiator.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ func (i *Initiator) Stop() {
i.wg.Wait()
}

func (i *Initiator) IsConnectedAndLoggedOn(sessionID SessionID) bool {
session, ok := i.sessions[sessionID]
if !ok {
return false
}

return session.IsConnected() && session.IsLoggedOn()
}

func (i *Initiator) SessionState(sessionID SessionID) string {
session, ok := i.sessions[sessionID]
if !ok {
return SessionStateUnknown
}

return session.State.String()
}

// NewInitiator creates and initializes a new Initiator.
func NewInitiator(app Application, storeFactory MessageStoreFactory, appSettings *Settings, logFactory LogFactory) (*Initiator, error) {
i := &Initiator{
Expand Down
2 changes: 1 addition & 1 deletion latent_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "github.com/quickfixgo/quickfix/internal"

type latentState struct{ inSessionTime }

func (state latentState) String() string { return "Latent State" }
func (state latentState) String() string { return SessionStateLatentState }
func (state latentState) IsLoggedOn() bool { return false }
func (state latentState) IsConnected() bool { return false }

Expand Down
2 changes: 1 addition & 1 deletion logon_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

type logonState struct{ connectedNotLoggedOn }

func (s logonState) String() string { return "Logon State" }
func (s logonState) String() string { return SessionStateLogonState }

func (s logonState) FixMsgIn(session *session, msg *Message) (nextState sessionState) {
msgType, err := msg.Header.GetBytes(tagMsgType)
Expand Down
2 changes: 1 addition & 1 deletion logout_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "github.com/quickfixgo/quickfix/internal"

type logoutState struct{ connectedNotLoggedOn }

func (state logoutState) String() string { return "Logout State" }
func (state logoutState) String() string { return SessionStateLogoutState }

func (state logoutState) FixMsgIn(session *session, msg *Message) (nextState sessionState) {
nextState = inSession{}.FixMsgIn(session, msg)
Expand Down
2 changes: 1 addition & 1 deletion not_session_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "github.com/quickfixgo/quickfix/internal"

type notSessionTime struct{ latentState }

func (notSessionTime) String() string { return "Not session time" }
func (notSessionTime) String() string { return SessionStateNotSessionTime }
func (notSessionTime) IsSessionTime() bool { return false }

func (state notSessionTime) FixMsgIn(session *session, msg *Message) (nextState sessionState) {
Expand Down
2 changes: 1 addition & 1 deletion resend_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type resendState struct {
resendRangeEnd int
}

func (s resendState) String() string { return "Resend" }
func (s resendState) String() string { return SessionStateResend }

func (s resendState) Timeout(session *session, event internal.Event) (nextState sessionState) {
nextState = inSession{}.Timeout(session, event)
Expand Down
4 changes: 3 additions & 1 deletion session_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type sessionFactory struct {
BuildInitiators bool
}

//Creates Session, associates with internal session registry
// Creates Session, associates with internal session registry
func (f sessionFactory) createSession(
sessionID SessionID, storeFactory MessageStoreFactory, settings *SessionSettings,
logFactory LogFactory, application Application,
Expand Down Expand Up @@ -307,6 +307,8 @@ func (f sessionFactory) newSession(
s.messageEvent = make(chan bool, 1)
s.admin = make(chan interface{})
s.application = application
s.stateMachine = stateMachine{State: latentState{}}

return
}

Expand Down
14 changes: 12 additions & 2 deletions session_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,18 @@ func handleStateError(s *session, err error) sessionState {
return latentState{}
}

//sessionState is the current state of the session state machine. The session state determines how the session responds to
//incoming messages, timeouts, and requests to send application messages.
const (
SessionStateUnknown = "Unknown"
SessionStateLatentState = "Latent State"
SessionStateInSession = "In Session"
SessionStateLogonState = "Logon State"
SessionStateLogoutState = "Logout State"
SessionStateNotSessionTime = "Not session time"
SessionStateResend = "Resend"
)

// sessionState is the current state of the session state machine. The session state determines how the session responds to
// incoming messages, timeouts, and requests to send application messages.
type sessionState interface {
//FixMsgIn is called by the session on incoming messages from the counter party. The return type is the next session state
//following message processing
Expand Down
31 changes: 31 additions & 0 deletions session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package quickfix

import (
"bytes"
"reflect"
"testing"
"time"

Expand Down Expand Up @@ -956,3 +957,33 @@ func (suite *SessionSendTestSuite) TestDropAndSendDropsQueueWithReset() {
suite.LastToAdminMessageSent()
suite.NoMessageSent()
}

func TestSessionState(t *testing.T) {
type wants struct {
connected bool
loggedOn bool
}

tests := []struct {
name string
state sessionState
want wants
}{
{name: "latentState", state: latentState{}, want: wants{connected: false, loggedOn: false}},
{name: "logonState", state: logonState{}, want: wants{connected: true, loggedOn: false}},
{name: "inSession", state: inSession{}, want: wants{connected: true, loggedOn: true}},
{name: "logoutState", state: logoutState{}, want: wants{connected: true, loggedOn: false}},
{name: "resendState", state: resendState{}, want: wants{connected: true, loggedOn: true}},
{name: "pendingTimeout", state: pendingTimeout{inSession{}}, want: wants{connected: true, loggedOn: true}},
{name: "notSessionTime", state: notSessionTime{}, want: wants{connected: false, loggedOn: false}},
}

for _, test := range tests {
if !reflect.DeepEqual(test.state.IsConnected(), test.want.connected) {
t.Errorf("%s.IsConnected() got = %v", test.name, test.state.IsConnected())
}
if !reflect.DeepEqual(test.state.IsLoggedOn(), test.want.loggedOn) {
t.Errorf("%s.IsLoggedOn() got = %v", test.name, test.state.IsLoggedOn())
}
}
}