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

platform

ConfigStore

Nothing

services

ReportService

ConfigContract named platform

workflows

ReportWorkflow

ReportingContract named reporting

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๏ƒ

All intermediate examples ยท Level contents ยท Full contents

Canonical page source