<commit_before>// Ninchat API connection library.
//
// https://ninchat.com/api
//
package ninchat

import (
	"sort"
	"sync"
)

const (
	discoveryTimeout  = second * 7
	connectTimeout    = second * 9
	connectIterations = 2
	maxBackoffDelay   = second * 60

	sessionCreateTimeout = second * 37

	maxEventAckDelay  = second * 7
	maxEventAckWindow = 4096
)

var (
	sessionEventAckWindow = jitterInt64(maxEventAckWindow, -0.25)
)

// Session hides the details of API connection management.  It needs to be
// initialized by setting at least OnSessionEvent and OnEvent, and calling
// SetParams.  After that the Open method is used to make a connection to the
// server.  Finally, the Close method disconnects from the server.
type Session struct {
	// OnSessionEvent is the session creation handler.  It will be invoked with
	// a "session_created" or an "error" event.
	//
	// If another "session_created" event is received, it means that the previous
	// session was lost, and a new one was established automatically.
	//
	// If an "error" event is received, it means that a new session can't be
	// established without intervention.  The client code must call SetParams to
	// supply new credentials, unless it decides to Close.
	//
	OnSessionEvent func(*Event)

	// OnEvent is the handler for in-session events.
	//
	// "error" events received via this callback are not fatal.
	//
	OnEvent func(*Event)

	// OnClose is an optional session closure handler.  It will be invoked
	// after a Close call has been fully processed.  It won't be invoked if an
	// "error" event is received via OnSessionEvent (unless SetParams is called
	// again).
	//
	OnClose func()

	// OnConnState is an optional connection state change monitor.  It will be
	// called with one of the following strings:
	//
	// - "connecting"
	// - "connected"
	// - "disconnected"
	//
	OnConnState func(state string)

	// OnConnActive is an optional connection activity monitor.  It will be
	// called (approximately) when data is received on the underlying network
	// connection.
	OnConnActive func()

	// OnLog is an optional message logger.
	OnLog func(fragments ...interface{})

	// Header fields to be added to HTTP requests.  The keys must be in
	// canonical format (see https://golang.org/pkg/net/http/#CanonicalHeaderKey).
	Header map[string][]string

	Address string

	forceLongPoll bool // only for testing

	mutex sync.Mutex // guards all variables below

	sessionParams map[string]interface{}
	sessionId     interface{}

	latestConnState string

	lastActionId    int64
	sendNotify      chan struct{}
	sendBuffer      []*Action
	numSent         int
	sendEventAck    bool
	receivedEventId int64
	ackedEventId    int64

	closeNotify chan struct{}
	closed      bool
	running     bool

	test testSupport
}

// transport is an interface implemented by webSocketTransport and
// longPollTransport.
type transport func(s *Session, host string) (connWorked, gotOnline bool)

// SetParams sets "create_session" action parameters.  If Open has already been
// called, this takes effect when a session is lost.
func (s *Session) SetParams(params map[string]interface{}) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	if params["message_types"] == nil {
		panic("message_types parameter not defined")
	}

	if x, found := params["session_id"]; x != nil {
		s.sessionId = x
	} else if found {
		delete(params, "session_id")
	}

	s.sessionParams = params

	if s.sendNotify != nil && !s.running {
		// opened + stopped -> restart
		s.running = true
		go s.discover()
	}<commit_msg>SetParams doc mentions resume_session action<commit_after>// Ninchat API connection library.
//
// https://ninchat.com/api
//
package ninchat

import (
	"sort"
	"sync"
)

const (
	discoveryTimeout  = second * 7
	connectTimeout    = second * 9
	connectIterations = 2
	maxBackoffDelay   = second * 60

	sessionCreateTimeout = second * 37

	maxEventAckDelay  = second * 7
	maxEventAckWindow = 4096
)

var (
	sessionEventAckWindow = jitterInt64(maxEventAckWindow, -0.25)
)

// Session hides the details of API connection management.  It needs to be
// initialized by setting at least OnSessionEvent and OnEvent, and calling
// SetParams.  After that the Open method is used to make a connection to the
// server.  Finally, the Close method disconnects from the server.
type Session struct {
	// OnSessionEvent is the session creation handler.  It will be invoked with
	// a "session_created" or an "error" event.
	//
	// If another "session_created" event is received, it means that the previous
	// session was lost, and a new one was established automatically.
	//
	// If an "error" event is received, it means that a new session can't be
	// established without intervention.  The client code must call SetParams to
	// supply new credentials, unless it decides to Close.
	//
	OnSessionEvent func(*Event)

	// OnEvent is the handler for in-session events.
	//
	// "error" events received via this callback are not fatal.
	//
	OnEvent func(*Event)

	// OnClose is an optional session closure handler.  It will be invoked
	// after a Close call has been fully processed.  It won't be invoked if an
	// "error" event is received via OnSessionEvent (unless SetParams is called
	// again).
	//
	OnClose func()

	// OnConnState is an optional connection state change monitor.  It will be
	// called with one of the following strings:
	//
	// - "connecting"
	// - "connected"
	// - "disconnected"
	//
	OnConnState func(state string)

	// OnConnActive is an optional connection activity monitor.  It will be
	// called (approximately) when data is received on the underlying network
	// connection.
	OnConnActive func()

	// OnLog is an optional message logger.
	OnLog func(fragments ...interface{})

	// Header fields to be added to HTTP requests.  The keys must be in
	// canonical format (see https://golang.org/pkg/net/http/#CanonicalHeaderKey).
	Header map[string][]string

	Address string

	forceLongPoll bool // only for testing

	mutex sync.Mutex // guards all variables below

	sessionParams map[string]interface{}
	sessionId     interface{}

	latestConnState string

	lastActionId    int64
	sendNotify      chan struct{}
	sendBuffer      []*Action
	numSent         int
	sendEventAck    bool
	receivedEventId int64
	ackedEventId    int64

	closeNotify chan struct{}
	closed      bool
	running     bool

	test testSupport
}

// transport is an interface implemented by webSocketTransport and
// longPollTransport.
type transport func(s *Session, host string) (connWorked, gotOnline bool)

// SetParams sets initial action parameters.  The initial action is
// "create_session" by default, or "resume_session" if the "session_id"
// parameter is set.  If Open has already been called, this takes effect when a
// session is lost.
func (s *Session) SetParams(params map[string]interface{}) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	if params["message_types"] == nil {
		panic("message_types parameter not defined")
	}

	if x, found := params["session_id"]; x != nil {
		s.sessionId = x
	} else if found {
		delete(params, "session_id")
	}

	s.sessionParams = params

	if s.sendNotify != nil && !s.running {
		// opened + stopped -> restart
		s.running = true
		go s.discover()
	}
{'fraction_non_alphanumeric': 0.08977556109725686, 'fraction_numerical': 0.006372956497644777, 'mean_word_length': 3.3435619735258726, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6734371', 'n_tokens_mistral': 2183, 'n_tokens_neox': 2075, 'n_words': 833}