On this page
Compose platform โ services โ workflows๏
Prerequisites: addressing,
dynamic linking, and SpellContract.
Run saved Intermediate lesson 26 from a checkout, or unpack the complete collection
so its _dynamic_world.py helper stays beside the script.
The application has three categories with separate books and owners:
Category |
Owns |
Needs from the previous category |
|---|---|---|
|
|
Nothing |
|
|
|
|
|
|
For the first edge, conjure the provider and consumer, link, pull the provider's spell, and meld the service. Repeat the same five steps for the next edge using that completed service as the provider's product.
Read the result๏
The script asserts that workflow.service is service: the resolved service crosses
the second boundary. Its run() result combines the workflow, report, and the
region value returned by the platform store. Inspect all three class definitions
in the complete linked example alongside the core operations below.
When applying this pattern, give each root an application owner and end those owned runtimes explicitly. Keep the scoped-cleanup pattern beside the composition pattern; construction and shutdown are both part of your design.
The workflow in code๏
These are the core steps from the saved example. Use its complete linked script for all class definitions and setup.
1def main() -> None:
2 # One book per CATEGORY - each book is that category's recipe list.
3 platform_book = dynamic_spellbook()
4 config_id = platform_book.bind(
5 spell=ConfigStore, existence="unique",
6 spellframe=ConfigContract, binding_name="platform",
7 )
8 services_book = dynamic_spellbook()
9 service_id = services_book.bind(
10 spell=ReportService, existence="unique",
11 spellframe=ReportingContract, binding_name="reporting",
12 )
13 workflows_book = dynamic_spellbook()
14 workflow_id = workflows_book.bind(spell=ReportWorkflow, existence="unique")
15
16 # ---- EDGE 1: platform feeds services ----
17 platform = platform_book.conjure(dynamic=True, name="platform") # 1) provider
18 services = services_book.conjure(dynamic=True, name="services") # 2) consumer
19 platform.link(services) # 3) link AFTER both
20 services.add_spell_to_contract( # 4) pull
21 spell_id=config_id, conduit=platform, permissions="create",
22 )
23 service = services.meld(spell_id=service_id) # 5) meld after the fact
24
25 # ---- EDGE 2: services feeds workflows (same cycle, one level up) ----
26 workflows = workflows_book.conjure(dynamic=True, name="workflows")
27 services.link(workflows)
28 workflows.add_spell_to_contract(
29 spell_id=service_id, conduit=services, permissions="create",
30 )
31 workflow = workflows.meld(spell_id=workflow_id)
32
33 assert workflow.service is service # the finished product crossed the edge
34 print("category chain resolved:", workflow.run())
35 print("factory types were just conduit names:",
36 platform.name, "->", services.name, "->", workflows.name)
Runnable examples๏
Conduit categories as factories โ Intermediate 26
Late binding with spellcontract โ Intermediate 36
Clusters unique per cluster โ Intermediate 25
All intermediate examples ยท Level contents ยท Full contents