1、增加座席业务状态机模块。

This commit is contained in:
redhat 2025-06-11 15:36:28 +08:00
parent e467ba3028
commit 9219363b7c
3 changed files with 458 additions and 0 deletions

84
pkg/http/http.go Normal file
View File

@ -0,0 +1,84 @@
package http
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
type Client struct {
core *http.Client
}
func NewClient() *Client {
return &Client{
core: http.DefaultClient,
}
}
func (c *Client) JSONGet(ctx context.Context, url string, header, params map[string]string, resp interface{}) error {
return c.JSONDo(ctx, http.MethodGet, getCompleteURL(url, params), header, nil, resp)
}
func (c *Client) JSONPost(ctx context.Context, url string, header map[string]string, req, resp interface{}) error {
return c.JSONDo(ctx, http.MethodPost, url, header, req, resp)
}
func (c *Client) JSONDo(ctx context.Context, method, url string, header map[string]string, req, resp interface{}) error {
var reqReader io.Reader
if req != nil {
body, _ := json.Marshal(req)
reqReader = bytes.NewReader(body)
}
request, err := http.NewRequestWithContext(ctx, method, url, reqReader)
if err != nil {
return err
}
if request.Header == nil {
request.Header = make(http.Header)
}
for k, v := range header {
request.Header.Add(k, v)
}
request.Header.Add("Content-Type", "application/json")
response, err := c.core.Do(request)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return fmt.Errorf("invalid status: %d", response.StatusCode)
}
if resp == nil {
return nil
}
respBody, err := io.ReadAll(response.Body)
if err != nil {
return err
}
return json.Unmarshal(respBody, resp)
}
func getCompleteURL(origin string, params map[string]string) string {
if len(params) == 0 {
return origin
}
values := url.Values{}
for k, v := range params {
values.Add(k, v)
}
queriesStr, _ := url.QueryUnescape(values.Encode())
return fmt.Sprintf("%s?%s", origin, queriesStr)
}

368
services/uniss/fsm.go Normal file
View File

