工作流作为状态机

3.4 版本
维护中的版本

workflow组件是仿照 Workflow net 得来的,后者是 Petri net 的一个子类。通过添加进一步的限制,你可以得到一个状态机(state machine)。最重要的一点是,状态机不可以同时存在于一个以上的place之中。另外值得注意的是,工作流在(自身的)定义线图(definition graph)中,一般不具有循环路径(cyclic path),但在状态机中却很常见。

状态机示例 

一个pull request,从一个初始的“start”状态开始,比如就是“运行Travis先生的测试”这一状态。当测试完成后,pull request处于“review”状态,贡献者们可以发起change, reject 或 accept 这个 pull request。在任何时候,你同样可以“更新”这个pull request,这将导致另外一个Travis在运行。

下面是pull request状态机:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# app/config/config.yml
framework:
    workflows:
        pull_request:
           type: 'state_machine'
           supports:
                - AppBundle\Entity\PullRequest
           places:
                - start
                - coding
                - travis
                - review
                - merged
                - closed
           transitions:
                submit:
                    from: start
                    to: travis
                update:
                    from: [coding, travis, review]
                    to: travis
                wait_for_reivew:
                    from: travis
                    to: review
                request_change:
                    from: review
                    to: coding
                accept:
                    from: review
                    to: merged
                reject:
                    from: review
                    to: closed
                reopen:
                    from: closed
                    to: review
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="utf-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:framework="http://symfony.com/schema/dic/symfony"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
        http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"
>
 
    <framework:config>
        <framework:workflow name="pull_request" type="state_machine">
            <framework:marking-store type="single_state"/>
 
            <framework:support>AppBundle\Entity\PullRequest</framework:support>
 
            <framework:place>start</framework:place>
            <framework:place>coding</framework:place>
            <framework:place>travis</framework:place>
            <framework:place>review</framework:place>
            <framework:place>merged</framework:place>
            <framework:place>closed</framework:place>
 
            <framework:transition name="submit">
                <framework:from>start</framework:from>
 
                <framework:to>travis</framework:to>
            </framework:transition>
 
            <framework:transition name="update">
                <framework:from>coding</framework:from>
                <framework:from>travis</framework:from>
                <framework:from>review</framework:from>
 
                <framework:to>travis</framework:to>
            </framework:transition>
 
            <framework:transition name="wait_for_review">
                <framework:from>travis</framework:from>
 
                <framework:to>review</framework:to>
            </framework:transition>
 
            <framework:transition name="request_change">
                <framework:from>review</framework:from>
 
                <framework:to>coding</framework:to>
            </framework:transition>
 
            <framework:transition name="accept">
                <framework:from>review</framework:from>
 
                <framework:to>merged</framework:to>
            </framework:transition>
 
            <framework:transition name="reject">
                <framework:from>review</framework:from>
 
                <framework:to>closed</framework:to>
            </framework:transition>
 
            <framework:transition name="reopen">
                <framework:from>closed</framework:from>
 
                <framework:to>review</framework:to>
            </framework:transition>
 
        </framework:workflow>
 
    </framework:config>
</container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// app/config/config.php
 
$container->loadFromExtension('framework', array(
    // ...
    'workflows' => array(
        'pull_request' => array(
          'type' => 'state_machine',
          'supports' => array('AppBundle\Entity\PullRequest'),
          'places' => array(
            'start',
            'coding',
            'travis',
            'review',
            'merged',
            'closed',
          ),
          'transitions' => array(
            'start'=> array(
              'form' => 'start',
              'to' => 'travis',
            ),
            'update'=> array(
              'form' => array('coding','travis','review'),
              'to' => 'travis',
            ),
            'wait_for_reivew'=> array(
              'form' => 'travis',
              'to' => 'review',
            ),
            'request_change'=> array(
              'form' => 'review',
              'to' => 'coding',
            ),
            'accept'=> array(
              'form' => 'review',
              'to' => 'merged',
            ),
            'reject'=> array(
              'form' => 'review',
              'to' => 'closed',
            ),
            'reopen'=> array(
              'form' => 'start',
              'to' => 'review',
            ),
          ),
        ),
    ),
));

现在,通过获取 state_machine.pull_request 服务,你可以使用状态机了:

1
$stateMachine = $this->container->get('state_machine.pull_request');

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)