import { Data, replayWithLatest, useGeneralDriver, pluckT, distinctPreviousT, StateMachine } from './libs/mobius-utils' export const processDispatcherDriver = (options = {}) => { /** * 对外广播的是状态,状态名称是固定的,接收到的信息是反馈,格式是可变的 * 如对外广播 status: start,代表当前是准备阶段,收到此状态之后,各模块都在“进行准备” * 各模块准备完成之后,将准备的信息以恰当的数据格式反馈给 dispatcher, * dispatcher 确认必要的模块都准备完毕之后,进入新的状态, * 如对外广播 status: update,代表当前进入更新阶段,收到此状态之后,各模块都“进行更新” * 在更新的过程中,各模块可以以恰当的数据格式随时向 dispatcher 反馈相关信息 * …… */ // 接收各模块的运行状态 const executeStatusInD = Data.empty() // 向各模块广播运行状态 const processRD = replayWithLatest(1, Data.empty()) const fsm = new StateMachine({ init: 'empty', transitions: [ { name: 'start', from: 'empty', to: 'start' }, { name: 'discard', from: 'start', to: 'discard' }, { name: 'update', from: 'start', to: 'update' }, { name: 'rollback', from: 'update', to: 'rollback' }, { name: 'cancel', from: 'discard', to: 'end' }, { name: 'fail', from: 'rollback', to: 'end' }, { name: 'success', from: 'update', to: 'end' }, { name: 'end', from: 'end', to: 'empty' } ], methods: { onAfterTransition: ({ from, to }) => { if (from !== 'none') { console.log('[ProcessDispatcherDriver] state changes:', from, '->', to) } } } }) executeStatusInD.pipe( pluckT('updateManager'), distinctPreviousT(v => JSON.stringify(v)) ).subscribeValue(status => { // 当 updateManager 将状态设置为 init 的时候,将 start 状态广播给所有模块 if (status.status === 'init') { fsm.start() processRD.mutate(() => ({ status: fsm.state })) } if (status.status === 'update') { const { result } = status if (result === 'success') { fsm.success() processRD.mutate(() => ({ status: fsm.state })) } if (result === 'fail') { fsm.rollback() processRD.mutate(() => ({ status: fsm.state })) } } }) executeStatusInD.subscribeValue(status => { // 当所有模块都进入 start 状态之后,切换到 update 状态 if (Object.values(status).every(s => s && s.status === 'start')) { fsm.update() processRD.mutate(() => ({ status: fsm.state })) } // 当所有模块都进入 rollback 状态之后,切换到 end 状态 if (Object.values(status).every(s => s && s.status === 'rollback')) { fsm.fail() processRD.mutate(() => ({ status: fsm.state })) } // 当所有模块都进入 end 状态之后,切换到 empty 状态 if (Object.values(status).every(s => s && s.status === 'end')) { fsm.end() processRD.mutate(() => ({ status: fsm.state })) } }) return { inputs: { executeStatus: executeStatusInD }, outputs: { process: processRD } } } export const useProcessDispatcherDriver = useGeneralDriver(processDispatcherDriver)