ATOM Transaction
本チュートリアルでは、ATOMのメソッド伝搬及び自律遷移について紹介します。ATOMは、任意の状態属性を定義することができ、状態属性に対して任意の状態遷移を定義することができます。遷移トリガーは、メソッド呼び出しの完了、失敗として定義できます。ATOMの詳細は、Docs » Scenario » ATOM
を参考にしてください。
チュートリアルの題材として、GoFのデザインパターンにおけるComposite
パターンを取り上げます。以下は、Composite
パターンにおけるクラスダイアグラムです。
Componentクラスを作成する
最初に作成するATOMは、Component
抽象クラスです。チュートリアルでは、Composite
やLeaf
の生成、削除の振る舞いや状態管理を上位クラスであるComponent
に実装しています。
状態マシンは、以下の図のように振舞う設計です。
Component
抽象クラスは、以下のような定義になります。各メソッドの実装は、クラウドリソースをコントロールするようにカスタマイズするとより理解を深められるでしょう。
category: example
name: Component
abstract: true
persistence: false
api_generation: false
attributes:
identifier:
field_immutable: true
field_name: name
field_persistence: true
field_type: string
local_fields:
- field_fsm:
Active:
execution_method: create_confirm
failure_transition: Deleting
status_type: Steady
Creating:
execution_method: create
failure_transition: Deleting
status_type: Initial
success_transition: Active
Deleted:
execution_method: delete_confirm
status_type: Terminate
Deleting:
execution_method: delete
success_transition: Deleted
field_immutable: false
field_name: state
field_nullable: true
field_persistence: true
field_type: string
field_unique: false
ref_fields: []
methods:
class_methods: []
instance_methods:
- auto_rollback: true
field_order: ascend
method_body: |-
async def create(self, *args, **kwargs):
qprint("{}.{}.create()".format(self.name, self.instance))
multiplexable_number: 1
propagation_mode: true
topdown: true
- auto_rollback: true
field_order: ascend
method_body: |-
async def create_confirm(self, *args, **kwargs):
for i in range(1, 4):
qprint("{}.{} create confirming...{}".format(self.name, self.instance, i))
await asyncio.sleep(1)
qprint("{}.{} create done.".format(self.name, self.instance))
multiplexable_number: 1
propagation_mode: false
topdown: true
- auto_rollback: true
field_order: descend
method_body: |-
async def delete(self, *args, **kwargs):
qprint("{}.{}.delete()".format(self.name, self.instance))
multiplexable_number: 1
propagation_mode: true
topdown: false
- auto_rollback: true
field_order: descend
method_body: |-
async def delete_confirm(self, *args, **kwargs):
for i in range(1, 4):
qprint("{}.{} delete confirming...{}".format(self.name, self.instance, i))
await asyncio.sleep(1)
await self.destroy()
multiplexable_number: 1
propagation_mode: false
topdown: false
Compositeクラスを作成する
Composite
具象クラスはComponent
を継承し、components
フィールドでComponent
型をリスト保持することで包含関係を構築します。
category: example
name: Composite
abstract: false
persistence: true
api_generation: false
attributes:
local_fields:
- field_immutable: false
field_name: components
field_nullable: true
field_persistence: true
field_type: array<AxisAtom.Component>
field_unique: false
ref_fields: []
extends:
- Component
methods:
class_methods: []
instance_methods: []
Leafクラスを作成する
Leaf
具象クラスはComponent
を継承するだけです。
category: example
name: Leaf
abstract: false
persistence: true
api_generation: false
attributes:
local_fields: []
ref_fields: []
extends:
- Component
methods:
class_methods: []
instance_methods: []
動作確認(正常終了編)
REPLでCompositeインスタンスツリーを生成し、最上位のインスタンスに対してcreate
メソッドを呼び出してください。メソッド実行が伝搬され、各インスタンスは自律的に状態を遷移させます。この間、トランザクションサービスが自動的にリンクされ、アトミックな制御が行われます。トランザクションモニターも合わせて確認しておくのも良いでしょう。
>>> debug()↵
Disconnected the currently subscribed channel and connected to the debug channel ['xaas.southbound.channel']
debug channel connected
>>> root = atom.Composite(name="root")↵
... b1 = atom.Composite(name="branch1")↵
... b2 = atom.Composite(name="branch2")↵
... root.components = [b1, b2]↵
... l1 = atom.Leaf(name="leaf1")↵
... l2 = atom.Leaf(name="leaf2")↵
... l3 = atom.Leaf(name="leaf3")↵
... root.components[0].components = [l1, l2]↵
... root.components[1].components = [l3]↵
... await root.create()↵
... ↵
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy.create()
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...1
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...2
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...3
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create done.
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy.create()
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...1
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...2
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...3
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create done.
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.create()
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...1
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...2
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...3
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create done.
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.create()
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...1
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...2
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...3
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create done.
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy.create()
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...1
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...2
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...3
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy create done.
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.create()
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...1
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...2
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...3
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create done.
↵
>>> select * from Composite;↵
| instance | xid | xname | name | state | components |
Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy NULL NULL root Active ["Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy","Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy"]
Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy NULL NULL branch1 Active ["TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==","TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg=="]
Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy NULL NULL branch2 Active ["TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg=="]
3 rows in set
>>> select * from Leaf;↵
| instance | xid | xname | name | state |
TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== NULL NULL leaf3 Active
TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== NULL NULL leaf1 Active
TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== NULL NULL leaf2 Active
3 rows in set
>>> await root.delete()↵
... ↵
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.delete()
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...1
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...2
leaf1.TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...3
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.delete()
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...1
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...2
leaf2.TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...3
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy.delete()
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...1
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...2
branch1.Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...3
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.delete()
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...1
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...2
leaf3.TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...3
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy.delete()
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...1
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...2
branch2.Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...3
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy.delete()
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...1
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...2
root.Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...3
↵
>>> select * from Composite;↵
Empty set
>>> select * from Leaf;↵
Empty set
>>> print(root.yaml_format)↵
... ↵
↵
Composite:
components:
- Composite:
components:
- Leaf:
instance: TGVhZjo2MDhjYTc2ODkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==
name: leaf1
state: Deleted
- Leaf:
instance: TGVhZjo2MDhjYWQzYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==
name: leaf2
state: Deleted
instance: Q29tcG9zaXRlOjYwOGM2MzdhOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy
name: branch1
state: Deleted
- Composite:
components:
- Leaf:
instance: TGVhZjo2MDhjYjJkYTkxYjYxMWViYjQ2ZmFjZGU0ODAwMTEyMg==
name: leaf3
state: Deleted
instance: Q29tcG9zaXRlOjYwOGM2YWU2OTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy
name: branch2
state: Deleted
instance: Q29tcG9zaXRlOjYwOGM1YWVjOTFiNjExZWJiNDZmYWNkZTQ4MDAxMTIy
name: root
state: Deleted
>>> debug(False)↵
debug channel disconnected
>>>
動作確認(ロールバック終了編)
次にロールバックの動作を確認します。ここでは、簡易にロールバックトリガーとなるエラーを発生させるため、Component
のcreate_confirm
メソッドを以下のように変更します。
async def create_confirm(self, *args, **kwargs):
for i in range(1, 4):
qprint("{}.{} create confirming...{}".format(self.name, self.instance, i))
await asyncio.sleep(1)
# leaf3の場合は、強制的にエラーを発出する
if self.name == "leaf3":
raise Error(500, reason="Rollback Test!!")
qprint("{}.{} create done.".format(self.name, self.instance))
実行すると以下の動作となります。トランザクション管理画面でCancelled
状態になっていることを確認してください。
>>> debug()↵
Disconnected the currently subscribed channel and connected to the debug channel ['xaas.southbound.channel']
debug channel connected
>>> root = atom.Composite(name="root")↵
... b1 = atom.Composite(name="branch1")↵
... b2 = atom.Composite(name="branch2")↵
... root.components = [b1, b2]↵
... l1 = atom.Leaf(name="leaf1")↵
... l2 = atom.Leaf(name="leaf2")↵
... l3 = atom.Leaf(name="leaf3")↵
... root.components[0].components = [l1, l2]↵
... root.components[1].components = [l3]↵
... await root.create()↵
... ↵
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy.create()
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...1
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...2
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...3
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create done.
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy.create()
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...1
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...2
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...3
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create done.
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.create()
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...1
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...2
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...3
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create done.
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.create()
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...1
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...2
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...3
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create done.
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy.create()
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...1
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...2
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create confirming...3
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy create done.
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.create()
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...1
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...2
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== create confirming...3
Hotspot exception occurred.
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.delete()
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...1
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...2
leaf1.TGVhZjpiMGFjNGU5ZTkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...3
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.delete()
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...1
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...2
leaf2.TGVhZjpiMGFjNTRlODkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...3
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy.delete()
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...1
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...2
branch1.Q29tcG9zaXRlOmIwYWMwNGYyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...3
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg==.delete()
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...1
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...2
leaf3.TGVhZjpiMGFjNWFlYzkxYjkxMWViYjQ2ZmFjZGU0ODAwMTEyMg== delete confirming...3
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy.delete()
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...1
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...2
branch2.Q29tcG9zaXRlOmIwYWMwZGIyOTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...3
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy.delete()
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...1
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...2
root.Q29tcG9zaXRlOjhkYjQ0NTM2OTFiOTExZWJiNDZmYWNkZTQ4MDAxMTIy delete confirming...3
>>> select * from Composite;↵
Empty set
>>> select * from Leaf;↵
Empty set
>>>
メソッド伝搬の多重化
上記のアプリケーションでは、create
とdelete
メソッドの伝搬は、包含リストの順序に従って逐次処理してきました。これらのメソッド伝搬を多重化して並行に処理したい場合は、multiplexable_number
を設定します。Component
クラスのcreate
及びdelete
メソッドのmultiplexable_number
を3
に設定して実行すると以下のような出力となります。
branchやleafが並列で処理されていることが確認できます。
Warning
以下の出力は、動作確認(ロールバック終了編)
で書き換えた強制エラー発行のコードは元の状態に戻している前提です。
>>> debug()↵
Disconnected the currently subscribed channel and connected to the debug channel ['xaas.hotspot.channel']
debug channel connected
>>> root = atom.Composite(name="root")↵
... b1 = atom.Composite(name="branch1")↵
... b2 = atom.Composite(name="branch2")↵
... root.components = [b1, b2]↵
... l1 = atom.Leaf(name="leaf1")↵
... l2 = atom.Leaf(name="leaf2")↵
... l3 = atom.Leaf(name="leaf3")↵
... root.components[0].components = [l1, l2]↵
... root.components[1].components = [l3]↵
... await root.create()↵
... ↵
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy.create()
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...1
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...2
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...3
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create done.
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy.create()
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy.create()
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...1
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...1
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...2
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...2
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...3
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create confirming...3
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create done.
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy create done.
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg==.create()
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg==.create()
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg==.create()
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...1
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...1
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...1
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...2
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...2
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...2
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...3
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...3
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create confirming...3
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create done.
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create done.
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== create done.
↵
>>> await root.delete()↵
... ↵
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg==.delete()
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg==.delete()
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg==.delete()
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...1
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...1
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...1
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...2
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...2
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...2
leaf2.TGVhZjo0Y2YwNzNjODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...3
leaf3.TGVhZjo0Y2YwN2EwODkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...3
leaf1.TGVhZjo0Y2YwNmNjMDkxYzYxMWViYjNmZWFjZGU0ODAwMTEyMg== delete confirming...3
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy.delete()
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy.delete()
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...1
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...1
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...2
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...2
branch2.Q29tcG9zaXRlOjRjZjAyYTZjOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...3
branch1.Q29tcG9zaXRlOjRjZjAyMmJhOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...3
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy.delete()
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...1
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...2
root.Q29tcG9zaXRlOjRjZjAxOWJlOTFjNjExZWJiM2ZlYWNkZTQ4MDAxMTIy delete confirming...3
↵
>>> debug(False)↵
debug channel disconnected
>>>
Tip
クラウドリソースのメトリックをクラウドPubsubなどのイベントブローカーにプッシュし、Docs » Collector/Reflector » Worker
を参考にイベントをコンシュームしてQmonus SDKに取り込み、ATOMの状態変化メソッドを呼び出してクラウドリソースをコントロールするようなメトリックフィードバックを実装することで自律的にステートを維持するようなアプリケーションを作ってみるとより理解を深めることができるでしょう。