On this page

Managed spell elastic pool๏ƒ

๐ŸŸก Intermediate ยท Lesson 42

Lease pooled objects and give them back by hand - Existence.managed_spell_quantity. A managed spell's objects live in a pool its root conduit owns. A meld takes an idle object, or builds one when none is waiting; ReleaseManagedSpell().release(obj) gives it back, and the next meld reuses it (the newest released object first). Nothing returns an object automatically: you decide when it goes back.

Elastic is the default mode: a meld never refuses, and managed_spell_limit (256 by default) is how many IDLE objects the pool keeps. With a small limit, a release that would keep more idle objects than the limit destroys the oldest idle one - its disposal methods run. Root teardown disposes the idle objects; describe(cls) shows what is alive, idle and out at any moment.

Before you run๏ƒ

Use the Intermediate guide for prerequisite concepts. Run from a checkout with Melder installed and Python 3.14 free-threading selected. The collection download includes the level's local helper modules.

Run the saved script๏ƒ

python UX_and_AIX_experiences/02_intermediate/42_managed_spell_elastic_pool.py
py -3.14t UX_and_AIX_experiences/02_intermediate/42_managed_spell_elastic_pool.py

Download this collection ยท Source on GitHub

Public surface๏ƒ

md.Spellbook.bind (managed_spell_mode, managed_spell_limit, disposal_method_names), md.Existence.managed_spell_quantity, md.ManagedSpellMode.elastic, md.Conduit.meld, md.Conduit.has_live_creation, md.ReleaseManagedSpell (release, describe), md.Conduit.cleanup

Code๏ƒ

  1"""
  2TIER: intermediate (42)
  3GOAL: Lease pooled objects and give them back by hand - Existence.managed_spell_quantity.
  4      A managed spell's objects live in a pool its root conduit owns. A meld takes an
  5      idle object, or builds one when none is waiting; ReleaseManagedSpell().release(obj)
  6      gives it back, and the next meld reuses it (the newest released object first).
  7      Nothing returns an object automatically: you decide when it goes back.
  8
  9      Elastic is the default mode: a meld never refuses, and managed_spell_limit (256
 10      by default) is how many IDLE objects the pool keeps. With a small limit, a release
 11      that would keep more idle objects than the limit destroys the oldest idle one -
 12      its disposal methods run. Root teardown disposes the idle objects; describe(cls)
 13      shows what is alive, idle and out at any moment.
 14SURFACE EXERCISED: md.Spellbook.bind (managed_spell_mode, managed_spell_limit,
 15                   disposal_method_names), md.Existence.managed_spell_quantity,
 16                   md.ManagedSpellMode.elastic, md.Conduit.meld,
 17                   md.Conduit.has_live_creation, md.ReleaseManagedSpell (release, describe),
 18                   md.Conduit.cleanup
 19"""
 20from typing import Tuple
 21
 22import melder as md
 23
 24
 25class DatabaseConnection:
 26    """A connection that is expensive to open and cheap to hand to the next caller.
 27
 28    `close` is its disposal method: the pool calls it when it destroys the object
 29    (a trim, or root teardown), never on an ordinary release. `closed` is a lesson
 30    diagnostic, so the example can observe disposal from the outside.
 31    """
 32
 33    def __init__(self) -> None:
 34        """Open the connection; the lesson only records that it is open."""
 35        self.closed: bool = False
 36        self.queries: int = 0
 37
 38    def close(self) -> None:
 39        """Close the connection; called by the pool when it destroys this object."""
 40        self.closed = True
 41
 42
 43class ScratchBuffer:
 44    """A pooled buffer bound with a small idle limit, to show the elastic trim."""
 45
 46    def __init__(self) -> None:
 47        """Allocate the buffer; `closed` records disposal."""
 48        self.closed: bool = False
 49
 50    def close(self) -> None:
 51        """Release the buffer; called by the pool when it trims this object."""
 52        self.closed = True
 53
 54
 55def pool_counts(cls: type) -> Tuple[int, int, int]:
 56    """Return (alive, idle, out) for the one pool of a managed class.
 57
 58    `ReleaseManagedSpell().describe(cls)` answers one snapshot per pool; this lesson
 59    binds each class once, so there is exactly one.
 60    """
 61    (snapshot,) = md.ReleaseManagedSpell().describe(cls)
 62    return snapshot["count"], snapshot["idle_count"], snapshot["out_count"]
 63
 64
 65def main() -> None:
 66    """Lease, release, reuse and trim pooled objects, then tear the root down.
 67
 68    Contract:
 69        Every assertion checks an observable outcome: object identity, the pool's
 70        counts from describe(), or the disposal flag. The conduit and the book are
 71        cleaned in finally blocks.
 72    Returns:
 73        None.
 74    """
 75    book = md.Spellbook()
 76    try:
 77        book.bind(
 78            spell=DatabaseConnection,
 79            existence=md.Existence.managed_spell_quantity,
 80            disposal_method_names=["close"],
 81        )
 82        book.bind(
 83            spell=ScratchBuffer,
 84            existence=md.Existence.managed_spell_quantity,
 85            managed_spell_mode=md.ManagedSpellMode.elastic,
 86            managed_spell_limit=2,
 87            disposal_method_names=["close"],
 88        )
 89        conduit = book.conjure()
 90        # Bind the release once: it is the one way back for every managed object.
 91        release = md.ReleaseManagedSpell().release
 92        try:
 93            # The pool exists from conjure on, empty, with the default elastic policy.
 94            (snapshot,) = md.ReleaseManagedSpell().describe(DatabaseConnection)
 95            assert snapshot["mode"] == "elastic" and snapshot["limit"] == 256
 96            assert pool_counts(DatabaseConnection) == (0, 0, 0)
 97            assert not conduit.has_live_creation("DatabaseConnection")
 98            print("pool ready at conjure:", snapshot["mode"], "limit", snapshot["limit"])
 99