@ -0,0 +1,368 @@
package uniss
import (
"context"
"dashboard/pkg/fsm"
"time"
"git.zhangshuocauc.cn/redhat/timewheel"
"go.uber.org/zap"
)
const (
unisFsmEventReset fsm.EventName = "unisFsmEventReset"
unisFsmEventOfline fsm.EventName = "unisFsmEventOfline"
unisFsmEventOnline fsm.EventName = "unisFsmEventOnline"
unisFsmEventLoginId fsm.EventName = "unisFsmEventLoginId"
unisFsmEventLoginSync fsm.EventName = "unisFsmEventLoginSync"
unisFsmEventLoginForce fsm.EventName = "unisFsmEventLoginForce"
unisFsmEventLoginServer fsm.EventName = "unisFsmEventLoginServer"
unisFsmEventLogout fsm.EventName = "unisFsmEventLogout"
unisFsmEventLogoutForce fsm.EventName = "unisFsmEventLogoutForce"
unisFsmEventLogoutServer fsm.EventName = "unisFsmEventLogoutServer"
unisFsmEventLogin fsm.EventName = "unisFsmEventLogin"
unisFsmEventLoginSyncFailed fsm.EventName = "unisFsmEventLoginSyncFailed"
unisFsmEventLoginSyncSuccess fsm.EventName = "unisFsmEventLoginSyncSuccess"
unisFsmEventLoginSuccess fsm.EventName = "unisFsmEventLoginSuccess"
unisFsmEventLoginFailed fsm.EventName = "unisFsmEventLoginFailed"
unisFsmEventLogoutSuccess fsm.EventName = "unisFsmEventLogoutSuccess"
unisFsmEventLogoutFailed fsm.EventName = "unisFsmEventLogoutFailed"
)
var events = fsm.Events{
unisFsmEventReset,
unisFsmEventLoginSuccess,
unisFsmEventLoginFailed,
unisFsmEventLogoutSuccess,
unisFsmEventLogoutFailed,
}
type fsmService struct {
unisMSystemFsm *unisMSystemFsm
unisMStateFsm *unisMStateFsm
}
func (f *fsmService) reset(ctx context.Context) {
f.unisMSystemFsm.reset(ctx)
f.unisMStateFsm.reset(ctx)
}
func newfsmService() (fsm *fsmService, err error) {
fsm = &fsmService{}
fsm.unisMSystemFsm, err = newunisMSystemFsm()
if err != nil {
return
}
fsm.unisMStateFsm, err = newunisMStateFsm()
if err != nil {
return
}
return
}
/*******************************主逻辑在线离线状态机************************************/
type unisMSystemFsm struct {
fsm *fsm.FSM
}
const (
unisMSystem = "unisMSystem"
unisMIdle = "unisMIdle"
unisMOnLine = "unisMOnLine"
unisMOfLine = "unisMOfLine"
unisMOnLineIdle = "unisMOnLineIdle"
unisMOnLineLoginId = "unisMOnLineLoginId"
unisMOnLineLoginning = "unisMOnLineLoginning"
unisMOnLineLogouting = "unisMOnLineLogouting"
unisMOnLineLoginSync = "unisMOnLineLoginSync"
)
func newunisMSystemFsm() (*unisMSystemFsm, error) {
res := new(unisMSystemFsm)
fsm, err := fsm.NewFsm(unisMSystem, unisMIdle, events, []*fsm.StateRule{
{Name: unisMSystem, Parent: "", InitState: unisMIdle, Processor: res.unisMSystem, Dst: []string{}},
{Name: unisMIdle, Parent: unisMSystem, InitState: "", Processor: res.unisMIdle, Dst: []string{}},
{Name: unisMOnLine, Parent: unisMSystem, InitState: unisMOnLineIdle, Processor: res.unisMOnLine, Dst: []string{}},
{Name: unisMOfLine, Parent: unisMSystem, InitState: "", Processor: res.unisMOfLine, Dst: []string{}},
{Name: unisMOnLineIdle, Parent: unisMOnLine, InitState: "", Processor: res.unisMOnLineIdle, Dst: []string{}},
{Name: unisMOnLineLoginId, Parent: unisMOnLine, InitState: "", Processor: res.unisMOnLineLoginId, Dst: []string{}},
{Name: unisMOnLineLoginning, Parent: unisMOnLine, InitState: "", Processor: res.unisMOnLineLoginning, Dst: []string{}},
{Name: unisMOnLineLogouting, Parent: unisMOnLine, InitState: "", Processor: res.unisMOnLineLogouting, Dst: []string{}},
{Name: unisMOnLineLoginSync, Parent: unisMOnLine, InitState: "", Processor: res.unisMOnLineLoginSync, Dst: []string{}},
}, zap.NewStdLog(log.Logger))
if err != nil {
log.Sugar().Error(err)
return nil, err
}
res.fsm = fsm
return res, nil
}
func (f *unisMSystemFsm) reset(ctx context.Context) {
f.fsm.ExecuteEvent(ctx, unisFsmEventReset, nil)
}
func (f *unisMSystemFsm) unisMSystem(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventReset:
e.FSM.StateChange(ctx, unisMIdle, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMSystemFsm) unisMIdle(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventOfline:
e.FSM.StateChange(ctx, unisMOfLine, nil)
case unisFsmEventOnline:
e.FSM.StateChange(ctx, unisMOnLineLoginSync, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMSystemFsm) unisMOnLine(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventOfline:
e.FSM.StateChange(ctx, unisMOfLine, nil)
case unisFsmEventLoginId:
case unisFsmEventLoginSync:
e.FSM.StateChange(ctx, unisMOnLineLoginSync, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMSystemFsm) unisMOfLine(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventOnline:
e.FSM.StateChange(ctx, unisMOnLineLoginSync, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
/**********************************主逻辑登录状态机***********************************/
func (f *unisMSystemFsm) unisMOnLineIdle(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventLoginId:
e.FSM.StateChange(ctx, unisMOnLineLoginId, e.Args)
case unisFsmEventLoginForce:
e.FSM.StateChange(ctx, unisMOnLineLoginning, e.Args)
case unisFsmEventLoginServer:
case unisFsmEventLogout:
e.FSM.StateChange(ctx, unisMOnLineLogouting, e.Args)
case unisFsmEventLogoutForce:
fallthrough
case unisFsmEventLogoutServer:
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMSystemFsm) unisMOnLineLoginId(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
e.FSM.StartEventTimer(ctx, timewheel.TimerTypeOnce, time.Second*5, nil)
case fsm.EventExit:
e.FSM.StopEventTimer()
case unisFsmEventLogin:
e.FSM.StateChange(ctx, unisMOnLineLoginning, e.Args)
case fsm.EventTimeOut:
e.FSM.StateChange(ctx, unisMOnLineIdle, nil)
case unisFsmEventLoginFailed:
e.FSM.StateChange(ctx, unisMOnLineIdle, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMSystemFsm) unisMOnLineLoginning(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
e.FSM.StartEventTimer(ctx, timewheel.TimerTypeOnce, time.Second*5, nil)
case fsm.EventExit:
e.FSM.StopEventTimer()
case fsm.EventTimeOut:
e.FSM.StateChange(ctx, unisMOnLineIdle, nil)
case unisFsmEventLoginFailed:
e.FSM.StateChange(ctx, unisMOnLineIdle, nil)
case unisFsmEventLoginSuccess:
e.FSM.StateChange(ctx, unisMOnLineIdle, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMSystemFsm) unisMOnLineLogouting(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
e.FSM.StartEventTimer(ctx, timewheel.TimerTypeOnce, time.Second*5, nil)
case fsm.EventExit:
e.FSM.StopEventTimer()
case fsm.EventTimeOut:
fallthrough
case unisFsmEventLogoutFailed:
fallthrough
case unisFsmEventLogoutSuccess:
e.FSM.StateChange(ctx, unisMOnLineIdle, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMSystemFsm) unisMOnLineLoginSync(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
e.FSM.StartEventTimer(ctx, timewheel.TimerTypeOnce, time.Second*10, nil)
case fsm.EventExit:
e.FSM.StopEventTimer()
case fsm.EventTimeOut:
case unisFsmEventLoginSyncFailed:
case unisFsmEventLoginSyncSuccess:
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
/***************************主登录状态机********************************************/
type unisMStateFsm struct {
fsm *fsm.FSM
}
const (
unisMState = "unisMState"
unisMStateIdle = "unisMStateIdle"
unisMStateLogin = "unisMStateLogin"
unisMStateLogout = "unisMStateLogout"
)
func newunisMStateFsm() (*unisMStateFsm, error) {
res := new(unisMStateFsm)
fsm, err := fsm.NewFsm(unisMState, unisMState, events, []*fsm.StateRule{
{Name: unisMState, Parent: "", InitState: unisMStateIdle, Processor: res.unisMState, Dst: []string{}},
{Name: unisMStateIdle, Parent: unisMState, InitState: "", Processor: res.unisMStateIdle, Dst: []string{}},
{Name: unisMStateLogin, Parent: unisMState, InitState: "", Processor: res.unisMStateLogin, Dst: []string{}},
{Name: unisMStateLogout, Parent: unisMState, InitState: "", Processor: res.unisMStateLogout, Dst: []string{}},
{},
}, zap.NewStdLog(log.Logger))
if err != nil {
log.Sugar().Error(err)
return nil, err
}
res.fsm = fsm
return res, nil
}
func (f *unisMStateFsm) reset(ctx context.Context) {
f.fsm.ExecuteEvent(ctx, unisFsmEventReset, nil)
}
func (f *unisMStateFsm) unisMState(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventReset:
e.FSM.StateChange(ctx, unisMStateIdle, nil)
case unisFsmEventLoginFailed:
case unisFsmEventLogoutFailed:
e.FSM.StateChange(ctx, unisMStateLogout, nil)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMStateFsm) unisMStateIdle(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventLoginSuccess:
e.FSM.StateChange(ctx, unisMStateLogin, e.Args)
case unisFsmEventLogoutSuccess:
e.FSM.StateChange(ctx, unisMStateLogout, e.Args)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMStateFsm) unisMStateLogin(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
e.FSM.StartEventTimer(ctx, timewheel.TimerTypeOnce, time.Minute*5, nil)
case fsm.EventExit:
e.FSM.StopEventTimer()
case fsm.EventTimeOut:
e.FSM.StartEventTimer(ctx, timewheel.TimerTypeOnce, time.Minute*5, nil)
case unisFsmEventLoginSuccess:
case unisFsmEventLogoutSuccess:
e.FSM.StateChange(ctx, unisMStateLogout, e.Args)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}
func (f *unisMStateFsm) unisMStateLogout(ctx context.Context, e *fsm.Event) error {
switch e.Event {
case fsm.EventEntry:
case fsm.EventExit:
case unisFsmEventLoginSuccess:
e.FSM.StateChange(ctx, unisMStateLogin, e.Args)
default:
return fsm.EventNoProc
}
return fsm.EventOK
}

View File

@ -20,6 +20,7 @@ type UnisStation struct {
commonService *commonService
communicateService *communicateService
dataCenterService *dataCenterService
fsmService *fsmService
}
func NewUnis(_log *logger.Logger, conf *settings.UnisConfig) (res *UnisStation, err error) {
@ -32,6 +33,11 @@ func NewUnis(_log *logger.Logger, conf *settings.UnisConfig) (res *UnisStation,
return
}
res.fsmService, err = newfsmService()
if err != nil {
return
}
res.commonService = newcommonService(res)
return