• 变更督程
    • 变更属性
    • 变更子进程规格
    • 添加和删除子进程

    变更督程

    督程行为支持更改内部状态,即,更改重启策略和最大重启频率属性,以及更改现存的子进程规格。

    还可以添加和删除子进程,但这不是自动处理的。指令必须在 .appup 文件中给出。

    变更属性

    由于督程需要更改它的内部状态,所以必须使用同步代码替换。不过,必须使用特殊的 update 指令。

    无论在升级还是降级的情况下,新版本的回调模块必须先加载。然后可以检查 init/1 的新返回值并相应改变内部状态。

    对于督程要使用以下 upgrade 指令:

    1. {update, Module, supervisor}

    例如:假设我们想将 Supervisor行为 一章中的 ch_sup 的重启策略从 one_for_one 更改成 one_for_all 。我们要修改 ch_sup.erl 中的回调函数 init/1

    1. -module(ch_sup).
    2. ...
    3.  
    4. init(_Args) ->
    5. {ok, {{one_for_all, 1, 60}, ...}}.

    文件 ch_app.appup

    1. {"2",
    2. [{"1", [{update, ch_sup, supervisor}]}],
    3. [{"1", [{update, ch_sup, supervisor}]}]
    4. }.

    变更子进程规格

    当更改一个现存的子进程规格时,指令——包括 .appup 文件——和上述的变更属性是一样的:

    1. {"2",
    2. [{"1", [{update, ch_sup, supervisor}]}],
    3. [{"1", [{update, ch_sup, supervisor}]}]
    4. }.

    更改不会影响现有的子进程。例如,更改了启动函数只会指定以后如果需要重启,那么子进程应该如何重启。

    注意,子进程规格的id不可以被更改。

    还要注意更改子进程规格的 Modules 字段可能会影响到发布处理过程自身,因为该字段用于在同步代码替换中识别哪些进程会受到影响。

    添加和删除子进程

    前面说过,变更子进程规格不会影响现存的子进程。新的子进程规格会被自动加入但不会被删除。并且,子进程不会自动启动或者终止,所以,必须明确使用 apply 指令。

    例如:假设当 ch_app 从“1”升级到“2”时,我们想要给 ch_sup 添加一个新的子进程 m1 。这也意味着如果从“2”降级到“1”的时候, m1 要被删除。

    1. {"2",
    2. [{"1",
    3. [{update, ch_sup, supervisor},
    4. {apply, {supervisor, restart_child, [ch_sup, m1]}}
    5. ]}],
    6. [{"1",
    7. [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    8. {apply, {supervisor, delete_child, [ch_sup, m1]}},
    9. {update, ch_sup, supervisor}
    10. ]}]
    11. }.

    注意指令的顺序非常重要。

    还要注意督程必须注册为 ch_sup 该脚本才能正常运行。如果督程没有被注册,那它就不能直接从脚本中访问。这就必须写一个帮助函数用来找到督程的pid并调用 supervisor:restart_child 等,而且必须使用 apply 指令在脚本中调用该函数。

    如果在 ch_app 的版本“2”中,引入了模块 m1 ,那么它也必须在升级时被加载,在降级时被删除:

    1. {"2",
    2. [{"1",
    3. [{add_module, m1},
    4. {update, ch_sup, supervisor},
    5. {apply, {supervisor, restart_child, [ch_sup, m1]}}
    6. ]}],
    7. [{"1",
    8. [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    9. {apply, {supervisor, delete_child, [ch_sup, m1]}},
    10. {update, ch_sup, supervisor},
    11. {delete_module, m1}
    12. ]}]
    13. }.

    再次注意指令的顺序非常重要。当升级时,在可以启动新的子进程之前,必须加载 m1 并且更改督程的子进程规格。当降级时,子进程必须在更改子进程规格和删除模块之前终止。