100            # Nothing is idle yet, so each meld builds a connection and leases it out.
101            first: DatabaseConnection = conduit.meld("DatabaseConnection")
102            second: DatabaseConnection = conduit.meld("DatabaseConnection")
103            assert first is not second
104            assert pool_counts(DatabaseConnection) == (2, 0, 2)
105            assert conduit.has_live_creation("DatabaseConnection")
106            print("two connections leased (alive, idle, out):", pool_counts(DatabaseConnection))
107
108            # Give one back: it becomes idle, still open, and the next meld reuses it.
109            first.queries += 1
110            release(first)
111            assert pool_counts(DatabaseConnection) == (2, 1, 1) and not first.closed
112            reused: DatabaseConnection = conduit.meld("DatabaseConnection")
113            assert reused is first and reused.queries == 1
114            print("the released connection came back on the next meld:", reused is first)
115
116            # The newest released object is leased first.
117            release(second)
118            release(reused)
119            newest: DatabaseConnection = conduit.meld("DatabaseConnection")
120            assert newest is reused
121            release(newest)
122            assert pool_counts(DatabaseConnection) == (2, 2, 0)
123            print("newest released leased first; all back (alive, idle, out):", pool_counts(DatabaseConnection))
124
125            # Elastic never refuses: with limit 2 a third buffer is still built...
126            buffers = [conduit.meld("ScratchBuffer") for _ in range(3)]
127            assert pool_counts(ScratchBuffer) == (3, 0, 3)
128            # ...but only 2 stay idle: the third release destroys the oldest idle buffer.
129            for buffer in buffers:
130                release(buffer)
131            assert [buffer.closed for buffer in buffers] == [True, False, False]
132            assert pool_counts(ScratchBuffer) == (2, 2, 0)
133            print("limit 2 keeps 2 idle buffers; the oldest was closed:", buffers[0].closed)
134        finally:
135            conduit.cleanup()
136
137        # Root teardown disposes what the pools hold and unregisters them.
138        assert first.closed and second.closed
139        assert md.ReleaseManagedSpell().describe(DatabaseConnection) == ()
140        print("root teardown closed the idle connections:", first.closed and second.closed)
141    finally:
142        book.cleanup()
143
144
145if __name__ == "__main__":
146    main()

Check the outcome๏ƒ

The script contains its own assertions or demonstrated refusal paths. Run it to evaluate those checks against your installed version. The code above is taken directly from the saved file; no run output is invented here.

More intermediate examples ยท Level guide

API contracts๏ƒ