Skip to content

Assigner

Leon Starr edited this page Jul 24, 2026 · 4 revisions

An assigner state model arbitrates competition for instances across a relationship. Rather than belonging to any one instance, it belongs to the relationship itself. See Lifecycle vs Assigner for when you need one.

The declaration line looks like this:

relationship R53 / Shaft

And the grammar is:

assigner = "relationship" SP rnum SP '/' SP name? EOL*
rnum = r'O?R[1-9][0-9]*' // Relationship number

Reading it left to right: the keyword relationship, one space, the relationship number, one space, a slash, one space, and then an optional partitioning class name.

Single vs multiple assigners

That optional name at the end is what distinguishes the two flavors of assigner.

A single assigner has one state machine refereeing the entire relationship for the whole domain. Leave the name off:

relationship R23 / ⎵

⚠️ That is not part of the syntax — it's standing in for a character you can't see. The grammar asks for a space on both sides of the slash (SP '/' SP name?), and only the trailing name is optional. So a single assigner line really does end with a space after the /, and if your editor trims trailing whitespace on save the file will stop parsing with Expected SP. Yes, this is a wart.

A multiple assigner partitions the competition, giving you one independent state machine per instance of some partitioning class. Name that class after the slash:

relationship R53 / Shaft

Here the competition for a Cabin is resolved separately within each Shaft, since the floors served by one shaft never compete for a cabin running in a different shaft. That's a far more scalable arrangement than one referee for the whole building, and it's the usual reason to reach for a partitioning class.

What the parser gives you

The relationship number lands in the assigner_rnum field of the StateModel_a named tuple and the partitioning class, if any, in assigner_pclass. For the R53 example above you get assigner_rnum='R53' and assigner_pclass='Shaft'. A single assigner leaves assigner_pclass set to None. Either way the lifecycle field is None.

In context

From the R53 assigner, with the metadata omitted:

domain Elevator Management
relationship R53 / Shaft
events
    Service requested
    No destination
    Transfer created
    Transfer completed
    Dest change evaluated
--
state NO TRANSFER
activity
    // Waiting for service request
transitions
    Service requested > Search for new destination
--

Apart from that second line, this is written exactly like a Lifecycle.

Clone this wiki locally