Preface
In the design of the electrical module's system orders, the order will involve the transfer between the various states and the state as well as state, scalability, maintainability is the focus of our concern! This article shares my technical solution.
As shown in the above figure, use golang
realize the order flow in the above figure, and at the same time, when the order status or order event is added subsequently, it can be completed quickly.
purpose
Regarding the processing of the order status, a unified entry is used to improve the scalability and
maintainability of the program.
logical analysis
The order status includes: default,
reserved,
confirmed,
locked.
Order events include: order creation,
confirmation order,
modification order,
payment order.
Through the above figure, we also know the relationship between status and event. For example, only confirmed orders can be modified
.
The following issues need to be considered:
- When the order status increases, how to make as few changes as possible or have little impact on history?
- If it is called at the same entrance, the input parameters required by the processing method of each event are different, how to deal with it?
- When an event is completed, it may send SMS or client Push operation, how to deal with it?
- It is possible that a certain event has different processing logic on different platforms (C-end, merchant back-end, management platform). How to deal with it?
How to design the code to solve the above problems?
The following is a code implementation of mine for your reference. creating an order at 160e94c832bfb9, the parameters are passed in and the user is sent a short message after completion. The operations of other events can be achieved in the same way.
Code
Define the state
// 定义订单状态
const (
StatusDefault = State(0)
StatusReserved = State(10)
StatusConfirmed = State(20)
StatusLocked = State(30)
)
// statusText 定义订单状态文案
var statusText = map[State]string{
StatusDefault: "默认",
StatusReserved: "已预订",
StatusConfirmed: "已确认",
StatusLocked: "已锁定",
}
// statusEvent 定义订单状态对应的可操作事件
var statusEvent = map[State][]Event{
StatusDefault: {EventCreate},
StatusReserved: {EventConfirm},
StatusConfirmed: {EventModify, EventPay},
}
func StatusText(status State) string {
return statusText[status]
}
When there is an increase in the status of a new order, just add the corresponding status in this file, and at the same time maintain the relationship between the order status and the order event.
Define event
// 定义订单事件
const (
EventCreate = Event("创建订单")
EventConfirm = Event("确定订单")
EventModify = Event("修改订单")
EventPay = Event("支付订单")
)
// 定义订单事件对应的处理方法
var eventHandler = map[Event]Handler{
EventCreate: handlerCreate,
EventConfirm: handlerConfirm,
EventModify: handlerModify,
EventPay: handlerPay,
}
When a new order event is added, just add the corresponding event in this file, and maintain the relationship between the order event and the event realization method.
Define how to handle the event
var (
// handlerCreate 创建订单
handlerCreate = Handler(func(opt *Opt) (State, error) {
message := fmt.Sprintf("正在处理创建订单逻辑,订单ID(%d), 订单名称(%s) ... 处理完毕!", opt.OrderId, opt.OrderName)
fmt.Println(message)
if opt.HandlerSendSMS != nil {
_ = opt.HandlerSendSMS("18888888888", "恭喜你预定成功了!")
}
return StatusReserved, nil
})
// handlerConfirm 确认订单
handlerConfirm = Handler(func(opt *Opt) (State, error) {
return StatusConfirmed, nil
})
// handlerModify 修改订单
handlerModify = Handler(func(opt *Opt) (State, error) {
return StatusReserved, nil
})
// handlerPay 支付订单
handlerPay = Handler(func(opt *Opt) (State, error) {
return StatusLocked, nil
})
)
Maintain specific event handling methods in this file. If the logic is more complicated, consider splitting the file for processing.
Core code
type State int // 状态
type Event string // 事件
type Handler func(opt *Opt) (State, error) // 处理方法,并返回新的状态
// FSM 有限状态机
type FSM struct {
mu sync.Mutex // 排他锁
state State // 当前状态
handlers map[State]map[Event]Handler // 当前状态可触发的有限个事件
}
// 获取当前状态
func (f *FSM) getState() State {
return f.state
}
// 设置当前状态
func (f *FSM) setState(newState State) {
f.state = newState
}
// addHandlers 添加事件和处理方法
func (f *FSM) addHandlers() (*FSM, error) {
...
return f, nil
}
// Call 事件处理
func (f *FSM) Call(event Event, opts ...Option) (State, error) {
f.mu.Lock()
defer f.mu.Unlock()
...
return f.getState(), nil
}
// NewFSM 实例化 FSM
func NewFSM(initState State) (fsm *FSM, err error) {
fsm = new(FSM)
fsm.state = initState
fsm.handlers = make(map[State]map[Event]Handler)
fsm, err = fsm.addHandlers()
if err != nil {
return
}
return
}
For the operation of the order status, you only need to use the Call
method!
The code for methods addHandlers
and Call
will not be posted. I have provided the source code address at the end of the article for everyone to download.
Call method
For example, the current state is the default , and the following operations are performed in sequence:
creates an order, and the status becomes
reserved;
- 160e94c832c2d1 Modification of the order is
pre-ordered state);
confirms the order, the status becomes
confirmed;
modify the order, the status becomes
reserved;
confirms the order, and the status becomes
Confirmed;
payment order, the status becomes
locked;
// 通过订单ID 或 其他信息查询到订单状态
orderStatus := order.StatusDefault
orderMachine, err := order.NewFSM(orderStatus)
if err != nil {
fmt.Println(err.Error())
return
}
// 创建订单,订单创建成功后再给用户发送短信
if _, err = orderMachine.Call(order.EventCreate,
order.WithOrderId(1),
order.WithOrderName("测试订单"),
order.WithHandlerSendSMS(sendSMS),
); err != nil {
fmt.Println(err.Error())
}
// 修改订单
if _, err = orderMachine.Call(order.EventModify); err != nil {
fmt.Println(err.Error())
}
// 确认订单
if _, err = orderMachine.Call(order.EventConfirm); err != nil {
fmt.Println(err.Error())
}
// 修改订单
if _, err = orderMachine.Call(order.EventModify); err != nil {
fmt.Println(err.Error())
}
// 确认订单
if _, err = orderMachine.Call(order.EventConfirm); err != nil {
fmt.Println(err.Error())
}
// 支付订单
if _, err = orderMachine.Call(order.EventPay); err != nil {
fmt.Println(err.Error())
}
Output:
正在处理创建订单逻辑,订单ID(1), 订单名称(测试订单) ... 处理完毕!
发送短信,给(18888888888)发送了(恭喜你预定成功了!)
操作[创建订单],状态从 [默认] 变成 [已预订]
[警告] 状态(已预订)不允许操作(修改订单)
操作[确定订单],状态从 [已预订] 变成 [已确认]
操作[修改订单],状态从 [已确认] 变成 [已预订]
操作[确定订单],状态从 [已预订] 变成 [已确认]
操作[支付订单],状态从 [已确认] 变成 [已锁定]
summary
The above is my technical solution, I hope it can be helpful to you. If you are interested, you can . The above code has been submitted to github 160e94c832c4a8 go-fsm-order for download and use.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。