基于原子的设计

  • 需求
    • 定义一组操作,操作执行过程中如果失败,支持回滚
  • 设计理念
    • 抽象一个(仅仅一个)状态的改变为一个步骤,也即是说步骤是一个状态变更
    • 将步骤按一定顺序串起组成整个原子
    • 每个步骤又分为两个部分
      • 收集当前的状态数据,并更新状态中的旧状态
      • 执行
      • 收集当前的状态数据,并更新状态中的新状态
    • 整个原子支持在执行原子之前操作和之后的操作,这两个操作都支持回滚,比如发版前关闭实例流量,发版完成后打开实例流量;当然这种操作也可以放到原子中,看场景和便捷性;
  • 注意
    • 一个真正的流水线上的原子设计,还有好多东西需要抽象;一个通用又灵活的流水线的原子,有更多的东西需要抽象;这里仅仅提供原子执行失败之后回滚功能的实现框架
    • 另外下面的代码提供了一个check_common函数,当某个状态变更(步骤)失败时,需要再次验证(或者说是确认)状态是否改变,会更严谨
class base_atom:
    def atom_pre(self):
        pass
    def atom_pre_undo(self):
        pass
    def atom(self):
        raise NotImplementError("atom方法必须要重写")
    def atom_post(self):
        pass
    def atom_post_undo(self):
        pass

class AtomError(Exception):
    def __init__(self,msg):
        self.message = msg
    def __str__(self):
        return self.message
    
class deploy_atom(base_atom):
    def __init__(self,states):
        # 执行顺序
        self.change_list = ["first","second","third", "fourth"]
        # 保存每一步old、new状态
        self.states = []
        self.ret = {"result": None}
    
    def first_step(self):
        print("exec first step!") 
    
    def first_undo(self):
        print("undo first step!")
    
    def second_step(self):
        print("exec second step!")
    
    def second_undo(self):
        print("undo second step!")
    
    def third_step(self):
        print("exec three step!")
    
    def third_undo(self):
        print("undo three step!")
    
    def fourth_step(self):
        print("exec four step!")
    
    def fourth_undo(self):
        print("undo four step!")
    
    def check_common(self):
        pass
    
    def atom(self):
        # self.change_list = ["first","second","three", "four"]
        # 维护一个执行轨迹的exec_tail列表
            # 执行时,执行完一个往exec_tail中加一个
            # 回滚时,回滚一个从exec_tail列表中pop掉一个
        exec_tail = []
        exec_ret,undo_ret = "success", ""
        exec_step = 0
        for n,exec in enumerate(self.change_list):
            try:
                # 模拟原子中某个不止执行失败
                if n == 2:
                    raise AtomError("Just a test")
                target = getattr(self, exec + "_step", None)
                target()
            except Exception as e:
                # 记录日志
                exec_ret = "fail"
                print("exec_ret: {}".format(exec_ret))
                # 跳出for循环
                break
            else:
                exec_tail.append(exec)
            # 如果要对最后一次执行失败的步骤进行状态校验就用这个替换else分支
            # finally:
                # 上面的break触发后,finally下的命令还是会执行的
                # exec_tail.append(exec)

        # print("exec_step: {0}".format(exec_step))

        if exec_ret == "fail":
            undo_ret = "successful"
            while(len(exec_tail) > 0):
                last_step = exec_tail.pop()
                try:
                    target = getattr(self, last_step + "_undo", None)
                    target()
                except Exception as e:
                    # 记录日志并退出for循环
                    undo_ret = "fail"
                    pass
                    break
                    
        self.ret = {"result": exec_ret, "undo_ret": undo_ret}
        return self.ret
        
deploy = deploy_atom({"name": "abc-test-api"})
deploy.atom()   

# 普通应用发版为例:     
# 1.upload tar and untar tar
    # file state change: old process path -> new process path
    # undo: delete new process path
# 2.stop old_process
    # process state change:  running -> stop
    # undo: stop -> running
    # check:
# 3.ln new path
    # file state change: old ln -> new ln
    # undo: new ln -> old ln
# 4.start new_process
    # process state change: stop -> running
    # undo: running -> stop 
    # check: 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值