func (s *sessionRegistry) leaveSession(party *party) error {
	sess := party.s
	s.Lock()
	defer s.Unlock()

	// remove from in-memory representation of the session:
	if err := sess.removeParty(party); err != nil {
		return trace.Wrap(err)
	}

	// emit "session leave" event (party left the session)
	s.srv.EmitAuditEvent(events.SessionLeaveEvent, events.EventFields{
		events.SessionEventID:  string(sess.id),
		events.EventUser:       party.user,
		events.SessionServerID: party.serverID,
	})

	// this goroutine runs for a short amount of time only after a session
	// becomes empty (no parties). It allows session to "linger" for a bit
	// allowing parties to reconnect if they lost connection momentarily
	lingerAndDie := func() {
		lingerTTL := sess.GetLingerTTL()
		if lingerTTL > 0 {
			time.Sleep(lingerTTL)
		}
		// not lingering anymore? someone reconnected? cool then... no need
		// to die...
		if !sess.isLingering() {
			log.Infof("[session.registry] session %v becomes active again", sess.id)
			return
		}
		log.Infof("[session.registry] session %v to be garbage collected", sess.id)

		// no more people left? Need to end the session!
		s.Lock()
		delete(s.sessions, sess.id)
		s.Unlock()

		// send an event indicating that this session has ended
		s.srv.EmitAuditEvent(events.SessionEndEvent, events.EventFields{
			events.SessionEventID: string(sess.id),
			events.EventUser:      party.user,
		})
		if err := sess.Close(); err != nil {
			log.Error(err)
		}

		// mark it as inactive in the DB
		if s.srv.sessionServer != nil {
			False := false
			s.srv.sessionServer.UpdateSession(rsession.UpdateRequest{
				ID:     sess.id,
				Active: &False,
			})
		}
	}
	go lingerAndDie()
	return nil
}
// leaveSession removes the given party from this session
leaveSession removes the given party from this session
// leaveSession removes the given party from this session
func (s *sessionRegistry) leaveSession(party *party) error {
	sess := party.s
	s.Lock()
	defer s.Unlock()
	if err := sess.removeParty(party); err != nil {
		return trace.Wrap(err)
	}
	s.srv.EmitAuditEvent(events.SessionLeaveEvent, events.EventFields{
		events.SessionEventID:  string(sess.id),
		events.EventUser:       party.user,
		events.SessionServerID: party.serverID,
	})
	lingerAndDie := func() {
		lingerTTL := sess.GetLingerTTL()
		if lingerTTL > 0 {
			time.Sleep(lingerTTL)
		}
		if !sess.isLingering() {
			log.Infof("[session.registry] session %v becomes active again", sess.id)
			return
		}
		log.Infof("[session.registry] session %v to be garbage collected", sess.id)
		s.Lock()
		delete(s.sessions, sess.id)
		s.Unlock()
		s.srv.EmitAuditEvent(events.SessionEndEvent, events.EventFields{
			events.SessionEventID: string(sess.id),
			events.EventUser:      party.user,
		})
		if err := sess.Close(); err != nil {
			log.Error(err)
		}
		if s.srv.sessionServer != nil {
			False := false
			s.srv.sessionServer.UpdateSession(rsession.UpdateRequest{
				ID:     sess.id,
				Active: &False,
			})
		}
	}
	go lingerAndDie()
	return nil
}
func ( s * sessionRegistry ) leaveSession ( party * party ) error { sess := party . s s . Lock ( ) defer s . Unlock ( ) if err := sess . removeParty ( party ) ; err != nil { return trace . Wrap ( err ) } s . srv . EmitAuditEvent ( events . SessionLeaveEvent , events . EventFields { events . SessionEventID : string ( sess . id ) , events . EventUser : party . user , events . SessionServerID : party . serverID , } ) lingerAndDie := func ( ) { lingerTTL := sess . GetLingerTTL ( ) if lingerTTL > 0 { time . Sleep ( lingerTTL ) } if ! sess . isLingering ( ) { log . Infof ( " " , sess . id ) return } log . Infof ( " " , sess . id ) s . Lock ( ) delete ( s . sessions , sess . id ) s . Unlock ( ) s . srv . EmitAuditEvent ( events . SessionEndEvent , events . EventFields { events . SessionEventID : string ( sess . id ) , events . EventUser : party . user , } ) if err := sess . Close ( ) ; err != nil { log . Error ( err ) } if s . srv . sessionServer != nil { False := false s . srv . sessionServer . UpdateSession ( rsession . UpdateRequest { ID : sess . id , Active : & False , } ) } } go lingerAndDie ( ) return nil }
leaveSession removes the given party from this session
leaveSession removes the given party from this session
// remove from in-memory representation of the session: // emit "session leave" event (party left the session) // this goroutine runs for a short amount of time only after a session // becomes empty (no parties). It allows session to "linger" for a bit // allowing parties to reconnect if they lost connection momentarily // not lingering anymore? someone reconnected? cool then... no need // to die... // no more people left? Need to end the session! // send an event indicating that this session has ended // mark it as inactive in the DB