【问题标题】:Self-resetting circular flow in wolkenkitwolkenkit中的自复位循环流
【发布时间】:2019-01-29 18:32:05
【问题描述】:

我有一个关于有状态流的问题,我将尝试将其分解为一个非常简单的示例: 我正在使用不同的状态,比如说原始、添加和计算。 我的状态由一个我想添加的 int 组成,在我添加两次之后,我想计算加倍的数量,然后再次将其设置为原始状态。 所以现在我将从一个原始流开始,int = 0。在我的转换中,我对 addNumber 事件做出反应,从事件数据中取出一个 int 并将其添加到我的状态,然后我 transitionTo('add')。 我重复一遍,添加另一个号码和transitionTo('calculate')。 在我的反应中,我现在对添加和计算之间的转换做出反应,并将新状态设置为整数的两倍。 我现在要做的是使用该数字,例如发送包含它的命令,然后重置状态和transitionTo('pristine')。 问题是:我不能设置状态,也不能转换。 你如何解决这个问题?

这里有实际的代码,这样更容易理解:

'use strict';

const identity = {
        'usermgmt.user.presentSwitched': event => event.user.id,
    'usermgmt.user.pauseSwitched': event => event.user.id
};

const initialState = {
    is: 'pristine',
    present: false,
    pause: false,
    presentSince: null,
    presentUntil: null,
    pauses: [],
};

const transitions = {
    pristine: {
        'usermgmt.user.presentSwitched' (flow, event) {
            flow.setState({
                present: true,
                presentSince: event.data.timestamp
            });
            flow.transitionTo('present');
        }
    },
    present: {
        'usermgmt.user.presentSwitched' (flow, event) {
            flow.setState({
                present: false,
                presentUntil: event.data.timestamp
            });
            flow.transitionTo('calculating');
        },
        'usermgmt.user.pauseSwitched' (flow, event) {
            const newPause = {pauseSince: event.data.timestamp};
            flow.setState({
                pause: true,
                pauses: [...flow.state.pauses, newPause]
        });
            flow.transitionTo('pause');
        }
    },
    pause: {
        'usermgmt.user.pauseSwitched' (flow, event) {
            const pauses = Object.create(flow.state.pauses);
            pauses[flow.state.pauses.length - 1].pauseUntil = event.data.timestamp;
            flow.setState({
                pause: false,
                pauseSince: event.data.timestamp,
                pauses
            });
            flow.transitionTo('present');
        }
    }
};

const reactions = {
    present: {
        'calculating' (flow, event, services) {
            const {app, logger} = services;

            const workDayId = 'kek';
            const from = flow.state.presentSince;
            const to = flow.state.presentUntil;
            const pauses = flow.state.pauses;

            logger.info(JSON.stringify(flow));

            app.keksing.recording().createRecording({workDayId, from, to, type: 'working'});

            flow.setState({
                present: false,
                pause: false,
                presentSince: null,
                presentUntil: null,
                pauses: [],
            });
            flow.transitionTo('pristine');
        }
    }
};

module.exports = { identity, initialState, transitions, reactions };

https://gist.github.com/DrFelder/122a72ffed3eb239a1a3ae33c99ea00d

【问题讨论】:

    标签: wolkenkit


    【解决方案1】:

    对此基本上有两种想法:

    1. 第一个选项是质疑您是否应该在此处使用流。也许您可以将其建模为一个聚合,使用诸如 startWorkendWorkpauseresume 之类的命令,以及所需的状态,然后您可以在该聚合中拥有您想要的逻辑。您可以对每个人使用一个聚合,也可以对每个存在块使用一个聚合。无论哪种方式,这应该工作。因此,换个说法:您是否有特殊原因要将其实现为流而不是聚合?
    2. 第二个选项是pristinecalculating 之间没有区别。因为,您实际上想要的是某种圆形,但您的流程并未建模为圆形。因此,如果不是最终转换到calculating,而是转换回pristine,您将处于所需的状态,并且在present->pristine 的反应内部,您可以进行您想要的计算并使用计算数据(实际上,对过渡的反应)。

    这有助于澄清一些事情吗?

    PS:也许在命名时更明确也会有所帮助,例如有pausedresumed 而不是pauseSwitched。这将需要更少的逻辑来弄清楚发生的事情的意图,这基本上是 DDD 的优势之一,能够在措辞上明确。因为,正如现在命名的那样,它更像是某种updated 事件(应该避免)。

    【讨论】:

    • 我完全同意你的代码本身的 cmets,我匆忙把它放在一起。使用流没有特殊原因,我只是认为它会是最优雅的解决方案。不过,我想我会采用您的第二个解决方案。
    猜你喜欢
    • 2019-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    相关资源
    最近更新 更多