agent.go 2.47 KB
package main

import (
	"github.com/golang/protobuf/proto"
	"math"
	"pro2d/common"
	"pro2d/common/components"
	"pro2d/common/logger"
	"pro2d/models"
	"pro2d/utils"
	"sync/atomic"
)

type Agent struct {
	components.IConnection
	Server components.IServer

	Role			*models.RoleModel


	Quit	  chan *Agent

	nextCheckTime   	int64 //下一次检查的时间
	lastHeartCheckTime 	int64
	heartTimeoutCount  	int   //超时次数
}

func NewAgent(s components.IServer) *Agent {
	return &Agent{
		Server:    s,

		Quit: make(chan *Agent),

		nextCheckTime:      0,
		lastHeartCheckTime: utils.Timex(),
		heartTimeoutCount:  0,
	}
}

func (c *Agent) OnConnection(conn components.IConnection)  {
	c.IConnection = conn
}

func (c *Agent) OnMessage(msg components.IMessage)  {
	atomic.StoreInt64(&c.lastHeartCheckTime, utils.Timex())
	md := c.Server.GetAction(msg.GetHeader().GetMsgID())
	if md == nil {
		logger.Debug("cmd: %d, md is nil", msg.GetHeader().GetMsgID())
		return
	}

	logger.Debug("protocode handler: %d", msg.GetHeader().GetMsgID())
	//fmt.Printf("errCode: %d, protomsg:%v\n", errCode, protomsg)

	f := md.(func (msg components.IMessage)  (int32, interface{}))
	errCode, protomsg := f(msg)
	rsp, err := proto.Marshal(protomsg.(proto.Message))
	if err != nil {
		conn := msg.GetSession()
		if conn != nil {
			conn.Send(-100, msg.GetHeader().GetMsgID(), nil)
		}
		return
	}
	conn := msg.GetSession()
	if conn != nil {
		conn.Send(errCode, msg.GetHeader().GetMsgID(), rsp)
	}
	return
	logger.Error("protocode not handler: %d", msg.GetHeader().GetMsgID())
}

func (c *Agent) OnTimer()  {
	nextCheckTime := atomic.LoadInt64(&c.nextCheckTime)
	now := utils.Timex()
	if now >= nextCheckTime {
		//检查心跳
		c.checkHeartBeat(now)
		nextCheckTime = now + common.HeartTimerInterval
		atomic.StoreInt64(&c.nextCheckTime, nextCheckTime)
	}

	if c.Role != nil {
		//role 恢复数据
		c.Role.OnRecoverTimer(now)
	}
}

func (c *Agent) OnClose()  {
	c.Close()
}

func (c *Agent) Close()  {
	if c.Role == nil {
		return
	}

	c.Role.OnOfflineEvent()
}

func (c *Agent) checkHeartBeat(now int64)  {
	lastHeartCheckTime := atomic.LoadInt64(&c.lastHeartCheckTime)
	logger.Debug("checkHeartBeat ID: %d, last: %d, now: %d", c.GetID(), lastHeartCheckTime, now)
	if math.Abs(float64(lastHeartCheckTime - now)) > common.HeartTimerInterval {
		c.heartTimeoutCount++
		if c.heartTimeoutCount >= common.HeartTimeoutCountMax {
			c.Stop()
			return
		}
		logger.Debug("timeout count: %d", c.heartTimeoutCount)
	}else {
		c.heartTimeoutCount = 0
	}
}